1 /* 2 * Copyright (c) 2021 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 16 #ifndef ECMASCRIPT_MEM_PARALLEL_EVACUATOR_H 17 #define ECMASCRIPT_MEM_PARALLEL_EVACUATOR_H 18 19 #include <atomic> 20 #include <memory> 21 22 #include "ecmascript/js_hclass.h" 23 #include "ecmascript/mem/heap.h" 24 #include "ecmascript/mem/object_xray.h" 25 #include "ecmascript/mem/region.h" 26 #include "ecmascript/mem/space.h" 27 #include "ecmascript/mem/tagged_object.h" 28 #include "ecmascript/mem/tlab_allocator.h" 29 #include "ecmascript/taskpool/task.h" 30 31 #include "ecmascript/platform/mutex.h" 32 33 namespace panda::ecmascript { 34 class ParallelEvacuator { 35 public: ParallelEvacuator(Heap * heap)36 explicit ParallelEvacuator(Heap *heap) : heap_(heap) {} 37 ~ParallelEvacuator() = default; 38 void Initialize(); 39 void Finalize(); 40 void Evacuate(); 41 GetPromotedSize()42 size_t GetPromotedSize() const 43 { 44 return promotedSize_; 45 } 46 GetEdenToYoungSize()47 size_t GetEdenToYoungSize() const 48 { 49 return edenToYoungSize_; 50 } 51 private: 52 class EvacuationTask : public Task { 53 public: 54 EvacuationTask(int32_t id, ParallelEvacuator *evacuator); 55 ~EvacuationTask() override; 56 bool Run(uint32_t threadIndex) override; 57 58 NO_COPY_SEMANTIC(EvacuationTask); 59 NO_MOVE_SEMANTIC(EvacuationTask); 60 61 private: 62 ParallelEvacuator *evacuator_; 63 TlabAllocator *allocator_ {nullptr}; 64 }; 65 66 class UpdateReferenceTask : public Task { 67 public: UpdateReferenceTask(int32_t id,ParallelEvacuator * evacuator)68 UpdateReferenceTask(int32_t id, ParallelEvacuator *evacuator) : Task(id), evacuator_(evacuator) {}; 69 ~UpdateReferenceTask() override = default; 70 71 bool Run(uint32_t threadIndex) override; 72 73 NO_COPY_SEMANTIC(UpdateReferenceTask); 74 NO_MOVE_SEMANTIC(UpdateReferenceTask); 75 76 private: 77 ParallelEvacuator *evacuator_; 78 }; 79 80 class Workload { 81 public: Workload(ParallelEvacuator * evacuator,Region * region)82 Workload(ParallelEvacuator *evacuator, Region *region) : evacuator_(evacuator), region_(region) {}; 83 virtual ~Workload() = default; 84 virtual bool Process(bool isMain) = 0; GetRegion()85 inline Region *GetRegion() const 86 { 87 return region_; 88 } 89 GetEvacuator()90 inline ParallelEvacuator *GetEvacuator() const 91 { 92 return evacuator_; 93 } 94 protected: 95 ParallelEvacuator *evacuator_; 96 Region *region_; 97 }; 98 99 class EvacuateWorkload : public Workload { 100 public: EvacuateWorkload(ParallelEvacuator * evacuator,Region * region)101 EvacuateWorkload(ParallelEvacuator *evacuator, Region *region) : Workload(evacuator, region) {} 102 ~EvacuateWorkload() override = default; 103 bool Process(bool isMain) override; 104 }; 105 106 class UpdateRSetWorkload : public Workload { 107 public: UpdateRSetWorkload(ParallelEvacuator * evacuator,Region * region,bool isEdenGC)108 UpdateRSetWorkload(ParallelEvacuator *evacuator, Region *region, bool isEdenGC) 109 : Workload(evacuator, region), isEdenGC_(isEdenGC) {} 110 ~UpdateRSetWorkload() override = default; 111 bool Process(bool isMain) override; 112 private: 113 bool isEdenGC_; 114 }; 115 116 class UpdateNewToEdenRSetWorkload : public Workload { 117 public: UpdateNewToEdenRSetWorkload(ParallelEvacuator * evacuator,Region * region)118 UpdateNewToEdenRSetWorkload(ParallelEvacuator *evacuator, Region *region) : Workload(evacuator, region) {} 119 ~UpdateNewToEdenRSetWorkload() override = default; 120 bool Process(bool isMain) override; 121 }; 122 123 class UpdateNewRegionWorkload : public Workload { 124 public: UpdateNewRegionWorkload(ParallelEvacuator * evacuator,Region * region,bool isYoungGC)125 UpdateNewRegionWorkload(ParallelEvacuator *evacuator, Region *region, bool isYoungGC) 126 : Workload(evacuator, region), isYoungGC_(isYoungGC) {} 127 ~UpdateNewRegionWorkload() override = default; 128 bool Process(bool isMain) override; 129 private: 130 bool isYoungGC_; 131 }; 132 133 class UpdateAndSweepNewRegionWorkload : public Workload { 134 public: UpdateAndSweepNewRegionWorkload(ParallelEvacuator * evacuator,Region * region,bool isYoungGC)135 UpdateAndSweepNewRegionWorkload(ParallelEvacuator *evacuator, Region *region, bool isYoungGC) 136 : Workload(evacuator, region), isYoungGC_(isYoungGC) {} 137 ~UpdateAndSweepNewRegionWorkload() override = default; 138 bool Process(bool isMain) override; 139 private: 140 bool isYoungGC_; 141 }; 142 ArrayTrackInfoSet(uint32_t threadIndex)143 std::unordered_set<JSTaggedType> &ArrayTrackInfoSet(uint32_t threadIndex) 144 { 145 return arrayTrackInfoSets_[threadIndex]; 146 } 147 148 TaggedObject* UpdateAddressAfterEvacation(TaggedObject *oldTrackInfo); 149 150 void UpdateTrackInfo(); 151 152 bool ProcessWorkloads(bool isMain = false); 153 154 void EvacuateSpace(); 155 bool EvacuateSpace(TlabAllocator *allocation, uint32_t threadIndex, bool isMain = false); 156 void EvacuateRegion(TlabAllocator *allocator, Region *region, std::unordered_set<JSTaggedType> &trackSet); 157 template<bool SetEdenObject> 158 inline void SetObjectFieldRSet(TaggedObject *object, JSHClass *cls); 159 template<bool SetEdenObject> 160 inline void SetObjectRSet(ObjectSlot slot, Region *region); 161 162 inline void UpdateLocalToShareRSet(TaggedObject *object, JSHClass *cls); 163 inline void SetLocalToShareRSet(ObjectSlot slot, Region *region); 164 165 inline bool IsWholeRegionEvacuate(Region *region); 166 inline bool WholeRegionEvacuate(Region *region); 167 void VerifyValue(TaggedObject *object, ObjectSlot slot); 168 void VerifyHeapObject(TaggedObject *object); 169 170 void UpdateReference(); 171 void UpdateRoot(); 172 void UpdateWeakReference(); 173 void UpdateRecordWeakReference(); 174 template<TriggerGCType gcType> 175 void UpdateWeakReferenceOpt(); 176 template<TriggerGCType gcType> 177 void UpdateRecordWeakReferenceOpt(); 178 template<bool IsEdenGC> 179 void UpdateRSet(Region *region); 180 void UpdateNewToEdenRSetReference(Region *region); 181 template<TriggerGCType gcType> 182 void UpdateNewRegionReference(Region *region); 183 template<TriggerGCType gcType> 184 void UpdateAndSweepNewRegionReference(Region *region); 185 template<TriggerGCType gcType> 186 void UpdateNewObjectField(TaggedObject *object, JSHClass *cls); 187 188 template<typename Callback> 189 inline bool VisitBodyInObj(TaggedObject *root, ObjectSlot start, ObjectSlot end, Callback callback); 190 inline bool UpdateForwardedOldToNewObjectSlot(TaggedObject *object, ObjectSlot &slot, bool isWeak); 191 template<bool IsEdenGC> 192 inline bool UpdateOldToNewObjectSlot(ObjectSlot &slot); 193 inline bool UpdateNewToEdenObjectSlot(ObjectSlot &slot); 194 inline void UpdateObjectSlot(ObjectSlot &slot); 195 template<TriggerGCType gcType> 196 inline void UpdateObjectSlotOpt(ObjectSlot &slot); 197 inline void UpdateWeakObjectSlot(TaggedObject *object, ObjectSlot &slot); 198 template<TriggerGCType gcType> 199 inline bool UpdateWeakObjectSlotOpt(JSTaggedValue value, ObjectSlot &slot); 200 201 inline std::unique_ptr<Workload> GetWorkloadSafe(); 202 inline void AddWorkload(std::unique_ptr<Workload> region); 203 204 inline int CalculateEvacuationThreadNum(); 205 inline int CalculateUpdateThreadNum(); 206 void WaitFinished(); 207 208 Heap *heap_; 209 TlabAllocator *allocator_ {nullptr}; 210 211 uintptr_t waterLine_ = 0; 212 std::vector<std::unique_ptr<Workload>> workloads_; 213 std::unordered_set<JSTaggedType> arrayTrackInfoSets_[MAX_TASKPOOL_THREAD_NUM + 1]; 214 std::atomic_int parallel_ = 0; 215 Mutex mutex_; 216 ConditionVariable condition_; 217 std::atomic<size_t> promotedSize_ = 0; 218 std::atomic<size_t> edenToYoungSize_ = 0; 219 }; 220 } // namespace panda::ecmascript 221 #endif // ECMASCRIPT_MEM_PARALLEL_EVACUATOR_H 222