1 /* 2 * Copyright (c) 2024 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_SHARED_SPACE_H 17 #define ECMASCRIPT_MEM_SHARED_SHARED_SPACE_H 18 19 #include "ecmascript/mem/mem_common.h" 20 #include "ecmascript/mem/sparse_space.h" 21 22 namespace panda::ecmascript { 23 #define CHECK_SOBJECT_NOT_NULL() \ 24 if (object != 0) { \ 25 return object; \ 26 } 27 28 class SharedHeap; 29 class SharedLocalSpace; 30 31 class SharedSparseSpace : public Space { 32 public: 33 SharedSparseSpace(SharedHeap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity); 34 ~SharedSparseSpace() override 35 { 36 delete allocator_; 37 } 38 NO_COPY_SEMANTIC(SharedSparseSpace); 39 NO_MOVE_SEMANTIC(SharedSparseSpace); 40 41 void Reset(); 42 43 uintptr_t AllocateWithoutGC(JSThread *thread, size_t size); 44 45 uintptr_t Allocate(JSThread *thread, size_t size, bool allowGC = true); 46 uintptr_t TryAllocateAndExpand(JSThread *thread, size_t size, bool expand); 47 48 // For work deserialize 49 void ResetTopPointer(uintptr_t top); 50 uintptr_t AllocateNoGCAndExpand(JSThread *thread, size_t size); 51 Region *AllocateDeserializeRegion(JSThread *thread); 52 void MergeDeserializeAllocateRegions(const std::vector<Region *> &allocateRegions); 53 54 // For sweeping 55 void PrepareSweeping(); 56 void AsyncSweep(bool isMain); 57 void Sweep(); 58 59 bool TryFillSweptRegion(); 60 // Ensure All region finished sweeping 61 bool FinishFillSweptRegion(); 62 63 void AddSweepingRegion(Region *region); 64 void SortSweepingRegion(); 65 Region *GetSweepingRegionSafe(); 66 void AddSweptRegionSafe(Region *region); 67 Region *GetSweptRegionSafe(); 68 69 void FreeRegion(Region *current, bool isMain = true); 70 void FreeLiveRange(uintptr_t freeStart, uintptr_t freeEnd, bool isMain); 71 72 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 73 74 size_t GetHeapObjectSize() const; 75 76 void IncreaseAllocatedSize(size_t size); 77 IncreaseLiveObjectSize(size_t size)78 void IncreaseLiveObjectSize(size_t size) 79 { 80 liveObjectSize_ += size; 81 } 82 DecreaseLiveObjectSize(size_t size)83 void DecreaseLiveObjectSize(size_t size) 84 { 85 liveObjectSize_ -= size; 86 } 87 CommittedSizeExceed()88 bool CommittedSizeExceed() 89 { 90 return committedSize_ >= maximumCapacity_ + outOfMemoryOvershootSize_; 91 } 92 93 void CheckAndTriggerLocalFullMark(); 94 95 size_t GetTotalAllocatedSize() const; 96 97 void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize); 98 99 void DetachFreeObjectSet(Region *region); 100 101 protected: 102 bool Expand(JSThread *thread); 103 FreeListAllocator<FreeObject> *allocator_; 104 SweepState sweepState_ = SweepState::NO_SWEEP; 105 SharedHeap *sHeap_ {nullptr}; 106 107 private: 108 static constexpr double LIVE_OBJECT_SIZE_RATIO = 0.8; 109 110 uintptr_t AllocateWithExpand(JSThread *thread, size_t size); 111 uintptr_t TryAllocate(JSThread *thread, size_t size); 112 // For sweeping 113 uintptr_t AllocateAfterSweepingCompleted(JSThread *thread, size_t size); 114 void IncAllocSObjectSize(uintptr_t object, size_t size); 115 116 Mutex lock_; 117 Mutex allocateLock_; 118 std::vector<Region *> sweepingList_; 119 std::vector<Region *> sweptList_; 120 size_t liveObjectSize_ {0}; 121 size_t triggerLocalFullMarkLimit_ {0}; 122 }; 123 124 class SharedAppSpawnSpace : public SharedSparseSpace { 125 public: 126 SharedAppSpawnSpace(SharedHeap *heap, size_t initialCapacity); 127 ~SharedAppSpawnSpace() override = default; 128 NO_COPY_SEMANTIC(SharedAppSpawnSpace); 129 NO_MOVE_SEMANTIC(SharedAppSpawnSpace); 130 131 void IterateOverMarkedObjects(const std::function<void(TaggedObject *object)> &visitor) const; 132 }; 133 134 class SharedNonMovableSpace : public SharedSparseSpace { 135 public: 136 SharedNonMovableSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity); 137 ~SharedNonMovableSpace() override = default; 138 NO_COPY_SEMANTIC(SharedNonMovableSpace); 139 NO_MOVE_SEMANTIC(SharedNonMovableSpace); 140 }; 141 142 class SharedOldSpace : public SharedSparseSpace { 143 public: 144 SharedOldSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity); 145 ~SharedOldSpace() override = default; GetMergeSize() const146 size_t GetMergeSize() const 147 { 148 return mergeSize_; 149 } 150 IncreaseMergeSize(size_t size)151 void IncreaseMergeSize(size_t size) 152 { 153 mergeSize_ += size; 154 } 155 ResetMergeSize()156 void ResetMergeSize() 157 { 158 mergeSize_ = 0; 159 } 160 161 void Merge(SharedLocalSpace *localSpace); 162 NO_COPY_SEMANTIC(SharedOldSpace); 163 NO_MOVE_SEMANTIC(SharedOldSpace); 164 Mutex lock_; 165 size_t mergeSize_ {0}; 166 }; 167 168 class SharedLocalSpace : public SharedSparseSpace { 169 public: 170 SharedLocalSpace() = delete; 171 SharedLocalSpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity); 172 ~SharedLocalSpace() override = default; 173 NO_COPY_SEMANTIC(SharedLocalSpace); 174 NO_MOVE_SEMANTIC(SharedLocalSpace); 175 176 uintptr_t Allocate(size_t size, bool isExpand = true); 177 bool AddRegionToList(Region *region); 178 void FreeBumpPoint(); 179 void Stop(); 180 }; 181 182 class SharedReadOnlySpace : public Space { 183 public: 184 SharedReadOnlySpace(SharedHeap *heap, size_t initialCapacity, size_t maximumCapacity); 185 ~SharedReadOnlySpace() override = default; SetReadOnly()186 void SetReadOnly() 187 { 188 auto cb = [](Region *region) { 189 region->SetReadOnlyAndMarked(); 190 }; 191 EnumerateRegions(cb); 192 } 193 194 void IterateOverObjects(const std::function<void(TaggedObject *object)> &visitor) const; 195 ClearReadOnly()196 void ClearReadOnly() 197 { 198 auto cb = [](Region *region) { 199 region->ClearReadOnly(); 200 }; 201 EnumerateRegions(cb); 202 } 203 204 bool Expand(JSThread *thread); 205 206 uintptr_t Allocate(JSThread *thread, size_t size); 207 208 NO_COPY_SEMANTIC(SharedReadOnlySpace); 209 NO_MOVE_SEMANTIC(SharedReadOnlySpace); 210 211 private: 212 Mutex allocateLock_; 213 BumpPointerAllocator allocator_; 214 }; 215 216 class SharedHugeObjectSpace : public Space { 217 public: 218 SharedHugeObjectSpace(BaseHeap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 219 size_t maximumCapacity); 220 ~SharedHugeObjectSpace() override = default; 221 NO_COPY_SEMANTIC(SharedHugeObjectSpace); 222 NO_MOVE_SEMANTIC(SharedHugeObjectSpace); 223 // Sometimes it is unsafe to checkSafePoint here, e.g. in deserialize, if do checkSafePoint JSThread may be 224 // suspended and then do SharedGC, which will free some regions in SharedHeap that are allocated at the beginning 225 // of deserializing for further object allocating, but no object has been allocated on at this moment. 226 uintptr_t Allocate(JSThread *thread, size_t objectSize, AllocateEventType allocType = AllocateEventType::NORMAL); 227 void Sweep(); 228 size_t GetHeapObjectSize() const; 229 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 230 231 void ReclaimHugeRegion(); 232 233 void InvokeAllocationInspector(Address object, size_t objectSize); 234 CommittedSizeExceed(size_t size = 0) const235 bool CommittedSizeExceed(size_t size = 0) const 236 { 237 return committedSize_ + size >= maximumCapacity_ + outOfMemoryOvershootSize_; 238 } 239 240 void CheckAndTriggerLocalFullMark(JSThread *thread, size_t size); 241 private: 242 static constexpr size_t HUGE_OBJECT_BITSET_SIZE = 16; 243 static constexpr double HUGE_OBJECT_SIZE_RATIO = 0.8; 244 245 size_t triggerLocalFullMarkLimit_ {0}; 246 EcmaList<Region> hugeNeedFreeList_ {}; 247 Mutex allocateLock_; 248 }; 249 } // namespace panda::ecmascript 250 #endif // ECMASCRIPT_MEM_SHARED_SHARED_SPACE_H 251