1 /** 2 * Copyright (c) 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_G1_G1_EVACUATE_REGIONS_WORKER_STATE_H 16 #define PANDA_RUNTIME_MEM_GC_G1_G1_EVACUATE_REGIONS_WORKER_STATE_H 17 18 #include "runtime/mem/lock_config_helper.h" 19 #include "runtime/include/coretypes/tagged_value.h" 20 #include "runtime/mark_word.h" 21 #include "runtime/include/mem/panda_containers.h" 22 #include "runtime/mem/gc/g1/g1-object-pointer-handlers.h" 23 24 namespace ark::mem { 25 template <typename LanguageConfig> 26 class G1GC; 27 28 template <MTModeT MODE> 29 class ObjectAllocatorG1; 30 31 class CardTable; 32 33 class SharedState; 34 35 /// Data and methods to evacuate live objects by one worker. 36 template <typename LanguageConfig> 37 class G1EvacuateRegionsWorkerState { 38 public: 39 using Ref = typename ObjectReference<LanguageConfig::LANG_TYPE>::Type; 40 41 G1EvacuateRegionsWorkerState(G1GC<LanguageConfig> *gc, uint id, PandaVector<Ref> *queue, SharedState *shared); 42 GetId()43 uint GetId() const 44 { 45 return id_; 46 }; 47 ProcessQueue()48 void ProcessQueue() 49 { 50 while (!queue_->empty()) { 51 Ref p = queue_->back(); 52 queue_->pop_back(); 53 ProcessRef(p); 54 } 55 } 56 PushToQueue(Ref p)57 void PushToQueue(Ref p) 58 { 59 queue_->push_back(p); 60 } 61 62 /// Evacuate single live object, traverse its fields and enqueue found references to the queue_ 63 ObjectHeader *Evacuate(ObjectHeader *obj, MarkWord markWord); 64 GetGC()65 G1GC<LanguageConfig> *GetGC() 66 { 67 return gc_; 68 } 69 GetCopiedBytesYoung()70 size_t GetCopiedBytesYoung() const 71 { 72 return copiedBytesYoung_; 73 } 74 GetCopiedObjectsYoung()75 size_t GetCopiedObjectsYoung() const 76 { 77 return copiedObjectsYoung_; 78 } 79 GetCopiedBytesOld()80 size_t GetCopiedBytesOld() const 81 { 82 return copiedBytesOld_; 83 } 84 GetCopiedObjectsOld()85 size_t GetCopiedObjectsOld() const 86 { 87 return copiedObjectsOld_; 88 } 89 GetLiveBytes()90 size_t GetLiveBytes() const 91 { 92 return liveBytes_; 93 } 94 GetRegionTo()95 Region *GetRegionTo() 96 { 97 return regionTo_; 98 } 99 GetShared()100 SharedState *GetShared() 101 { 102 return shared_; 103 } 104 IsSameRegion(void * ref,void * obj)105 bool IsSameRegion(void *ref, void *obj) const 106 { 107 return ark::mem::IsSameRegion(ref, obj, regionSizeBits_); 108 } 109 EnqueueCard(void * p)110 void EnqueueCard(void *p) 111 { 112 auto *card = cardTable_->GetCardPtr(ToUintPtr(p)); 113 if (card != latestCard_) { 114 cardQueue_.insert(card); 115 latestCard_ = card; 116 } 117 } 118 119 template <typename Visitor> VisitCards(Visitor visitor)120 void VisitCards(Visitor visitor) 121 { 122 for (auto *card : cardQueue_) { 123 visitor(card); 124 } 125 } 126 GetTaskStart()127 uint64_t GetTaskStart() const 128 { 129 return taskStart_; 130 } 131 GetTaskEnd()132 uint64_t GetTaskEnd() const 133 { 134 return taskEnd_; 135 } 136 DumpStat()137 void DumpStat() const 138 { 139 LOG(INFO, GC) << "=== Worker #" << GetId(); 140 LOG(INFO, GC) << "non heap roots scan duration " << ark::helpers::TimeConverter(scanNonHeapRootsDuration_); 141 LOG(INFO, GC) << "added refs from non heap roots " << addNonHeapRootsRefsCount_; 142 LOG(INFO, GC) << "remset scan duration " << ark::helpers::TimeConverter(scanRemsetDuration_); 143 LOG(INFO, GC) << "remset count " << remsetCount_; 144 LOG(INFO, GC) << "added refs from remset " << foundRemsetRefsCount_; 145 LOG(INFO, GC) << "reenque cards " << reenqueueCardsCount_; 146 LOG(INFO, GC) << "evacuation duration " << ark::helpers::TimeConverter(evacuationDuration_); 147 LOG(INFO, GC) << "evacuation add cards " << evacuationAddCardsCount_; 148 } 149 Work()150 void Work() 151 { 152 StartWork(); 153 154 Init(); 155 EvacuateNonHeapRoots(); 156 ScanRemset(); 157 EvacuateLiveObjects(); 158 159 EndWork(); 160 } 161 162 private: 163 void StartWork(); Init()164 void Init() 165 { 166 constexpr size_t RESERVED_SIZE = 200000; 167 queue_->reserve(RESERVED_SIZE); 168 regionTo_ = GetNextRegion(); 169 } 170 171 void EndWork(); 172 void EvacuateNonHeapRoots(); 173 void ScanRemset(); 174 template <typename Visitor> 175 void IterateRefsInMemRange(const MemRange &memRange, Region *region, Visitor *visitor); 176 void EvacuateLiveObjects(); 177 GetNextRegion()178 Region *GetNextRegion() 179 { 180 auto *region = objectAllocator_->template PopFromOldRegionQueue<true>(); 181 if (region != nullptr) { 182 return region; 183 } 184 return CreateNewRegion(); 185 } 186 CreateNewRegion()187 Region *CreateNewRegion() 188 { 189 return objectAllocator_->template CreateAndSetUpNewOldRegion<true>(); 190 } 191 192 void ProcessRef(Ref p); 193 194 ObjectHeader *SetForwardAddress(ObjectHeader *src, ObjectHeader *dst, MarkWord markWord); 195 196 G1GC<LanguageConfig> *gc_; 197 ObjectAllocatorG1<LanguageConfig::MT_MODE> *objectAllocator_; 198 CardTable *cardTable_; 199 size_t regionSizeBits_; 200 uint id_; 201 SharedState *shared_; 202 PandaVector<Ref> *queue_; 203 EvacuationObjectPointerHandler<LanguageConfig> evacuationObjectPointerHandler_; 204 205 PandaSet<CardTable::CardPtr> cardQueue_; 206 CardTable::CardPtr latestCard_ {nullptr}; 207 208 uint64_t taskStart_ {0}; 209 uint64_t taskEnd_ {0}; 210 211 size_t copiedBytesYoung_ {0}; 212 size_t copiedObjectsYoung_ {0}; 213 size_t copiedBytesOld_ {0}; 214 size_t copiedObjectsOld_ {0}; 215 size_t liveBytes_ {0}; 216 Region *regionTo_ {nullptr}; 217 218 uint64_t scanNonHeapRootsDuration_ {0}; 219 uint64_t addNonHeapRootsRefsCount_ {0}; 220 221 uint64_t scanRemsetDuration_ {0}; 222 uint64_t foundRemsetRefsCount_ {0}; 223 uint64_t remsetCount_ {0}; 224 225 uint64_t evacuationDuration_ {0}; 226 uint64_t reenqueueCardsCount_ {0}; 227 uint64_t evacuationAddCardsCount_ {0}; 228 }; 229 230 /// Common data which is shared between workers. 231 class SharedState { 232 public: SharedState(Thread * gcThread,size_t workersCount,RemSet<> * remset)233 SharedState(Thread *gcThread, size_t workersCount, RemSet<> *remset) 234 : gcThread_(gcThread), workersCount_(workersCount), remset_(remset) 235 { 236 } 237 GetGcThread()238 Thread *GetGcThread() const 239 { 240 return gcThread_; 241 } 242 GetWorkersCount()243 size_t GetWorkersCount() const 244 { 245 return workersCount_; 246 } 247 GetRemset()248 RemSet<> *GetRemset() const 249 { 250 return remset_; 251 } 252 253 /// Counter which can be used to distribute remset processing between workers GetRemsetCounter()254 std::atomic<size_t> &GetRemsetCounter() 255 { 256 return remsetCounter_; 257 } 258 259 private: 260 Thread *gcThread_; 261 size_t workersCount_; 262 std::atomic<size_t> remsetCounter_ {}; 263 RemSet<> *remset_; 264 }; 265 266 } // namespace ark::mem 267 #endif 268