• 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 "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