• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/mem/shared_heap/shared_full_gc.h"
17 
18 #include "common_components/taskpool/taskpool.h"
19 #include "ecmascript/mem/shared_heap/shared_concurrent_marker.h"
20 #include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h"
21 #include "ecmascript/mem/shared_heap/shared_gc_marker-inl.h"
22 
23 namespace panda::ecmascript {
RunPhases()24 void SharedFullGC::RunPhases()
25 {
26     ASSERT("SharedFullGC should be disabled" && !g_isEnableCMCGC);
27     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, ("SharedFullGC::RunPhases;GCReason"
28         + std::to_string(static_cast<int>(sHeap_->GetEcmaGCStats()->GetGCReason()))
29         + ";Sensitive" + std::to_string(static_cast<int>(sHeap_->GetSensitiveStatus()))
30         + ";IsInBackground" + std::to_string(sHeap_->IsInBackground())
31         + ";Startup" + std::to_string(static_cast<int>(sHeap_->GetStartupStatus()))
32         + ";Old" + std::to_string(sHeap_->GetOldSpace()->GetCommittedSize())
33         + ";huge" + std::to_string(sHeap_->GetHugeObjectSpace()->GetCommittedSize())
34         + ";NonMov" + std::to_string(sHeap_->GetNonMovableSpace()->GetCommittedSize())
35         + ";TotCommit" + std::to_string(sHeap_->GetCommittedSize())
36         + ";NativeBindingSize" + std::to_string(sHeap_->GetNativeSizeAfterLastGC())
37         + ";NativeLimitGC" + std::to_string(sHeap_->GetNativeSizeTriggerSharedGC())
38         + ";NativeLimitCM" + std::to_string(sHeap_->GetNativeSizeTriggerSharedCM())).c_str(), "");
39     TRACE_GC(GCStats::Scope::ScopeId::TotalGC, sHeap_->GetEcmaGCStats());
40     sHeap_->SetGCThreadQosPriority(common::PriorityMode::STW);
41     Initialize();
42     Mark();
43     Sweep();
44     Finish();
45     sHeap_->SetGCThreadQosPriority(common::PriorityMode::FOREGROUND);
46 }
47 
Initialize()48 void SharedFullGC::Initialize()
49 {
50     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedFullGC::Initialize", "");
51     TRACE_GC(GCStats::Scope::ScopeId::Initialize, sHeap_->GetEcmaGCStats());
52     sHeap_->Prepare(true);
53     if (UNLIKELY(sHeap_->CheckOngoingConcurrentMarking())) {
54         // Concurrent shared mark should always trigger shared gc without moving.
55         sHeap_->GetConcurrentMarker()->Reset(true);
56     }
57     sHeap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
58         current->ClearMarkGCBitset();
59         current->ClearCrossRegionRSet();
60     });
61     sHeap_->EnumerateOldSpaceRegions([](Region *current) {
62         ASSERT(current->InSharedSweepableSpace());
63         current->ResetAliveObject();
64     });
65     sWorkManager_->Initialize(TriggerGCType::SHARED_FULL_GC, SharedParallelMarkPhase::SHARED_COMPRESS_TASK);
66 }
67 
MarkRoots(SharedMarkType markType)68 void SharedFullGC::MarkRoots(SharedMarkType markType)
69 {
70     SharedGCMovableMarker *marker = static_cast<SharedGCMovableMarker*>(sHeap_->GetSharedGCMovableMarker());
71     SharedFullGCMarkRootVisitor sharedFullGCMarkRootVisitor(marker, DAEMON_THREAD_INDEX);
72     marker->MarkRoots(sharedFullGCMarkRootVisitor, markType);
73 }
74 
Mark()75 void SharedFullGC::Mark()
76 {
77     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedFullGC::Mark", "");
78     TRACE_GC(GCStats::Scope::ScopeId::Mark, sHeap_->GetEcmaGCStats());
79     SharedGCMovableMarker *marker = sHeap_->GetSharedGCMovableMarker();
80 
81     MarkRoots(SharedMarkType::NOT_CONCURRENT_MARK);
82     marker->DoMark<SharedMarkType::NOT_CONCURRENT_MARK>(DAEMON_THREAD_INDEX);
83     marker->MergeBackAndResetRSetWorkListHandler();
84     sHeap_->WaitRunningTaskFinished();
85 }
86 
Sweep()87 void SharedFullGC::Sweep()
88 {
89     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedFullGC::Sweep", "");
90     TRACE_GC(GCStats::Scope::ScopeId::Sweep, sHeap_->GetEcmaGCStats());
91     UpdateRecordWeakReference();
92     WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) {
93         Region *objectRegion = Region::ObjectAddressToRange(header);
94         if (!objectRegion) {
95             LOG_GC(ERROR) << "SharedFullGC updateWeakReference: region is nullptr, header is " << header;
96             return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
97         }
98         if (objectRegion->InSharedOldSpace()) {
99             MarkWord markWord(header);
100             if (markWord.IsForwardingAddress()) {
101                 return markWord.ToForwardingAddress();
102             }
103             return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
104         }
105         if (!objectRegion->InSharedSweepableSpace() || objectRegion->Test(header)) {
106             return header;
107         }
108         return reinterpret_cast<TaggedObject *>(ToUintPtr(nullptr));
109     };
110     auto stringTableCleaner = Runtime::GetInstance()->GetEcmaStringTable()->GetCleaner();
111     stringTableCleaner->PostSweepWeakRefTask(gcUpdateWeak);
112     Runtime::GetInstance()->ProcessNativeDeleteInSharedGC(gcUpdateWeak);
113     Runtime::GetInstance()->ProcessSharedNativeDelete(gcUpdateWeak);
114 
115     Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
116         ASSERT(!thread->IsInRunningState());
117         thread->IterateWeakEcmaGlobalStorage(gcUpdateWeak, GCKind::SHARED_GC);
118         thread->GetEcmaVM()->ProcessSnapShotEnv(gcUpdateWeak);
119         const_cast<Heap*>(thread->GetEcmaVM()->GetHeap())->ResetTlab();
120         thread->ClearVMCachedConstantPool();
121     });
122 
123     stringTableCleaner->JoinAndWaitSweepWeakRefTask(gcUpdateWeak);
124     sHeap_->GetSweeper()->Sweep(true);
125     sHeap_->GetSweeper()->PostTask(true);
126 }
127 
Finish()128 void SharedFullGC::Finish()
129 {
130     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedFullGC::Finish", "");
131     TRACE_GC(GCStats::Scope::ScopeId::Finish, sHeap_->GetEcmaGCStats());
132     sHeap_->SwapOldSpace();
133     sWorkManager_->Finish();
134     if (!isAppspawn_) {
135         sHeap_->Reclaim(TriggerGCType::SHARED_FULL_GC);
136     } else {
137         sHeap_->ReclaimForAppSpawn();
138     }
139 
140     sHeap_->GetSweeper()->TryFillSweptRegion();
141 }
142 
UpdateRecordWeakReference()143 void SharedFullGC::UpdateRecordWeakReference()
144 {
145     auto totalThreadCount = common::Taskpool::GetCurrentTaskpool()->GetTotalThreadNum() + 1;
146     for (uint32_t i = 0; i < totalThreadCount; i++) {
147         ProcessQueue *queue = sHeap_->GetWorkManager()->GetWeakReferenceQueue(i);
148 
149         while (true) {
150             auto obj = queue->PopBack();
151             if (UNLIKELY(obj == nullptr)) {
152                 break;
153             }
154             ObjectSlot slot(ToUintPtr(obj));
155             JSTaggedValue value(slot.GetTaggedType());
156             ASSERT(value.IsWeak());
157             auto header = value.GetTaggedWeakRef();
158             Region *objectRegion = Region::ObjectAddressToRange(header);
159             if (!objectRegion->InSharedOldSpace()) {
160                 if (!objectRegion->Test(header)) {
161                     slot.Clear();
162                 }
163             } else {
164                 MarkWord markWord(header);
165                 if (markWord.IsForwardingAddress()) {
166                     TaggedObject *dst = markWord.ToForwardingAddress();
167                     auto weakRef = JSTaggedValue(JSTaggedValue(dst).CreateAndGetWeakRef()).GetRawTaggedObject();
168                     slot.Update(weakRef);
169                 } else {
170                     slot.Clear();
171                 }
172             }
173         }
174     }
175 }
176 
HasEvacuated(Region * region)177 bool SharedFullGC::HasEvacuated(Region *region)
178 {
179     auto marker = reinterpret_cast<SharedGCMovableMarker *>(sHeap_->GetSharedGCMovableMarker());
180     return marker->NeedEvacuate(region);
181 }
182 
ResetWorkManager(SharedGCWorkManager * sWorkManager)183 void SharedFullGC::ResetWorkManager(SharedGCWorkManager *sWorkManager)
184 {
185     sWorkManager_ = sWorkManager;
186 }
187 }  // namespace panda::ecmascript
188