1 /* 2 * Copyright (c) 2025 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_SHARED_HEAP_SHARED_GC_EVACUATOR_H 17 #define ECMASCRIPT_MEM_SHARED_HEAP_SHARED_GC_EVACUATOR_H 18 19 #include "ecmascript/mem/heap-inl.h" 20 21 namespace panda::ecmascript { 22 class SharedGCEvacuator { 23 public: SharedGCEvacuator(SharedHeap * heap)24 explicit SharedGCEvacuator(SharedHeap *heap) : sHeap_(heap), objectFieldCSetVisitor_(this) {} 25 ~SharedGCEvacuator() = default; 26 NO_COPY_SEMANTIC(SharedGCEvacuator); 27 NO_MOVE_SEMANTIC(SharedGCEvacuator); 28 void Evacuate(); 29 private: 30 void EvacuateRegions(); 31 void UpdateReference(); 32 bool UpdateObjectSlot(ObjectSlot slot); 33 void UpdateObjectSlotRoot(ObjectSlot slot); 34 void ProcessObjectField(TaggedObject *object, JSHClass *hclass); 35 void UpdateCrossRegionRSet(ObjectSlot slot, Region *objectRegion); 36 void WaitFinished(); 37 int CalculateUpdateThreadNum(); 38 39 class UpdateRootVisitor final : public RootVisitor { 40 public: 41 UpdateRootVisitor() = default; 42 ~UpdateRootVisitor() = default; 43 44 void VisitRoot([[maybe_unused]] Root type, ObjectSlot slot) override; 45 void VisitRangeRoot([[maybe_unused]] Root type, ObjectSlot start, ObjectSlot end) override; 46 void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, ObjectSlot base, ObjectSlot derived, 47 uintptr_t baseOldObject) override; 48 private: 49 void UpdateObjectSlotRoot(ObjectSlot slot); 50 }; 51 52 class ObjectFieldCSetVisitor final : public EcmaObjectRangeVisitor<ObjectFieldCSetVisitor> { 53 public: ObjectFieldCSetVisitor(SharedGCEvacuator * evacuator)54 explicit ObjectFieldCSetVisitor(SharedGCEvacuator *evacuator) : evacuator_(evacuator) {} 55 ~ObjectFieldCSetVisitor() override = default; 56 57 void VisitObjectRangeImpl(TaggedObject *root, ObjectSlot start, ObjectSlot end, VisitObjectArea area) override; 58 private: 59 SharedGCEvacuator *evacuator_ {nullptr}; 60 }; 61 62 class Workload { 63 public: Workload(SharedGCEvacuator * evacuator,Region * region)64 Workload(SharedGCEvacuator *evacuator, Region *region) : evacuator_(evacuator), region_(region) {} 65 virtual ~Workload() = default; 66 virtual void Process(bool isMain) = 0; 67 protected: 68 SharedGCEvacuator *evacuator_ {nullptr}; 69 Region *region_ {nullptr}; 70 }; 71 AddWorkload(std::unique_ptr<Workload> workload)72 void AddWorkload(std::unique_ptr<Workload> workload) 73 { 74 workloads_.emplace_back(std::move(workload)); 75 } 76 GetWorkload()77 std::unique_ptr<Workload> GetWorkload() 78 { 79 LockHolder holder(lock_); 80 std::unique_ptr<Workload> workload; 81 if (!workloads_.empty()) { 82 workload = std::move(workloads_.back()); 83 workloads_.pop_back(); 84 } 85 return workload; 86 } 87 ProcessWorkloads(bool isMain)88 void ProcessWorkloads(bool isMain) 89 { 90 std::unique_ptr<Workload> workload = GetWorkload(); 91 while (workload != nullptr) { 92 workload->Process(isMain); 93 workload = GetWorkload(); 94 } 95 if (!isMain) { 96 LockHolder holder(lock_); 97 if (--parallel_ <= 0) { 98 condition_.SignalAll(); 99 } 100 } 101 } 102 103 class UpdateLocalReferenceWorkload : public Workload { 104 public: UpdateLocalReferenceWorkload(SharedGCEvacuator * evacuator,Region * region)105 UpdateLocalReferenceWorkload(SharedGCEvacuator *evacuator, Region *region) : Workload(evacuator, region) {} 106 void Process(bool isMain) override; 107 }; 108 109 class UpdateSharedReferenceWorkload : public Workload { 110 public: UpdateSharedReferenceWorkload(SharedGCEvacuator * evacuator,Region * region)111 UpdateSharedReferenceWorkload(SharedGCEvacuator *evacuator, Region *region) : Workload(evacuator, region) {} 112 void Process(bool isMain) override; 113 }; 114 115 class UpdateReferenceTask : public Task { 116 public: UpdateReferenceTask(int32_t id,SharedGCEvacuator * evacuator)117 UpdateReferenceTask(int32_t id, SharedGCEvacuator *evacuator) : Task(id), evacuator_(evacuator) {}; 118 ~UpdateReferenceTask() override = default; 119 NO_COPY_SEMANTIC(UpdateReferenceTask); 120 NO_MOVE_SEMANTIC(UpdateReferenceTask); 121 122 bool Run(uint32_t threadIndex) override; 123 124 private: 125 SharedGCEvacuator *evacuator_ {nullptr}; 126 }; 127 128 SharedHeap *sHeap_ {nullptr}; 129 Mutex lock_; 130 ConditionVariable condition_; 131 std::vector<std::unique_ptr<Workload>> workloads_; 132 UpdateRootVisitor rootVisitor_; 133 ObjectFieldCSetVisitor objectFieldCSetVisitor_; 134 int parallel_ {0}; 135 }; 136 } // namespace panda::ecmascript 137 138 #endif // ECMASCRIPT_MEM_SHARED_HEAP_SHARED_GC_EVACUATOR_H 139