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