1 /*
2 * Copyright (c) 2021 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/partial_gc.h"
17
18 #include "ecmascript/mem/concurrent_marker.h"
19 #include "ecmascript/mem/incremental_marker.h"
20 #include "ecmascript/mem/parallel_evacuator.h"
21 #include "ecmascript/mem/parallel_marker.h"
22 #include "ecmascript/mem/old_gc_visitor-inl.h"
23 #include "ecmascript/mem/young_gc_visitor-inl.h"
24 #include "ecmascript/runtime_call_id.h"
25 #include "ecmascript/mem/verification.h"
26
27 namespace panda::ecmascript {
PartialGC(Heap * heap)28 PartialGC::PartialGC(Heap *heap) : heap_(heap), workManager_(heap->GetWorkManager()) {}
29
RunPhases()30 void PartialGC::RunPhases()
31 {
32 GCStats *gcStats = heap_->GetEcmaVM()->GetEcmaGCStats();
33 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::RunPhases" + std::to_string(heap_->IsConcurrentFullMark())
34 + ";Reason" + std::to_string(static_cast<int>(gcStats->GetGCReason()))
35 + ";Sensitive" + std::to_string(static_cast<int>(heap_->GetSensitiveStatus()))
36 + ";IsInBackground" + std::to_string(heap_->IsInBackground())
37 + ";Startup" + std::to_string(static_cast<int>(heap_->GetStartupStatus()))
38 + ";ConMark" + std::to_string(static_cast<int>(heap_->GetJSThread()->GetMarkStatus()))
39 + ";Young" + std::to_string(heap_->GetNewSpace()->GetCommittedSize())
40 + ";Old" + std::to_string(heap_->GetOldSpace()->GetCommittedSize())
41 + ";TotalCommit" + std::to_string(heap_->GetCommittedSize())
42 + ";NativeBindingSize" + std::to_string(heap_->GetNativeBindingSize())
43 + ";NativeLimitSize" + std::to_string(heap_->GetGlobalSpaceNativeLimit()));
44 TRACE_GC(GCStats::Scope::ScopeId::TotalGC, gcStats);
45 MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), PartialGC_RunPhases);
46 bool mainThreadInForeground = heap_->GetJSThread()->IsMainThreadFast() && !heap_->IsInBackground();
47 bool needAjustGCThreadPrio = heap_->GetGCType() == TriggerGCType::OLD_GC ||
48 heap_->GetNewSpace()->GetCommittedSize() >= heap_->GetNewSpace()->GetMaximumCapacity();
49 if (mainThreadInForeground && needAjustGCThreadPrio) {
50 Taskpool::GetCurrentTaskpool()->SetThreadPriority(PriorityMode::STW);
51 }
52 markingInProgress_ = heap_->CheckOngoingConcurrentMarking();
53 LOG_GC(DEBUG) << "markingInProgress_" << markingInProgress_;
54 Initialize();
55 Mark();
56 if (UNLIKELY(heap_->ShouldVerifyHeap())) {
57 Verification::VerifyMark(heap_);
58 }
59 ProcessSharedGCRSetWorkList();
60 Sweep();
61 Evacuate();
62 if (heap_->IsConcurrentFullMark()) {
63 heap_->GetSweeper()->PostTask();
64 }
65 if (UNLIKELY(heap_->ShouldVerifyHeap())) {
66 Verification::VerifyEvacuate(heap_);
67 }
68 Finish();
69 if (mainThreadInForeground && needAjustGCThreadPrio) {
70 Taskpool::GetCurrentTaskpool()->SetThreadPriority(PriorityMode::FOREGROUND);
71 }
72 }
73
Initialize()74 void PartialGC::Initialize()
75 {
76 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Initialize");
77 TRACE_GC(GCStats::Scope::ScopeId::Initialize, heap_->GetEcmaVM()->GetEcmaGCStats());
78 if (!markingInProgress_ && !heap_->GetIncrementalMarker()->IsTriggeredIncrementalMark()) {
79 LOG_GC(DEBUG) << "No ongoing Concurrent marking. Initializing...";
80 heap_->Prepare();
81 if (heap_->IsConcurrentFullMark()) {
82 heap_->GetOldSpace()->SelectCSet();
83 heap_->GetAppSpawnSpace()->EnumerateRegions([](Region *current) {
84 current->ClearMarkGCBitset();
85 current->ClearCrossRegionRSet();
86 });
87 heap_->EnumerateNonNewSpaceRegions([](Region *current) {
88 current->ResetAliveObject();
89 });
90 }
91 workManager_->Initialize(TriggerGCType::OLD_GC, ParallelGCTaskPhase::OLD_HANDLE_GLOBAL_POOL_TASK);
92
93 freeSize_ = 0;
94 hugeSpaceFreeSize_ = 0;
95 oldSpaceCommitSize_ = heap_->GetOldSpace()->GetCommittedSize();
96 nonMoveSpaceCommitSize_ = heap_->GetNonMovableSpace()->GetCommittedSize();
97 }
98 }
99
Finish()100 void PartialGC::Finish()
101 {
102 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Finish");
103 TRACE_GC(GCStats::Scope::ScopeId::Finish, heap_->GetEcmaVM()->GetEcmaGCStats());
104 heap_->Resume(OLD_GC);
105 if (heap_->GetIncrementalMarker()->IsTriggeredIncrementalMark()) {
106 heap_->GetIncrementalMarker()->Reset();
107 } else if (markingInProgress_) {
108 auto marker = heap_->GetConcurrentMarker();
109 marker->Reset(false);
110 } else {
111 workManager_->Finish();
112 }
113 if (heap_->IsConcurrentFullMark()) {
114 heap_->GetSweeper()->TryFillSweptRegion();
115 heap_->SetFullMarkRequestedState(false);
116 }
117 if (heap_->IsNearGCInSensitive()) {
118 heap_->SetNearGCInSensitive(false);
119 }
120 }
121
MarkRoots()122 void PartialGC::MarkRoots()
123 {
124 if (heap_->IsYoungMark()) {
125 YoungGCMarkRootVisitor youngGCMarkRootVisitor(workManager_->GetWorkNodeHolder(MAIN_THREAD_INDEX));
126 heap_->GetNonMovableMarker()->MarkRoots(youngGCMarkRootVisitor);
127 } else {
128 OldGCMarkRootVisitor oldGCMarkRootVisitor(workManager_->GetWorkNodeHolder(MAIN_THREAD_INDEX));
129 heap_->GetNonMovableMarker()->MarkRoots(oldGCMarkRootVisitor);
130 }
131 }
132
Mark()133 void PartialGC::Mark()
134 {
135 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Mark");
136 TRACE_GC(GCStats::Scope::ScopeId::Mark, heap_->GetEcmaVM()->GetEcmaGCStats());
137 if (markingInProgress_) {
138 heap_->GetConcurrentMarker()->ReMark();
139 return;
140 }
141 MarkRoots();
142 workManager_->GetWorkNodeHolder(MAIN_THREAD_INDEX)->PushWorkNodeToGlobal(false);
143 if (heap_->IsConcurrentFullMark()) {
144 heap_->GetNonMovableMarker()->ProcessMarkStack(MAIN_THREAD_INDEX);
145 } else if (heap_->IsYoungMark()) {
146 NonMovableMarker *marker = static_cast<NonMovableMarker*>(heap_->GetNonMovableMarker());
147 {
148 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "GC::ProcessOldToNew");
149 marker->ProcessOldToNew(MAIN_THREAD_INDEX);
150 }
151 marker->ProcessSnapshotRSet(MAIN_THREAD_INDEX);
152 }
153 heap_->WaitRunningTaskFinished();
154 // MarkJitCodeMap must be call after other mark work finish to make sure which jserror object js alive.
155 heap_->GetNonMovableMarker()->MarkJitCodeMap(MAIN_THREAD_INDEX);
156 }
157
Sweep()158 void PartialGC::Sweep()
159 {
160 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Sweep");
161 ProcessNativeDelete();
162 if (heap_->IsConcurrentFullMark()) {
163 heap_->GetOldSpace()->EnumerateRegions([](Region *current) {
164 current->SetRegionAliveSize();
165 });
166 TRACE_GC(GCStats::Scope::ScopeId::Sweep, heap_->GetEcmaVM()->GetEcmaGCStats());
167 heap_->GetSweeper()->Sweep();
168 }
169 }
170
ProcessNativeDelete()171 void PartialGC::ProcessNativeDelete()
172 {
173 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "GC::ProcessNativeDelete");
174 TRACE_GC(GCStats::Scope::ScopeId::ClearNativeObject, heap_->GetEcmaVM()->GetEcmaGCStats());
175 WeakRootVisitor gcUpdateWeak = [this](TaggedObject *header) -> TaggedObject* {
176 Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(header));
177 ASSERT(!objectRegion->InSharedHeap());
178 if (!objectRegion->InYoungSpaceOrCSet() && heap_->IsYoungMark()) {
179 return header;
180 }
181 if (!objectRegion->Test(header)) {
182 return nullptr;
183 }
184 return header;
185 };
186 heap_->GetEcmaVM()->ProcessNativeDelete(gcUpdateWeak);
187 }
188
Evacuate()189 void PartialGC::Evacuate()
190 {
191 ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "PartialGC::Evacuate");
192 TRACE_GC(GCStats::Scope::ScopeId::Evacuate, heap_->GetEcmaVM()->GetEcmaGCStats());
193 heap_->GetEvacuator()->Evacuate();
194 }
195
ProcessSharedGCRSetWorkList()196 ARK_INLINE void PartialGC::ProcessSharedGCRSetWorkList()
197 {
198 TRACE_GC(GCStats::Scope::ScopeId::ProcessSharedGCRSetWorkList, heap_->GetEcmaVM()->GetEcmaGCStats());
199 heap_->ProcessSharedGCRSetWorkList();
200 }
201 } // namespace panda::ecmascript
202