• 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 #ifndef PANDA_RUNTIME_MEM_GC_GC_MARKER_H
16 #define PANDA_RUNTIME_MEM_GC_GC_MARKER_H
17 
18 #include "runtime/mem/gc/gc.h"
19 #include "runtime/mem/gc/bitmap.h"
20 #include "runtime/mem/gc/gc_root.h"
21 #include "runtime/include/object_header.h"
22 #include "runtime/include/language_config.h"
23 
24 namespace ark::coretypes {
25 class DynClass;
26 }  // namespace ark::coretypes
27 
28 namespace ark::mem {
29 
30 class GCMarkerBase {
31 public:
GCMarkerBase(GC * gc)32     explicit GCMarkerBase(GC *gc) : gc_(gc) {}
33 
GetGC()34     GC *GetGC() const
35     {
36         return gc_;
37     }
38 
39 private:
40     GC *gc_;
41 };
42 
43 template <typename Marker, LangTypeT LANG_TYPE>
44 class GCMarker;
45 
46 template <typename Marker>
47 class GCMarker<Marker, LANG_TYPE_STATIC> : public GCMarkerBase {
48 public:
49     using ReferenceCheckPredicateT = typename GC::ReferenceCheckPredicateT;
50 
GCMarker(GC * gc)51     explicit GCMarker(GC *gc) : GCMarkerBase(gc) {}
52 
53     void MarkInstance(GCMarkingStackType *objectsStack, const ObjectHeader *object, const BaseClass *cls,
54                       const ReferenceCheckPredicateT &refPred);
55 
56     void MarkInstance(GCMarkingStackType *objectsStack, const ObjectHeader *object, const BaseClass *cls);
57 
58 private:
AsMarker()59     Marker *AsMarker()
60     {
61         return static_cast<Marker *>(this);
62     }
63 
64     /**
65      * Iterate over all fields with references of object and add all not null object references to the objects_stack
66      * @param objects_stack - stack with objects
67      * @param object
68      * @param base_cls - class of object(used for perf in case if class for the object already was obtained)
69      */
70     void HandleObject(GCMarkingStackType *objectsStack, const ObjectHeader *object, const Class *cls);
71 
72     /**
73      * Iterate over class data and add all found not null object references to the objects_stack
74      * @param objects_stack - stack with objects
75      * @param cls - class
76      */
77     void HandleClass(GCMarkingStackType *objectsStack, const Class *cls);
78 
79     /**
80      * For arrays of objects add all not null object references to the objects_stack
81      * @param objects_stack - stack with objects
82      * @param array_object - array object
83      * @param cls - class of array object(used for perf)
84      */
85     void HandleArrayClass(GCMarkingStackType *objectsStack, const coretypes::Array *arrayObject, const Class *cls);
86 };
87 
88 template <typename Marker>
89 class GCMarker<Marker, LANG_TYPE_DYNAMIC> : public GCMarkerBase {
90 public:
91     using ReferenceCheckPredicateT = typename GC::ReferenceCheckPredicateT;
92 
GCMarker(GC * gc)93     explicit GCMarker(GC *gc) : GCMarkerBase(gc) {}
94 
95     void MarkInstance(GCMarkingStackType *objectsStack, const ObjectHeader *object, const BaseClass *cls,
96                       const ReferenceCheckPredicateT &refPred);
97 
98     void MarkInstance(GCMarkingStackType *objectsStack, const ObjectHeader *object, const BaseClass *cls);
99 
100 private:
AsMarker()101     Marker *AsMarker()
102     {
103         return static_cast<Marker *>(this);
104     }
105 
106     /**
107      * Iterate over all fields with references of object and add all not null object references to the objects_stack
108      * @param objects_stack - stack with objects
109      * @param object
110      * @param base_cls - class of object(used for perf in case if class for the object already was obtained)
111      */
112     void HandleObject(GCMarkingStackType *objectsStack, const ObjectHeader *object, const BaseClass *cls);
113 
114     /**
115      * Iterate over class data and add all found not null object references to the objects_stack
116      * @param objects_stack - stack with objects
117      * @param cls - class
118      */
119     void HandleClass(GCMarkingStackType *objectsStack, const coretypes::DynClass *cls);
120 
121     /**
122      * For arrays of objects add all not null object references to the objects_stack
123      * @param objects_stack - stack with objects
124      * @param array_object - array object
125      * @param cls - class of array object(used for perf)
126      */
127     void HandleArrayClass(GCMarkingStackType *objectsStack, const coretypes::Array *arrayObject, const BaseClass *cls);
128 };
129 
130 template <typename Marker, class LanguageConfig>
131 class DefaultGCMarker : public GCMarker<Marker, LanguageConfig::LANG_TYPE> {
132     using Base = GCMarker<Marker, LanguageConfig::LANG_TYPE>;
133 
134 public:
DefaultGCMarker(GC * gc)135     explicit DefaultGCMarker(GC *gc) : GCMarker<Marker, LanguageConfig::LANG_TYPE>(gc) {}
136 
137     template <bool REVERSED_MARK = false>
MarkIfNotMarked(ObjectHeader * object)138     bool MarkIfNotMarked(ObjectHeader *object) const
139     {
140         MarkBitmap *bitmap = GetMarkBitMap(object);
141         if (bitmap != nullptr) {
142             if (atomicMarkFlag_) {
143                 return !bitmap->AtomicTestAndSet(object);
144             }
145             if (bitmap->Test(object)) {
146                 return false;
147             }
148             bitmap->Set(object);
149             return true;
150         }
151         if (atomicMarkFlag_) {
152             if (IsObjectHeaderMarked<REVERSED_MARK, true>(object)) {
153                 return false;
154             }
155             MarkObjectHeader<REVERSED_MARK, true>(object);
156         } else {
157             if (IsObjectHeaderMarked<REVERSED_MARK, false>(object)) {
158                 return false;
159             }
160             MarkObjectHeader<REVERSED_MARK, false>(object);
161         }
162         return true;
163     }
164 
165     template <bool REVERSED_MARK = false>
Mark(ObjectHeader * object)166     void Mark(ObjectHeader *object) const
167     {
168         MarkBitmap *bitmap = GetMarkBitMap(object);
169         if (bitmap != nullptr) {
170             if (atomicMarkFlag_) {
171                 bitmap->AtomicTestAndSet(object);
172             } else {
173                 bitmap->Set(object);
174             }
175             return;
176         }
177         if constexpr (REVERSED_MARK) {  // NOLINTNEXTLINE(readability-braces-around-statements)
178             if (atomicMarkFlag_) {
179                 object->SetUnMarkedForGC<true>();
180             } else {
181                 object->SetUnMarkedForGC<false>();
182             }
183             return;
184         }
185         if (atomicMarkFlag_) {
186             object->SetMarkedForGC<true>();
187         } else {
188             object->SetMarkedForGC<false>();
189         }
190     }
191 
192     template <bool REVERSED_MARK = false>
UnMark(ObjectHeader * object)193     void UnMark(ObjectHeader *object) const
194     {
195         MarkBitmap *bitmap = GetMarkBitMap(object);
196         if (bitmap != nullptr) {
197             return;  // no need for bitmap
198         }
199         if constexpr (REVERSED_MARK) {  // NOLINTNEXTLINE(readability-braces-around-statements)
200             if (atomicMarkFlag_) {
201                 object->SetMarkedForGC<true>();
202             } else {
203                 object->SetMarkedForGC<false>();
204             }
205             return;
206         }
207         if (atomicMarkFlag_) {
208             object->SetUnMarkedForGC<true>();
209         } else {
210             object->SetUnMarkedForGC<false>();
211         }
212     }
213 
214     template <bool REVERSED_MARK = false>
IsMarked(const ObjectHeader * object)215     bool IsMarked(const ObjectHeader *object) const
216     {
217         MarkBitmap *bitmap = GetMarkBitMap(object);
218         if (bitmap != nullptr) {
219             if (atomicMarkFlag_) {
220                 return bitmap->AtomicTest(object);
221             }
222             return bitmap->Test(object);
223         }
224         bool isMarked = atomicMarkFlag_ ? object->IsMarkedForGC<true>() : object->IsMarkedForGC<false>();
225         if constexpr (REVERSED_MARK) {  // NOLINTNEXTLINE(readability-braces-around-statements)
226             return !isMarked;
227         }
228         return isMarked;
229     }
230 
231     template <bool REVERSED_MARK = false>
MarkChecker(const ObjectHeader * object)232     ObjectStatus MarkChecker(const ObjectHeader *object) const
233     {
234         if constexpr (!REVERSED_MARK) {  // NOLINTNEXTLINE(readability-braces-around-statements)
235             // If ClassAddr is not set - it means object header initialization is in progress now
236             if (object->ClassAddr<BaseClass>() == nullptr) {
237                 return ObjectStatus::ALIVE_OBJECT;
238             }
239         }
240         ObjectStatus objectStatus =
241             IsMarked<REVERSED_MARK>(object) ? ObjectStatus::ALIVE_OBJECT : ObjectStatus::DEAD_OBJECT;
242         LOG(DEBUG, GC) << " Mark check for " << std::hex << object << std::dec
243                        << " object is alive: " << static_cast<bool>(objectStatus);
244         return objectStatus;
245     }
246 
GetMarkBitMap(const void * object)247     MarkBitmap *GetMarkBitMap(const void *object) const
248     {
249         for (auto bitmap : markBitmaps_) {
250             if (bitmap->IsAddrInRange(object)) {
251                 return bitmap;
252             }
253         }
254         return nullptr;
255     }
256 
ClearMarkBitMaps()257     void ClearMarkBitMaps()
258     {
259         markBitmaps_.clear();
260     }
261 
AddMarkBitMap(MarkBitmap * bitmap)262     void AddMarkBitMap(MarkBitmap *bitmap)
263     {
264         markBitmaps_.push_back(bitmap);
265     }
266 
267     template <typename It>
AddMarkBitMaps(It start,It end)268     void AddMarkBitMaps(It start, It end)
269     {
270         markBitmaps_.insert(markBitmaps_.end(), start, end);
271     }
272 
HasBitMap(MarkBitmap * bitmap)273     bool HasBitMap(MarkBitmap *bitmap)
274     {
275         return std::find(markBitmaps_.begin(), markBitmaps_.end(), bitmap) != markBitmaps_.end();
276     }
277 
SetAtomicMark(bool flag)278     void SetAtomicMark(bool flag)
279     {
280         atomicMarkFlag_ = flag;
281     }
282 
GetAtomicMark()283     bool GetAtomicMark() const
284     {
285         return atomicMarkFlag_;
286     }
287 
BindBitmaps(bool clearPygoteSpaceBitmaps)288     void BindBitmaps(bool clearPygoteSpaceBitmaps)
289     {
290         // Set marking bitmaps
291         ClearMarkBitMaps();
292         auto pygoteSpaceAllocator = Base::GetGC()->GetObjectAllocator()->GetPygoteSpaceAllocator();
293         if (pygoteSpaceAllocator != nullptr) {
294             // clear live bitmaps if we decide to rebuild it in full gc,
295             // it will be used as marked bitmaps and updated at end of gc
296             if (clearPygoteSpaceBitmaps) {
297                 pygoteSpaceAllocator->ClearLiveBitmaps();
298             }
299             auto &bitmaps = pygoteSpaceAllocator->GetLiveBitmaps();
300             AddMarkBitMaps(bitmaps.begin(), bitmaps.end());
301         }
302     }
303 
304 private:
305     template <bool REVERSED_MARK = false, bool ATOMIC_MARK = true>
IsObjectHeaderMarked(const ObjectHeader * object)306     bool IsObjectHeaderMarked(const ObjectHeader *object) const
307     {
308         // NOLINTNEXTLINE(readability-braces-around-statements)
309         if constexpr (REVERSED_MARK) {  // NOLINT(bugprone-suspicious-semicolon)
310             return !object->IsMarkedForGC<ATOMIC_MARK>();
311         }
312         return object->IsMarkedForGC<ATOMIC_MARK>();
313     }
314 
315     template <bool REVERSED_MARK = false, bool ATOMIC_MARK = true>
MarkObjectHeader(ObjectHeader * object)316     void MarkObjectHeader(ObjectHeader *object) const
317     {
318         // NOLINTNEXTLINE(readability-braces-around-statements)
319         if constexpr (REVERSED_MARK) {  // NOLINT(bugprone-suspicious-semicolon)
320             object->SetUnMarkedForGC<ATOMIC_MARK>();
321             return;
322         }
323         object->SetMarkedForGC<ATOMIC_MARK>();
324     }
325 
326 private:
327     // Bitmaps for mark object
328     PandaVector<MarkBitmap *> markBitmaps_;
329     bool atomicMarkFlag_ = true;
330 };
331 
332 template <class Marker>
333 class NoAtomicGCMarkerScope {
334 public:
NoAtomicGCMarkerScope(Marker * marker)335     explicit NoAtomicGCMarkerScope(Marker *marker)
336     {
337         ASSERT(marker != nullptr);
338         gcMarker_ = marker;
339         oldState_ = gcMarker_->GetAtomicMark();
340         if (oldState_) {
341             gcMarker_->SetAtomicMark(false);
342         }
343     }
344 
345     NO_COPY_SEMANTIC(NoAtomicGCMarkerScope);
346     NO_MOVE_SEMANTIC(NoAtomicGCMarkerScope);
347 
~NoAtomicGCMarkerScope()348     ~NoAtomicGCMarkerScope()
349     {
350         if (oldState_) {
351             gcMarker_->SetAtomicMark(oldState_);
352         }
353     }
354 
355 private:
356     Marker *gcMarker_;
357     bool oldState_ = false;
358 };
359 
360 template <class LanguageConfig>
361 class DefaultGCMarkerImpl : public DefaultGCMarker<DefaultGCMarkerImpl<LanguageConfig>, LanguageConfig> {
362     using Base = DefaultGCMarker<DefaultGCMarkerImpl<LanguageConfig>, LanguageConfig>;
363 
364 public:
DefaultGCMarkerImpl(GC * gc)365     explicit DefaultGCMarkerImpl(GC *gc) : Base(gc) {}
366 };
367 
368 }  // namespace ark::mem
369 
370 #endif  // PANDA_RUNTIME_MEM_GC_GC_MARKER_H
371