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