• 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_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_evacuator.h"
22 #include "ecmascript/mem/shared_heap/shared_gc_marker-inl.h"
23 #include "ecmascript/mem/shared_heap/shared_gc_visitor-inl.h"
24 #include "ecmascript/mem/verification.h"
25 
26 namespace panda::ecmascript {
RunPhases()27 void SharedGC::RunPhases()
28 {
29     ASSERT("SharedGC should be disabled" && !g_isEnableCMCGC);
30     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, ("SharedGC::RunPhases;GCReason"
31         + std::to_string(static_cast<int>(sHeap_->GetEcmaGCStats()->GetGCReason()))
32         + ";MarkReason" + std::to_string(static_cast<int>(sHeap_->GetEcmaGCStats()->GetMarkReason()))
33         + ";Sensitive" + std::to_string(static_cast<int>(sHeap_->GetSensitiveStatus()))
34         + ";IsInBackground" + std::to_string(sHeap_->IsInBackground())
35         + ";Startup" + std::to_string(static_cast<int>(sHeap_->GetStartupStatus()))
36         + ";Old" + std::to_string(sHeap_->GetOldSpace()->GetCommittedSize())
37         + ";huge" + std::to_string(sHeap_->GetHugeObjectSpace()->GetCommittedSize())
38         + ";NonMov" + std::to_string(sHeap_->GetNonMovableSpace()->GetCommittedSize())
39         + ";TotCommit" + std::to_string(sHeap_->GetCommittedSize())
40         + ";NativeBindingSize" + std::to_string(sHeap_->GetNativeSizeAfterLastGC())
41         + ";NativeLimitGC" + std::to_string(sHeap_->GetNativeSizeTriggerSharedGC())
42         + ";NativeLimitCM" + std::to_string(sHeap_->GetNativeSizeTriggerSharedCM())).c_str(), "");
43     TRACE_GC(GCStats::Scope::ScopeId::TotalGC, sHeap_->GetEcmaGCStats());
44     sHeap_->SetGCThreadQosPriority(common::PriorityMode::STW);
45     markingInProgress_ = sHeap_->CheckOngoingConcurrentMarking();
46     Initialize();
47     Mark();
48     if (UNLIKELY(sHeap_->ShouldVerifyHeap())) {
49         // verify mark
50         LOG_ECMA(DEBUG) << "start verify mark";
51         SharedHeapVerification(sHeap_, VerifyKind::VERIFY_SHARED_GC_MARK).VerifyMark(markingInProgress_);
52     }
53     PreSweep();
54     Evacuate();
55     Sweep();
56     if (UNLIKELY(sHeap_->ShouldVerifyHeap())) {
57         // verify sweep
58         LOG_ECMA(DEBUG) << "start verify sweep";
59         SharedHeapVerification(sHeap_, VerifyKind::VERIFY_SHARED_GC_SWEEP).VerifySweep(markingInProgress_);
60     }
61     Finish();
62     sHeap_->SetGCThreadQosPriority(common::PriorityMode::FOREGROUND);
63     sHeap_->ResetNativeSizeAfterLastGC();
64 }
65 
Initialize()66 void SharedGC::Initialize()
67 {
68     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGC::Initialize", "");
69     TRACE_GC(GCStats::Scope::ScopeId::Initialize, sHeap_->GetEcmaGCStats());
70     if (!markingInProgress_) {
71         sHeap_->Prepare(true);
72         sHeap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
73             current->ClearMarkGCBitset();
74             current->ClearCrossRegionRSet();
75         });
76         sHeap_->EnumerateOldSpaceRegions([](Region *current) {
77             ASSERT(current->InSharedSweepableSpace());
78             current->ResetAliveObject();
79         });
80         sWorkManager_->Initialize(TriggerGCType::SHARED_GC, SharedParallelMarkPhase::SHARED_MARK_TASK);
81     }
82 }
83 
MarkRoots(SharedMarkType markType)84 void SharedGC::MarkRoots(SharedMarkType markType)
85 {
86     SharedGCMarkRootVisitor sharedGCMarkRootVisitor(sWorkManager_, DAEMON_THREAD_INDEX);
87     sHeap_->GetSharedGCMarker()->MarkRoots(sharedGCMarkRootVisitor, markType);
88 }
89 
Mark()90 void SharedGC::Mark()
91 {
92     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGC::Mark", "");
93     TRACE_GC(GCStats::Scope::ScopeId::Mark, sHeap_->GetEcmaGCStats());
94     if (markingInProgress_) {
95         sHeap_->GetConcurrentMarker()->ReMark();
96         return;
97     }
98     SharedGCMarker *marker = sHeap_->GetSharedGCMarker();
99     MarkRoots(SharedMarkType::NOT_CONCURRENT_MARK);
100     marker->DoMark<SharedMarkType::NOT_CONCURRENT_MARK>(DAEMON_THREAD_INDEX);
101     marker->MergeBackAndResetRSetWorkListHandler();
102     sHeap_->WaitRunningTaskFinished();
103 }
PreSweep()104 void SharedGC::PreSweep()
105 {
106     sHeap_->GetSweeper()->Sweep(false);
107     UpdateRecordWeakReference();
108 }
109 
Evacuate()110 void SharedGC::Evacuate()
111 {
112     if (sHeap_->HasCSetRegions()) {
113         sHeap_->GetSharedGCEvacuator()->Evacuate();
114     }
115 }
116 
Sweep()117 void SharedGC::Sweep()
118 {
119     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGC::Sweep", "");
120     TRACE_GC(GCStats::Scope::ScopeId::Sweep, sHeap_->GetEcmaGCStats());
121     WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) -> TaggedObject* {
122         Region *objectRegion = Region::ObjectAddressToRange(header);
123         if (UNLIKELY(objectRegion == nullptr)) {
124             LOG_GC(ERROR) << "SharedGC updateWeakReference: region is nullptr, header is " << header;
125             return nullptr;
126         }
127         if (!objectRegion->InSharedSweepableSpace()) {
128             return header;
129         }
130         if (objectRegion->InSCollectSet()) {
131             MarkWord markWord(header);
132             if (markWord.IsForwardingAddress()) {
133                 return markWord.ToForwardingAddress();
134             }
135             return nullptr;
136         }
137         if (objectRegion->Test(header)) {
138             return header;
139         }
140         return nullptr;
141     };
142     auto stringTableCleaner = Runtime::GetInstance()->GetEcmaStringTable()->GetCleaner();
143     stringTableCleaner->PostSweepWeakRefTask(gcUpdateWeak);
144     Runtime::GetInstance()->ProcessNativeDeleteInSharedGC(gcUpdateWeak);
145     Runtime::GetInstance()->ProcessSharedNativeDelete(gcUpdateWeak);
146     bool needClearCache = sHeap_->HasCSetRegions();
147     Runtime::GetInstance()->GCIterateThreadList([&gcUpdateWeak, needClearCache](JSThread *thread) {
148         ASSERT(!thread->IsInRunningState());
149         thread->IterateWeakEcmaGlobalStorage(gcUpdateWeak, GCKind::SHARED_GC);
150         thread->GetEcmaVM()->ProcessSnapShotEnv(gcUpdateWeak);
151         const_cast<Heap*>(thread->GetEcmaVM()->GetHeap())->ResetTlab();
152         if (needClearCache) {
153             thread->ClearVMCachedConstantPool();
154         }
155     });
156 
157     stringTableCleaner->JoinAndWaitSweepWeakRefTask(gcUpdateWeak);
158     sHeap_->GetSweeper()->PostTask(false);
159 }
160 
Finish()161 void SharedGC::Finish()
162 {
163     ECMA_BYTRACE_NAME(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, "SharedGC::Finish", "");
164     TRACE_GC(GCStats::Scope::ScopeId::Finish, sHeap_->GetEcmaGCStats());
165     sHeap_->Reclaim(TriggerGCType::SHARED_GC);
166     if (markingInProgress_) {
167         sHeap_->GetConcurrentMarker()->Reset(false);
168     } else {
169         sWorkManager_->Finish();
170     }
171     sHeap_->GetSweeper()->TryFillSweptRegion();
172 }
173 
UpdateRecordWeakReference()174 void SharedGC::UpdateRecordWeakReference()
175 {
176     auto totalThreadCount = common::Taskpool::GetCurrentTaskpool()->GetTotalThreadNum() + 1;
177     for (uint32_t i = 0; i < totalThreadCount; i++) {
178         ProcessQueue *queue = sHeap_->GetWorkManager()->GetWeakReferenceQueue(i);
179 
180         while (true) {
181             auto obj = queue->PopBack();
182             if (UNLIKELY(obj == nullptr)) {
183                 break;
184             }
185             ObjectSlot slot(ToUintPtr(obj));
186             JSTaggedValue value(slot.GetTaggedType());
187             if (value.IsWeak()) {
188                 auto header = value.GetTaggedWeakRef();
189                 Region *objectRegion = Region::ObjectAddressToRange(header);
190                 if (!objectRegion->Test(header)) {
191                     slot.Clear();
192                 }
193             }
194         }
195     }
196 }
197 
ResetWorkManager(SharedGCWorkManager * sWorkManager)198 void SharedGC::ResetWorkManager(SharedGCWorkManager *sWorkManager)
199 {
200     sWorkManager_ = sWorkManager;
201 }
202 }  // namespace panda::ecmascript
203