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