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 21namespace panda::ecmascript { 22class LinearSpace : public Space { 23public: 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 33 const uintptr_t *GetAllocationTopAddress() 34 { 35 return allocator_.GetTopAddress(); 36 } 37 const uintptr_t *GetAllocationEndAddress() 38 { 39 return allocator_.GetEndAddress(); 40 } 41 size_t GetOvershootSize() const 42 { 43 return overShootSize_; 44 } 45 void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize); 46 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 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 65protected: 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 78class EdenSpace : public LinearSpace { 79public: 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 93 uintptr_t GetWaterLine() const 94 { 95 return waterLine_; 96 } 97 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); 105 void AllowTryEnable() 106 { 107 shouldTryEnable_ = true; 108 } 109 bool ShouldTryEnable() 110 { 111 if (shouldTryEnable_) { 112 shouldTryEnable_ = false; 113 return true; 114 } 115 return false; 116 } 117 118private: 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 129class SemiSpace : public LinearSpace { 130public: 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 148 uintptr_t GetWaterLine() const 149 { 150 return waterLine_; 151 } 152 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 162private: 163 static constexpr int GROWING_FACTOR = 2; 164 Mutex lock_; 165 size_t minimumCapacity_; 166}; 167 168class SnapshotSpace : public LinearSpace { 169public: 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 175 size_t GetHeapObjectSize() const 176 { 177 return liveObjectSize_; 178 } 179 180 void IncreaseLiveObjectSize(size_t size) 181 { 182 liveObjectSize_ += size; 183 } 184 185private: 186 size_t liveObjectSize_ {0}; 187}; 188 189class ReadOnlySpace : public LinearSpace { 190public: 191 ReadOnlySpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity, 192 MemSpaceType type = MemSpaceType::READ_ONLY_SPACE); 193 ~ReadOnlySpace() override = default; 194 void SetReadOnly() 195 { 196 auto cb = [](Region *region) { 197 region->SetReadOnlyAndMarked(); 198 }; 199 EnumerateRegions(cb); 200 } 201 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