1 /* 2 * Copyright (c) 2022 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_SPARSE_SPACE_H 17 #define ECMASCRIPT_MEM_SPARSE_SPACE_H 18 19 #include "ecmascript/mem/space-inl.h" 20 #include "ecmascript/mem/mem_common.h" 21 22 #define CHECK_OBJECT_AND_INC_OBJ_SIZE(size) \ 23 if (object != 0) { \ 24 IncreaseLiveObjectSize(size); \ 25 if (!heap_->IsFullMark() || heap_->GetJSThread()->IsReadyToMark()) { \ 26 Region::ObjectAddressToRange(object)->IncreaseAliveObject(size); \ 27 } \ 28 return object; \ 29 } \ 30 31 enum class SweepState : uint8_t { 32 NO_SWEEP, 33 SWEEPING, 34 SWEPT 35 }; 36 37 namespace panda::ecmascript { 38 class LocalSpace; 39 40 class SparseSpace : public Space { 41 public: 42 explicit SparseSpace(Heap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity); ~SparseSpace()43 ~SparseSpace() override 44 { 45 delete allocator_; 46 } 47 NO_COPY_SEMANTIC(SparseSpace); 48 NO_MOVE_SEMANTIC(SparseSpace); 49 50 void Initialize() override; 51 void Reset(); 52 53 uintptr_t Allocate(size_t size, bool allowGC = true); 54 bool Expand(); 55 56 // For sweeping 57 void PrepareSweeping(); 58 void AsyncSweep(bool isMain); 59 void Sweep(); 60 61 bool TryFillSweptRegion(); 62 // Ensure All region finished sweeping 63 bool FinishFillSweptRegion(); 64 65 void AddSweepingRegion(Region *region); 66 void SortSweepingRegion(); 67 Region *GetSweepingRegionSafe(); 68 void AddSweptRegionSafe(Region *region); 69 Region *GetSweptRegionSafe(); 70 Region *TryToGetSuitableSweptRegion(size_t size); 71 72 void FreeRegion(Region *current, bool isMain = true); 73 void FreeLiveRange(Region *current, uintptr_t freeStart, uintptr_t freeEnd, bool isMain); 74 75 void DetachFreeObjectSet(Region *region); 76 77 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 78 void IterateOldToNewOverObjects( 79 const std::function<void(TaggedObject *object, JSTaggedValue value)> &visitor) const; 80 81 size_t GetHeapObjectSize() const; 82 83 void IncreaseAllocatedSize(size_t size); 84 IncreaseLiveObjectSize(size_t size)85 void IncreaseLiveObjectSize(size_t size) 86 { 87 liveObjectSize_ += size; 88 } 89 DecreaseLiveObjectSize(size_t size)90 void DecreaseLiveObjectSize(size_t size) 91 { 92 liveObjectSize_ -= size; 93 } 94 95 size_t GetTotalAllocatedSize() const; 96 97 protected: 98 FreeListAllocator *allocator_; 99 SweepState sweepState_ = SweepState::NO_SWEEP; 100 Heap *heap_ {nullptr}; 101 102 private: 103 // For sweeping 104 uintptr_t AllocateAfterSweepingCompleted(size_t size); 105 106 os::memory::Mutex lock_; 107 std::vector<Region *> sweepingList_; 108 std::vector<Region *> sweptList_; 109 size_t liveObjectSize_ {0}; 110 }; 111 112 class OldSpace : public SparseSpace { 113 public: 114 explicit OldSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 115 ~OldSpace() override = default; 116 NO_COPY_SEMANTIC(OldSpace); 117 NO_MOVE_SEMANTIC(OldSpace); 118 119 Region *TryToGetExclusiveRegion(size_t size); 120 121 // CSet 122 void SelectCSet(); 123 void CheckRegionSize(); 124 void RevertCSet(); 125 void ReclaimCSet(); 126 GetSelectedRegionNumber()127 unsigned long GetSelectedRegionNumber() const 128 { 129 return std::max(committedSize_ / PARTIAL_GC_MAX_COLLECT_REGION_RATE, PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE); 130 } 131 GetMergeSize()132 size_t GetMergeSize() const 133 { 134 return mergeSize_; 135 } 136 IncreaseMergeSize(size_t size)137 void IncreaseMergeSize(size_t size) 138 { 139 mergeSize_ += size; 140 } 141 ResetMergeSize()142 void ResetMergeSize() 143 { 144 mergeSize_ = 0; 145 } 146 147 template<class Callback> EnumerateCollectRegionSet(const Callback & cb)148 void EnumerateCollectRegionSet(const Callback &cb) const 149 { 150 for (Region *current : collectRegionSet_) { 151 if (current != nullptr) { 152 cb(current); 153 } 154 } 155 } 156 157 void Merge(LocalSpace *localSpace); 158 private: 159 static constexpr int64_t PARTIAL_GC_MAX_EVACUATION_SIZE = 4_MB; 160 static constexpr unsigned long long PARTIAL_GC_MAX_COLLECT_REGION_RATE = 2_MB; 161 static constexpr unsigned long long PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE = 16; 162 static constexpr size_t PARTIAL_GC_MIN_COLLECT_REGION_SIZE = 5; 163 164 CVector<Region *> collectRegionSet_; 165 os::memory::Mutex lock_; 166 size_t mergeSize_ {0}; 167 }; 168 169 class NonMovableSpace : public SparseSpace { 170 public: 171 explicit NonMovableSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 172 ~NonMovableSpace() override = default; 173 NO_COPY_SEMANTIC(NonMovableSpace); 174 NO_MOVE_SEMANTIC(NonMovableSpace); 175 }; 176 177 class AppSpawnSpace : public SparseSpace { 178 public: 179 explicit AppSpawnSpace(Heap *heap, size_t initialCapacity); 180 ~AppSpawnSpace() override = default; 181 NO_COPY_SEMANTIC(AppSpawnSpace); 182 NO_MOVE_SEMANTIC(AppSpawnSpace); 183 184 void IterateOverMarkedObjects(const std::function<void(TaggedObject *object)> &visitor) const; 185 }; 186 187 class LocalSpace : public SparseSpace { 188 public: 189 LocalSpace() = delete; 190 explicit LocalSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 191 ~LocalSpace() override = default; 192 NO_COPY_SEMANTIC(LocalSpace); 193 NO_MOVE_SEMANTIC(LocalSpace); 194 195 uintptr_t Allocate(size_t size, bool isExpand = true); 196 bool AddRegionToList(Region *region); 197 void FreeBumpPoint(); 198 void Stop(); 199 }; 200 201 class MachineCodeSpace : public SparseSpace { 202 public: 203 explicit MachineCodeSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 204 ~MachineCodeSpace() override = default; 205 NO_COPY_SEMANTIC(MachineCodeSpace); 206 NO_MOVE_SEMANTIC(MachineCodeSpace); // Note: Expand() left for define 207 }; 208 } // namespace panda::ecmascript 209 #endif // ECMASCRIPT_MEM_SPARSE_SPACE_H 210