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() const41 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 overShootSizeForConcurrentMark_ {0}; 71 size_t allocateAfterLastGC_ {0}; 72 size_t survivalObjectSize_ {0}; 73 uintptr_t waterLine_ {0}; 74 // This value is set in ConcurrentMark::InitializeMarking before post GC task, so do not need atomic store/load. 75 uintptr_t freshObjectWaterLine_ {0}; 76 }; 77 78 class EdenSpace : public LinearSpace { 79 public: 80 EdenSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 81 ~EdenSpace() override; 82 NO_COPY_SEMANTIC(EdenSpace); 83 NO_MOVE_SEMANTIC(EdenSpace); 84 85 void Initialize() override; 86 void Restart(); 87 88 uintptr_t AllocateSync(size_t size); 89 uintptr_t Allocate(size_t size); 90 bool Expand(); 91 void SetOverShootSize(size_t size); 92 GetWaterLine() const93 uintptr_t GetWaterLine() const 94 { 95 return waterLine_; 96 } GetTop() const97 uintptr_t GetTop() const 98 { 99 return allocator_.GetTop(); 100 } 101 size_t GetHeapObjectSize() const; 102 size_t GetSurvivalObjectSize() const; 103 size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 104 void ReclaimRegions(size_t cachedSize = 0); AllowTryEnable()105 void AllowTryEnable() 106 { 107 shouldTryEnable_ = true; 108 } ShouldTryEnable()109 bool ShouldTryEnable() 110 { 111 if (shouldTryEnable_) { 112 shouldTryEnable_ = false; 113 return true; 114 } 115 return false; 116 } 117 118 private: 119 Region *AllocRegion(); 120 121 static constexpr int GROWING_FACTOR = 2; 122 bool isFull_ {true}; 123 Mutex lock_; 124 MemMap memMap_; 125 std::deque<MemMap> freeRegions_; 126 bool shouldTryEnable_ {false}; 127 }; 128 129 class SemiSpace : public LinearSpace { 130 public: 131 SemiSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 132 ~SemiSpace() override = default; 133 NO_COPY_SEMANTIC(SemiSpace); 134 NO_MOVE_SEMANTIC(SemiSpace); 135 136 void Initialize() override; 137 void Restart(size_t overShootSize = 0); 138 size_t CalculateNewOverShootSize(); 139 bool CommittedSizeIsLarge(); 140 141 uintptr_t AllocateSync(size_t size); 142 143 void SetOverShootSize(size_t size); 144 void AddOverShootSize(size_t size); 145 bool AdjustCapacity(size_t allocatedSizeSinceGC, JSThread *thread); 146 void SetWaterLine(); 147 GetWaterLine() const148 uintptr_t GetWaterLine() const 149 { 150 return waterLine_; 151 } GetTop() const152 uintptr_t GetTop() const 153 { 154 return allocator_.GetTop(); 155 } 156 size_t GetHeapObjectSize() const; 157 size_t GetSurvivalObjectSize() const; 158 size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 159 160 bool SwapRegion(Region *region, SemiSpace *fromSpace); 161 162 private: 163 static constexpr int GROWING_FACTOR = 2; 164 Mutex lock_; 165 size_t minimumCapacity_; 166 }; 167 168 class SnapshotSpace : public LinearSpace { 169 public: 170 SnapshotSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 171 ~SnapshotSpace() override = default; 172 NO_COPY_SEMANTIC(SnapshotSpace); 173 NO_MOVE_SEMANTIC(SnapshotSpace); 174 GetHeapObjectSize() const175 size_t GetHeapObjectSize() const 176 { 177 return liveObjectSize_; 178 } 179 IncreaseLiveObjectSize(size_t size)180 void IncreaseLiveObjectSize(size_t size) 181 { 182 liveObjectSize_ += size; 183 } 184 185 private: 186 size_t liveObjectSize_ {0}; 187 }; 188 189 class ReadOnlySpace : public LinearSpace { 190 public: 191 ReadOnlySpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity, 192 MemSpaceType type = MemSpaceType::READ_ONLY_SPACE); 193 ~ReadOnlySpace() override = default; SetReadOnly()194 void SetReadOnly() 195 { 196 auto cb = [](Region *region) { 197 region->SetReadOnlyAndMarked(); 198 }; 199 EnumerateRegions(cb); 200 } 201 ClearReadOnly()202 void ClearReadOnly() 203 { 204 auto cb = [](Region *region) { 205 region->ClearReadOnly(); 206 }; 207 EnumerateRegions(cb); 208 } 209 210 NO_COPY_SEMANTIC(ReadOnlySpace); 211 NO_MOVE_SEMANTIC(ReadOnlySpace); 212 }; 213 } // namespace panda::ecmascript 214 #endif // ECMASCRIPT_MEM_LINEAR_SPACE_H 215