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_EVACUATION_H 17 #define ECMASCRIPT_MEM_PARALLEL_EVACUATION_H 18 19 #include <atomic> 20 #include <memory> 21 22 #include "ecmascript/mem/heap.h" 23 #include "ecmascript/mem/object_xray.h" 24 #include "ecmascript/mem/region.h" 25 #include "ecmascript/mem/remembered_set.h" 26 #include "ecmascript/mem/space.h" 27 #include "ecmascript/mem/tagged_object.h" 28 #include "ecmascript/platform/task.h" 29 #include "os/mutex.h" 30 31 namespace panda::ecmascript { 32 class JSHClass; 33 class TlabAllocator; 34 class ParallelEvacuation { 35 public: ParallelEvacuation(Heap * heap)36 ParallelEvacuation(Heap *heap) : heap_(heap), objXRay_(heap->GetEcmaVM()) {} 37 ~ParallelEvacuation() = default; 38 void Initialize(); 39 void Finalize(); 40 void Evacuate(); 41 GetPromotedSize()42 size_t GetPromotedSize() const 43 { 44 return promotedSize_; 45 } 46 47 private: 48 class EvacuationTask : public Task { 49 public: 50 EvacuationTask(ParallelEvacuation *evacuation); 51 ~EvacuationTask() override; 52 bool Run(uint32_t threadIndex) override; 53 54 NO_COPY_SEMANTIC(EvacuationTask); 55 NO_MOVE_SEMANTIC(EvacuationTask); 56 57 private: 58 ParallelEvacuation *evacuation_; 59 TlabAllocator *allocator_; 60 }; 61 62 class UpdateReferenceTask : public Task { 63 public: UpdateReferenceTask(ParallelEvacuation * evacuation)64 UpdateReferenceTask(ParallelEvacuation *evacuation) : evacuation_(evacuation) {}; 65 ~UpdateReferenceTask() override = default; 66 67 bool Run(uint32_t threadIndex) override; 68 69 NO_COPY_SEMANTIC(UpdateReferenceTask); 70 NO_MOVE_SEMANTIC(UpdateReferenceTask); 71 72 private: 73 ParallelEvacuation *evacuation_; 74 }; 75 76 class Fragment { 77 public: Fragment(ParallelEvacuation * evacuation,Region * region)78 Fragment(ParallelEvacuation *evacuation, Region *region) : evacuation_(evacuation), region_(region) {}; 79 virtual ~Fragment() = default; 80 virtual bool Process(bool isMain) = 0; GetRegion()81 inline Region *GetRegion() 82 { 83 return region_; 84 } 85 GetEvacuation()86 inline ParallelEvacuation *GetEvacuation() 87 { 88 return evacuation_; 89 } 90 protected: 91 ParallelEvacuation *evacuation_; 92 Region *region_; 93 }; 94 95 class EvacuationFragment : public Fragment { 96 public: EvacuationFragment(ParallelEvacuation * evacuation,Region * region)97 EvacuationFragment(ParallelEvacuation *evacuation, Region *region) : Fragment(evacuation, region) {} 98 bool Process(bool isMain) override; 99 }; 100 101 class UpdateRSetFragment : public Fragment { 102 public: UpdateRSetFragment(ParallelEvacuation * evacuation,Region * region)103 UpdateRSetFragment(ParallelEvacuation *evacuation, Region *region) : Fragment(evacuation, region) {} 104 bool Process(bool isMain) override; 105 }; 106 107 class UpdateNewRegionFragment : public Fragment { 108 public: UpdateNewRegionFragment(ParallelEvacuation * evacuation,Region * region)109 UpdateNewRegionFragment(ParallelEvacuation *evacuation, Region *region) : Fragment(evacuation, region) {} 110 bool Process(bool isMain) override; 111 }; 112 113 class UpdateAndSweepNewRegionFragment : public Fragment { 114 public: UpdateAndSweepNewRegionFragment(ParallelEvacuation * evacuation,Region * region)115 UpdateAndSweepNewRegionFragment(ParallelEvacuation *evacuation, Region *region) 116 : Fragment(evacuation, region) {} 117 bool Process(bool isMain) override; 118 }; 119 120 bool ProcessFragments(bool isMain = false); 121 122 void EvacuateSpace(); 123 bool EvacuateSpace(TlabAllocator *allocation, bool isMain = false); 124 void EvacuateRegion(TlabAllocator *allocator, Region *region); 125 inline void SetObjectFieldRSet(TaggedObject *object, JSHClass *cls); 126 127 inline bool IsWholeRegionEvacuate(Region *region); 128 void VerifyHeapObject(TaggedObject *object); 129 130 void UpdateReference(); 131 void UpdateRoot(); 132 void UpdateWeakReference(); 133 void UpdateRecordWeakReference(); 134 void UpdateRSet(Region *region); 135 void UpdateNewRegionReference(Region *region); 136 void UpdateAndSweepNewRegionReference(Region *region); 137 void UpdateNewObjectField(TaggedObject *object, JSHClass *cls); 138 139 inline bool UpdateObjectSlot(ObjectSlot &slot); 140 inline bool UpdateWeakObjectSlot(TaggedObject *object, ObjectSlot &slot); 141 142 inline std::unique_ptr<Fragment> GetFragmentSafe(); 143 inline void AddFragment(std::unique_ptr<Fragment> region); 144 145 inline int CalculateEvacuationThreadNum(); 146 inline int CalculateUpdateThreadNum(); 147 void WaitFinished(); 148 149 Heap *heap_; 150 TlabAllocator *allocator_; 151 ObjectXRay objXRay_; 152 153 uintptr_t waterLine_; 154 std::vector<std::unique_ptr<Fragment>> fragments_; 155 std::atomic_int parallel_ = 0; 156 os::memory::Mutex mutex_; 157 os::memory::ConditionVariable condition_; 158 std::atomic<size_t> promotedSize_ = 0; 159 }; 160 } // namespace panda::ecmascript 161 #endif // ECMASCRIPT_MEM_PARALLEL_EVACUATION_H 162