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_marker-inl.h"
21 #include "ecmascript/mem/verification.h"
22 #include "ecmascript/runtime.h"
23
24 namespace panda::ecmascript {
RunPhases()25 void SharedGC::RunPhases()
26 {
27 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::RunPhases"
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(sHeap_->OnStartupEvent())
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 TRACE_GC(GCStats::Scope::ScopeId::TotalGC, sHeap_->GetEcmaGCStats());
37 markingInProgress_ = sHeap_->CheckOngoingConcurrentMarking();
38 Initialize();
39 Mark();
40 if (UNLIKELY(sHeap_->ShouldVerifyHeap())) {
41 // verify mark
42 LOG_ECMA(DEBUG) << "start verify mark";
43 SharedHeapVerification(sHeap_, VerifyKind::VERIFY_SHARED_GC_MARK).VerifyMark(markingInProgress_);
44 }
45 Sweep();
46 if (UNLIKELY(sHeap_->ShouldVerifyHeap())) {
47 // verify sweep
48 LOG_ECMA(DEBUG) << "start verify sweep";
49 SharedHeapVerification(sHeap_, VerifyKind::VERIFY_SHARED_GC_SWEEP).VerifySweep(markingInProgress_);
50 }
51 Finish();
52 sHeap_->ResetNativeSizeAfterLastGC();
53 }
54
Initialize()55 void SharedGC::Initialize()
56 {
57 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Initialize");
58 TRACE_GC(GCStats::Scope::ScopeId::Initialize, sHeap_->GetEcmaGCStats());
59 if (!markingInProgress_) {
60 sHeap_->Prepare(true);
61 sHeap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
62 current->ClearMarkGCBitset();
63 });
64 sHeap_->EnumerateOldSpaceRegions([](Region *current) {
65 ASSERT(current->InSharedSweepableSpace());
66 current->ResetAliveObject();
67 });
68 sWorkManager_->Initialize(TriggerGCType::SHARED_GC, SharedParallelMarkPhase::SHARED_MARK_TASK);
69 }
70 }
Mark()71 void SharedGC::Mark()
72 {
73 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Mark");
74 TRACE_GC(GCStats::Scope::ScopeId::Mark, sHeap_->GetEcmaGCStats());
75 if (markingInProgress_) {
76 sHeap_->GetConcurrentMarker()->ReMark();
77 return;
78 }
79 SharedGCMarker *marker = sHeap_->GetSharedGCMarker();
80 marker->MarkRoots(DAEMON_THREAD_INDEX, SharedMarkType::NOT_CONCURRENT_MARK);
81 marker->DoMark<SharedMarkType::NOT_CONCURRENT_MARK>(DAEMON_THREAD_INDEX);
82 marker->MergeBackAndResetRSetWorkListHandler();
83 sHeap_->WaitRunningTaskFinished();
84 }
85
Sweep()86 void SharedGC::Sweep()
87 {
88 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Sweep");
89 TRACE_GC(GCStats::Scope::ScopeId::Sweep, sHeap_->GetEcmaGCStats());
90 UpdateRecordWeakReference();
91 WeakRootVisitor gcUpdateWeak = [](TaggedObject *header) -> TaggedObject* {
92 Region *objectRegion = Region::ObjectAddressToRange(header);
93 if (UNLIKELY(objectRegion == nullptr)) {
94 LOG_GC(ERROR) << "SharedGC updateWeakReference: region is nullptr, header is " << header;
95 return nullptr;
96 }
97 if (!objectRegion->InSharedSweepableSpace() || objectRegion->Test(header)) {
98 return header;
99 }
100 return nullptr;
101 };
102 auto stringTableCleaner = Runtime::GetInstance()->GetEcmaStringTable()->GetCleaner();
103 stringTableCleaner->PostSweepWeakRefTask(gcUpdateWeak);
104 Runtime::GetInstance()->ProcessNativeDeleteInSharedGC(gcUpdateWeak);
105 Runtime::GetInstance()->ProcessSharedNativeDelete(gcUpdateWeak);
106
107 Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
108 ASSERT(!thread->IsInRunningState());
109 thread->IterateWeakEcmaGlobalStorage(gcUpdateWeak, GCKind::SHARED_GC);
110 const_cast<Heap*>(thread->GetEcmaVM()->GetHeap())->ResetTlab();
111 });
112
113 stringTableCleaner->JoinAndWaitSweepWeakRefTask(gcUpdateWeak);
114 sHeap_->GetSweeper()->Sweep(false);
115 sHeap_->GetSweeper()->PostTask(false);
116 }
117
Finish()118 void SharedGC::Finish()
119 {
120 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Finish");
121 TRACE_GC(GCStats::Scope::ScopeId::Finish, sHeap_->GetEcmaGCStats());
122 sHeap_->Reclaim(TriggerGCType::SHARED_GC);
123 if (markingInProgress_) {
124 sHeap_->GetConcurrentMarker()->Reset(false);
125 } else {
126 sWorkManager_->Finish();
127 }
128 sHeap_->GetSweeper()->TryFillSweptRegion();
129 }
130
UpdateRecordWeakReference()131 void SharedGC::UpdateRecordWeakReference()
132 {
133 auto totalThreadCount = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum() + 1;
134 for (uint32_t i = 0; i < totalThreadCount; i++) {
135 ProcessQueue *queue = sHeap_->GetWorkManager()->GetWeakReferenceQueue(i);
136
137 while (true) {
138 auto obj = queue->PopBack();
139 if (UNLIKELY(obj == nullptr)) {
140 break;
141 }
142 ObjectSlot slot(ToUintPtr(obj));
143 JSTaggedValue value(slot.GetTaggedType());
144 if (value.IsWeak()) {
145 auto header = value.GetTaggedWeakRef();
146 Region *objectRegion = Region::ObjectAddressToRange(header);
147 if (!objectRegion->Test(header)) {
148 slot.Clear();
149 }
150 }
151 }
152 }
153 }
154
ResetWorkManager(SharedGCWorkManager *sWorkManager)155 void SharedGC::ResetWorkManager(SharedGCWorkManager *sWorkManager)
156 {
157 sWorkManager_ = sWorkManager;
158 }
159 } // namespace panda::ecmascript
160