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