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 21 #define CHECK_OBJECT_AND_INC_OBJ_SIZE(size) \ 22 if (object != 0) { \ 23 IncrementLiveObjectSize(size); \ 24 return object; \ 25 } 26 27 enum class SweepState : uint8_t { 28 NO_SWEEP, 29 SWEEPING, 30 SWEPT 31 }; 32 33 namespace panda::ecmascript { 34 class LocalSpace; 35 36 class SparseSpace : public Space { 37 public: 38 explicit SparseSpace(Heap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity); ~SparseSpace()39 ~SparseSpace() 40 { 41 delete allocator_; 42 } 43 NO_COPY_SEMANTIC(SparseSpace); 44 NO_MOVE_SEMANTIC(SparseSpace); 45 46 void Initialize() override; 47 void Reset(); 48 49 uintptr_t Allocate(size_t size, bool isAllowGC = true); 50 bool Expand(); 51 52 // For sweeping 53 void PrepareSweeping(); 54 void AsyncSweeping(bool isMain); 55 void Sweeping(); 56 57 bool FillSweptRegion(); 58 59 void AddSweepingRegion(Region *region); 60 void SortSweepingRegion(); 61 Region *GetSweepingRegionSafe(); 62 void AddSweptRegionSafe(Region *region); 63 Region *GetSweptRegionSafe(); 64 65 void FreeRegion(Region *current, bool isMain = true); 66 void FreeLiveRange(Region *current, uintptr_t freeStart, uintptr_t freeEnd, bool isMain); 67 68 void DetachFreeObjectSet(Region *region); 69 70 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 71 72 size_t GetHeapObjectSize() const; IncrementLiveObjectSize(size_t size)73 void IncrementLiveObjectSize(size_t size) 74 { 75 liveObjectSize_ += size; 76 } 77 DecrementLiveObjectSize(size_t size)78 void DecrementLiveObjectSize(size_t size) 79 { 80 liveObjectSize_ -= size; 81 } 82 83 size_t GetTotalAllocatedSize() const; 84 85 protected: 86 FreeListAllocator *allocator_; 87 SweepState sweepState_ = SweepState::NO_SWEEP; 88 89 private: 90 // For sweeping 91 uintptr_t AllocateAfterSweepingCompleted(size_t size); 92 93 os::memory::Mutex lock_; 94 std::vector<Region *> sweepingList_; 95 std::vector<Region *> sweptList_; 96 size_t liveObjectSize_ {0}; 97 }; 98 99 class OldSpace : public SparseSpace { 100 public: 101 explicit OldSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 102 ~OldSpace() override = default; 103 NO_COPY_SEMANTIC(OldSpace); 104 NO_MOVE_SEMANTIC(OldSpace); 105 106 /* The most extreme situation: 107 * All the younger generation were promoted, and there was no free space in the old space. 108 */ CanExpand(size_t promoteSize)109 bool CanExpand(size_t promoteSize) 110 { 111 return initialCapacity_ > committedSize_ + promoteSize; 112 } 113 Region *TryToGetExclusiveRegion(size_t size); 114 115 // CSet 116 void SelectCSet(); 117 void CheckRegionSize(); 118 void RevertCSet(); 119 void ReclaimCSet(); IsCSetEmpty()120 bool IsCSetEmpty() const 121 { 122 return isCSetEmpty_; 123 } GetSelectedRegionNumber()124 unsigned long GetSelectedRegionNumber() const 125 { 126 return std::max(committedSize_ / PARTIAL_GC_MAX_COLLECT_REGION_RATE, PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE); 127 } 128 129 template<class Callback> EnumerateCollectRegionSet(const Callback & cb)130 void EnumerateCollectRegionSet(const Callback &cb) const 131 { 132 for (Region *current : collectRegionSet_) { 133 if (current != nullptr) { 134 cb(current); 135 } 136 } 137 } 138 139 void Merge(LocalSpace *localSpace); 140 private: 141 static constexpr unsigned long PARTIAL_GC_MAX_COLLECT_REGION_RATE = 1024 * 1024 * 2; 142 static constexpr unsigned long PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE = 16; 143 static constexpr size_t PARTIAL_GC_MIN_COLLECT_REGION_SIZE = 5; 144 145 CVector<Region *> collectRegionSet_; 146 bool isCSetEmpty_ {true}; 147 os::memory::Mutex lock_; 148 }; 149 150 class NonMovableSpace : public SparseSpace { 151 public: 152 explicit NonMovableSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 153 ~NonMovableSpace() override = default; 154 NO_COPY_SEMANTIC(NonMovableSpace); 155 NO_MOVE_SEMANTIC(NonMovableSpace); 156 }; 157 158 class LocalSpace : public SparseSpace { 159 public: 160 LocalSpace() = delete; 161 explicit LocalSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 162 ~LocalSpace() override = default; 163 NO_COPY_SEMANTIC(LocalSpace); 164 NO_MOVE_SEMANTIC(LocalSpace); 165 166 uintptr_t Allocate(size_t size, bool isExpand = true); 167 bool AddRegionToList(Region *region); 168 void FreeBumpPoint(); 169 }; 170 171 class MachineCodeSpace : public SparseSpace { 172 public: 173 explicit MachineCodeSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 174 ~MachineCodeSpace() override = default; 175 NO_COPY_SEMANTIC(MachineCodeSpace); 176 NO_MOVE_SEMANTIC(MachineCodeSpace); // Note: Expand() left for define 177 }; 178 } // namespace panda::ecmascript 179 #endif // ECMASCRIPT_MEM_SPARSE_SPACE_H 180