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