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_LINEAR_SPACE_H 17 #define ECMASCRIPT_MEM_LINEAR_SPACE_H 18 19 #include "ecmascript/mem/space-inl.h" 20 21 namespace panda::ecmascript { 22 class LinearSpace : public Space { 23 public: 24 LinearSpace(Heap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity); 25 NO_COPY_SEMANTIC(LinearSpace); 26 NO_MOVE_SEMANTIC(LinearSpace); 27 uintptr_t Allocate(size_t size, bool isPromoted = false); 28 bool Expand(bool isPromoted); 29 void Stop(); 30 void ResetAllocator(); 31 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 32 GetAllocationTopAddress()33 const uintptr_t *GetAllocationTopAddress() 34 { 35 return allocator_.GetTopAddress(); 36 } GetAllocationEndAddress()37 const uintptr_t *GetAllocationEndAddress() 38 { 39 return allocator_.GetEndAddress(); 40 } GetOvershootSize()41 size_t GetOvershootSize() const 42 { 43 return overShootSize_; 44 } 45 void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize); 46 RecordCurrentRegionAsHalfFresh()47 void RecordCurrentRegionAsHalfFresh() 48 { 49 Region *region = GetCurrentRegion(); 50 ASSERT(region != nullptr); 51 ASSERT(!region->IsFreshRegion() && !region->IsHalfFreshRegion()); 52 region->SetRegionTypeFlag(RegionTypeFlag::HALF_FRESH); 53 freshObjectWaterLine_ = allocator_.GetTop(); 54 ASSERT(region->InRange(freshObjectWaterLine_)); 55 } 56 IsFreshObjectInHalfFreshRegion(TaggedObject * object)57 bool IsFreshObjectInHalfFreshRegion(TaggedObject *object) 58 { 59 uintptr_t addr = ToUintPtr(object); 60 ASSERT(Region::ObjectAddressToRange(object)->IsHalfFreshRegion()); 61 ASSERT(Region::ObjectAddressToRange(object)->InRange(addr)); 62 return addr >= freshObjectWaterLine_; 63 } 64 65 protected: 66 Heap *localHeap_; 67 JSThread *thread_ {nullptr}; 68 BumpPointerAllocator allocator_; 69 size_t overShootSize_ {0}; 70 size_t allocateAfterLastGC_ {0}; 71 size_t survivalObjectSize_ {0}; 72 uintptr_t waterLine_ {0}; 73 // This value is set in ConcurrentMark::InitializeMarking before post GC task, so do not need atomic store/load. 74 uintptr_t freshObjectWaterLine_ {0}; 75 }; 76 77 class EdenSpace : public LinearSpace { 78 public: 79 EdenSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 80 ~EdenSpace() override; 81 NO_COPY_SEMANTIC(EdenSpace); 82 NO_MOVE_SEMANTIC(EdenSpace); 83 84 void Initialize() override; 85 void Restart(); 86 87 uintptr_t AllocateSync(size_t size); 88 uintptr_t Allocate(size_t size); 89 bool Expand(); 90 void SetOverShootSize(size_t size); 91 GetWaterLine()92 uintptr_t GetWaterLine() const 93 { 94 return waterLine_; 95 } GetTop()96 uintptr_t GetTop() const 97 { 98 return allocator_.GetTop(); 99 } 100 size_t GetHeapObjectSize() const; 101 size_t GetSurvivalObjectSize() const; 102 size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 103 void ReclaimRegions(size_t cachedSize = 0); AllowTryEnable()104 void AllowTryEnable() 105 { 106 shouldTryEnable_ = true; 107 } ShouldTryEnable()108 bool ShouldTryEnable() 109 { 110 if (shouldTryEnable_) { 111 shouldTryEnable_ = false; 112 return true; 113 } 114 return false; 115 } 116 117 private: 118 Region *AllocRegion(); 119 120 static constexpr int GROWING_FACTOR = 2; 121 bool isFull_ {true}; 122 Mutex lock_; 123 MemMap memMap_; 124 std::deque<MemMap> freeRegions_; 125 bool shouldTryEnable_ {false}; 126 }; 127 128 class SemiSpace : public LinearSpace { 129 public: 130 SemiSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 131 ~SemiSpace() override = default; 132 NO_COPY_SEMANTIC(SemiSpace); 133 NO_MOVE_SEMANTIC(SemiSpace); 134 135 void Initialize() override; 136 void Restart(size_t overShootSize = 0); 137 size_t CalculateNewOverShootSize(); 138 bool CommittedSizeIsLarge(); 139 140 uintptr_t AllocateSync(size_t size); 141 142 void SetOverShootSize(size_t size); 143 bool AdjustCapacity(size_t allocatedSizeSinceGC, JSThread *thread); 144 void SetWaterLine(); 145 GetWaterLine()146 uintptr_t GetWaterLine() const 147 { 148 return waterLine_; 149 } GetTop()150 uintptr_t GetTop() const 151 { 152 return allocator_.GetTop(); 153 } 154 size_t GetHeapObjectSize() const; 155 size_t GetSurvivalObjectSize() const; 156 size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 157 158 bool SwapRegion(Region *region, SemiSpace *fromSpace); 159 160 private: 161 static constexpr int GROWING_FACTOR = 2; 162 Mutex lock_; 163 size_t minimumCapacity_; 164 }; 165 166 class SnapshotSpace : public LinearSpace { 167 public: 168 SnapshotSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 169 ~SnapshotSpace() override = default; 170 NO_COPY_SEMANTIC(SnapshotSpace); 171 NO_MOVE_SEMANTIC(SnapshotSpace); 172 GetHeapObjectSize()173 size_t GetHeapObjectSize() const 174 { 175 return liveObjectSize_; 176 } 177 IncreaseLiveObjectSize(size_t size)178 void IncreaseLiveObjectSize(size_t size) 179 { 180 liveObjectSize_ += size; 181 } 182 183 private: 184 size_t liveObjectSize_ {0}; 185 }; 186 187 class ReadOnlySpace : public LinearSpace { 188 public: 189 ReadOnlySpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity, 190 MemSpaceType type = MemSpaceType::READ_ONLY_SPACE); 191 ~ReadOnlySpace() override = default; SetReadOnly()192 void SetReadOnly() 193 { 194 auto cb = [](Region *region) { 195 region->SetReadOnlyAndMarked(); 196 }; 197 EnumerateRegions(cb); 198 } 199 ClearReadOnly()200 void ClearReadOnly() 201 { 202 auto cb = [](Region *region) { 203 region->ClearReadOnly(); 204 }; 205 EnumerateRegions(cb); 206 } 207 208 NO_COPY_SEMANTIC(ReadOnlySpace); 209 NO_MOVE_SEMANTIC(ReadOnlySpace); 210 }; 211 } // namespace panda::ecmascript 212 #endif // ECMASCRIPT_MEM_LINEAR_SPACE_H 213