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