• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 "runtime/mem/gc/stw-gc/stw-gc.h"
17 
18 #include "libpandabase/trace/trace.h"
19 #include "libpandabase/utils/logger.h"
20 #include "runtime/include/object_header-inl.h"
21 #include "runtime/include/panda_vm.h"
22 #include "runtime/mem/gc/gc_root-inl.h"
23 #include "runtime/mem/gc/workers/gc_workers_task_pool.h"
24 #include "runtime/mem/object_helpers.h"
25 #include "runtime/mem/pygote_space_allocator-inl.h"
26 #include "runtime/mem/gc/static/gc_marker_static-inl.h"
27 #include "runtime/mem/gc/dynamic/gc_marker_dynamic-inl.h"
28 #include "runtime/mem/gc/gc_adaptive_stack_inl.h"
29 
30 namespace ark::mem {
31 
32 template <class LanguageConfig>
StwGC(ObjectAllocatorBase * objectAllocator,const GCSettings & settings)33 StwGC<LanguageConfig>::StwGC(ObjectAllocatorBase *objectAllocator, const GCSettings &settings)
34     : GCLang<LanguageConfig>(objectAllocator, settings), marker_(this)
35 {
36     this->SetType(GCType::STW_GC);
37 }
38 
39 template <class LanguageConfig>
InitializeImpl()40 void StwGC<LanguageConfig>::InitializeImpl()
41 {
42     trace::ScopedTrace scopedTrace(__FUNCTION__);
43     InternalAllocatorPtr allocator = this->GetInternalAllocator();
44     auto barrierSet = allocator->New<GCDummyBarrierSet>(allocator);
45     ASSERT(barrierSet != nullptr);
46     this->SetGCBarrierSet(barrierSet);
47     this->CreateWorkersTaskPool();
48     LOG_DEBUG_GC << "STW GC Initialized";
49 }
50 
51 template <class LanguageConfig>
CheckGCCause(GCTaskCause cause) const52 bool StwGC<LanguageConfig>::CheckGCCause(GCTaskCause cause) const
53 {
54     // Causes for generational GC are unsuitable for STW (non-generational) GC
55     if (cause == GCTaskCause::YOUNG_GC_CAUSE || cause == GCTaskCause::MIXED) {
56         return false;
57     }
58     return cause != GCTaskCause::CROSSREF_CAUSE && cause != GCTaskCause::INVALID_CAUSE;
59 }
60 
61 template <class LanguageConfig>
RunPhasesImpl(GCTask & task)62 void StwGC<LanguageConfig>::RunPhasesImpl(GCTask &task)
63 {
64     trace::ScopedTrace scopedTrace(__FUNCTION__);
65     auto memStats = this->GetPandaVm()->GetMemStats();
66     GCScopedPauseStats scopedPauseStats(this->GetPandaVm()->GetGCStats(), this->GetStats());
67     [[maybe_unused]] size_t bytesInHeapBeforeGc = memStats->GetFootprintHeap();
68     marker_.BindBitmaps(true);
69     Mark(task);
70     Sweep();
71     marker_.ReverseMark();
72     [[maybe_unused]] size_t bytesInHeapAfterGc = memStats->GetFootprintHeap();
73     ASSERT(bytesInHeapAfterGc <= bytesInHeapBeforeGc);
74     task.collectionType = GCCollectionType::FULL;
75 }
76 
77 template <class LanguageConfig>
Mark(const GCTask & task)78 void StwGC<LanguageConfig>::Mark(const GCTask &task)
79 {
80     GCScope<TRACE_PHASE> gcScope(__FUNCTION__, this, GCPhase::GC_PHASE_MARK);
81 
82     // Iterate over roots and add other roots
83     bool useGcWorkers = this->GetSettings()->ParallelMarkingEnabled();
84     GCMarkingStackType objectsStack(this, useGcWorkers ? this->GetSettings()->GCRootMarkingStackMaxSize() : 0,
85                                     useGcWorkers ? this->GetSettings()->GCWorkersMarkingStackMaxSize() : 0,
86                                     GCWorkersTaskTypes::TASK_MARKING,
87                                     this->GetSettings()->GCMarkingStackNewTasksFrequency());
88 
89     this->VisitRoots(
90         [&objectsStack, &useGcWorkers, this](const GCRoot &gcRoot) {
91             LOG_DEBUG_GC << "Handle root " << GetDebugInfoAboutObject(gcRoot.GetObjectHeader());
92             if (marker_.MarkIfNotMarked(gcRoot.GetObjectHeader())) {
93                 objectsStack.PushToStack(gcRoot.GetType(), gcRoot.GetObjectHeader());
94             }
95             if (!useGcWorkers) {
96                 MarkStack(&objectsStack);
97             }
98         },
99         VisitGCRootFlags::ACCESS_ROOT_ALL);
100 
101     this->GetPandaVm()->VisitStringTable(
102         [this, &objectsStack](ObjectHeader *str) {
103             if (this->marker_.MarkIfNotMarked(str)) {
104                 ASSERT(str != nullptr);
105                 objectsStack.PushToStack(RootType::STRING_TABLE, str);
106             }
107         },
108         VisitGCRootFlags::ACCESS_ROOT_ALL);
109     MarkStack(&objectsStack);
110     ASSERT(objectsStack.Empty());
111     if (useGcWorkers) {
112         this->GetWorkersTaskPool()->WaitUntilTasksEnd();
113     }
114     auto refClearPred = [this]([[maybe_unused]] const ObjectHeader *obj) { return this->InGCSweepRange(obj); };
115     // NOLINTNEXTLINE(performance-unnecessary-value-param)
116     this->GetPandaVm()->HandleReferences(task, refClearPred);
117 }
118 
119 template <class LanguageConfig>
MarkStack(GCMarkingStackType * stack)120 void StwGC<LanguageConfig>::MarkStack(GCMarkingStackType *stack)
121 {
122     trace::ScopedTrace scopedTrace(__FUNCTION__);
123     ASSERT(stack != nullptr);
124     size_t objectsCount = 0;
125     auto refPred = [this](const ObjectHeader *obj) { return this->InGCSweepRange(obj); };
126     while (!stack->Empty()) {
127         objectsCount++;
128         auto *object = this->PopObjectFromStack(stack);
129         ValidateObject(nullptr, object);
130         auto *baseClass = object->template ClassAddr<BaseClass>();
131         LOG_DEBUG_GC << "Current object: " << GetDebugInfoAboutObject(object);
132         this->marker_.MarkInstance(stack, object, baseClass, refPred);
133     }
134     LOG_DEBUG_GC << "Iterated over " << objectsCount << " objects in the stack";
135 }
136 
137 template <class LanguageConfig>
Sweep()138 void StwGC<LanguageConfig>::Sweep()
139 {
140     GCScope<TRACE_PHASE> gcScope(__FUNCTION__, this, GCPhase::GC_PHASE_SWEEP);
141     if (!marker_.IsReverseMark()) {
142         LOG_DEBUG_GC << "Sweep with MarkChecker";
143         SweepImpl<DIRECT_MARK>();
144     } else {
145         LOG_DEBUG_GC << "Sweep with ReverseMarkChecker";
146         SweepImpl<REVERSE_MARK>();
147     }
148 }
149 
150 template <class LanguageConfig>
151 template <typename StwGC<LanguageConfig>::MarkType MARK_TYPE>
SweepImpl()152 void StwGC<LanguageConfig>::SweepImpl()
153 {
154     this->GetPandaVm()->SweepVmRefs([this](ObjectHeader *object) {
155         return this->marker_.template MarkChecker<static_cast<bool>(MARK_TYPE)>(object);
156     });
157     this->GetObjectAllocator()->Collect(
158         [this](ObjectHeader *object) {
159             auto status = this->marker_.template MarkChecker<static_cast<bool>(MARK_TYPE)>(object);
160             if (status == ObjectStatus::DEAD_OBJECT) {
161                 LOG_DEBUG_OBJECT_EVENTS << "DELETE OBJECT: " << object;
162             }
163             return status;
164         },
165         GCCollectMode::GC_ALL);
166     this->GetObjectAllocator()->VisitAndRemoveFreePools(
167         [](void *mem, [[maybe_unused]] size_t size) { PoolManager::GetMmapMemPool()->FreePool(mem, size); });
168 }
169 
170 template <class LanguageConfig>
InitGCBits(ark::ObjectHeader * object)171 void StwGC<LanguageConfig>::InitGCBits(ark::ObjectHeader *object)
172 {
173     if (!marker_.IsReverseMark()) {
174         object->SetUnMarkedForGC();
175         ASSERT(!object->IsMarkedForGC());
176     } else {
177         object->SetMarkedForGC();
178         ASSERT(object->IsMarkedForGC());
179     }
180     LOG_DEBUG_GC << "Init gc bits for object: " << std::hex << object << " bit: " << object->IsMarkedForGC()
181                  << " reversed_mark: " << marker_.IsReverseMark();
182 }
183 
184 template <class LanguageConfig>
InitGCBitsForAllocationInTLAB(ark::ObjectHeader * objHeader)185 void StwGC<LanguageConfig>::InitGCBitsForAllocationInTLAB([[maybe_unused]] ark::ObjectHeader *objHeader)
186 {
187     LOG(FATAL, GC) << "TLABs are not supported by this GC";
188 }
189 
190 template <class LanguageConfig>
Trigger(PandaUniquePtr<GCTask> task)191 bool StwGC<LanguageConfig>::Trigger(PandaUniquePtr<GCTask> task)
192 {
193     return this->AddGCTask(true, std::move(task));
194 }
195 
196 template <class LanguageConfig>
WorkerTaskProcessing(GCWorkersTask * task,void * workerData)197 void StwGC<LanguageConfig>::WorkerTaskProcessing(GCWorkersTask *task, [[maybe_unused]] void *workerData)
198 {
199     switch (task->GetType()) {
200         case GCWorkersTaskTypes::TASK_MARKING: {
201             auto *stack = task->Cast<GCMarkWorkersTask>()->GetMarkingStack();
202             MarkStack(stack);
203             this->GetInternalAllocator()->Delete(stack);
204             break;
205         }
206         default:
207             LOG(FATAL, GC) << "Unimplemented for " << GCWorkersTaskTypesToString(task->GetType());
208             UNREACHABLE();
209     }
210 }
211 
212 template <class LanguageConfig>
IsPostponeGCSupported() const213 bool StwGC<LanguageConfig>::IsPostponeGCSupported() const
214 {
215     return true;
216 }
217 
218 template <class LanguageConfig>
MarkObject(ObjectHeader * object)219 void StwGC<LanguageConfig>::MarkObject(ObjectHeader *object)
220 {
221     marker_.Mark(object);
222 }
223 
224 template <class LanguageConfig>
UnMarkObject(ObjectHeader * objectHeader)225 void StwGC<LanguageConfig>::UnMarkObject([[maybe_unused]] ObjectHeader *objectHeader)
226 {
227     LOG(FATAL, GC) << "UnMarkObject for STW GC shouldn't be called";
228 }
229 
230 template <class LanguageConfig>
MarkReferences(GCMarkingStackType * references,GCPhase gcPhase)231 void StwGC<LanguageConfig>::MarkReferences(GCMarkingStackType *references, [[maybe_unused]] GCPhase gcPhase)
232 {
233     trace::ScopedTrace scopedTrace(__FUNCTION__);
234     ASSERT(gcPhase == GCPhase::GC_PHASE_MARK);
235     LOG_DEBUG_GC << "Start marking " << references->Size() << " references";
236     MarkStack(references);
237 }
238 
239 template <class LanguageConfig>
IsMarked(const ObjectHeader * object) const240 bool StwGC<LanguageConfig>::IsMarked(const ObjectHeader *object) const
241 {
242     return marker_.IsMarked(object);
243 }
244 
245 TEMPLATE_CLASS_LANGUAGE_CONFIG(StwGC);
246 TEMPLATE_CLASS_LANGUAGE_CONFIG(StwGCMarker);
247 
248 }  // namespace ark::mem
249