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 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 SemiSpace : public LinearSpace { 79 public: 80 SemiSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 81 ~SemiSpace() override = default; 82 NO_COPY_SEMANTIC(SemiSpace); 83 NO_MOVE_SEMANTIC(SemiSpace); 84 85 void Initialize() override; 86 void Restart(size_t overShootSize = 0); 87 size_t CalculateNewOverShootSize(); 88 bool CommittedSizeIsLarge(); 89 90 uintptr_t AllocateSync(size_t size); 91 92 void SetOverShootSize(size_t size); 93 void AddOverShootSize(size_t size); 94 bool AdjustCapacity(size_t allocatedSizeSinceGC, JSThread *thread); 95 void SetWaterLine(); 96 GetWaterLine()97 uintptr_t GetWaterLine() const 98 { 99 return waterLine_; 100 } GetTop()101 uintptr_t GetTop() const 102 { 103 return allocator_.GetTop(); 104 } 105 size_t GetHeapObjectSize() const; 106 size_t GetSurvivalObjectSize() const; 107 size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 108 109 bool SwapRegion(Region *region, SemiSpace *fromSpace); 110 111 private: 112 static constexpr int GROWING_FACTOR = 2; 113 Mutex lock_; 114 size_t minimumCapacity_; 115 }; 116 117 class SnapshotSpace : public LinearSpace { 118 public: 119 SnapshotSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 120 ~SnapshotSpace() override = default; 121 NO_COPY_SEMANTIC(SnapshotSpace); 122 NO_MOVE_SEMANTIC(SnapshotSpace); 123 GetHeapObjectSize()124 size_t GetHeapObjectSize() const 125 { 126 return liveObjectSize_; 127 } 128 IncreaseLiveObjectSize(size_t size)129 void IncreaseLiveObjectSize(size_t size) 130 { 131 liveObjectSize_ += size; 132 } 133 134 private: 135 size_t liveObjectSize_ {0}; 136 }; 137 138 class ReadOnlySpace : public LinearSpace { 139 public: 140 ReadOnlySpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity, 141 MemSpaceType type = MemSpaceType::READ_ONLY_SPACE); 142 ~ReadOnlySpace() override = default; SetReadOnly()143 void SetReadOnly() 144 { 145 auto cb = [](Region *region) { 146 region->SetReadOnlyAndMarked(); 147 }; 148 EnumerateRegions(cb); 149 } 150 ClearReadOnly()151 void ClearReadOnly() 152 { 153 auto cb = [](Region *region) { 154 region->ClearReadOnly(); 155 }; 156 EnumerateRegions(cb); 157 } 158 159 NO_COPY_SEMANTIC(ReadOnlySpace); 160 NO_MOVE_SEMANTIC(ReadOnlySpace); 161 }; 162 } // namespace panda::ecmascript 163 #endif // ECMASCRIPT_MEM_LINEAR_SPACE_H 164