14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_MEM_LINEAR_SPACE_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_LINEAR_SPACE_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/mem/space-inl.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript { 224514f5e3Sopenharmony_ciclass LinearSpace : public Space { 234514f5e3Sopenharmony_cipublic: 244514f5e3Sopenharmony_ci LinearSpace(Heap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity); 254514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(LinearSpace); 264514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(LinearSpace); 274514f5e3Sopenharmony_ci uintptr_t Allocate(size_t size, bool isPromoted = false); 284514f5e3Sopenharmony_ci bool Expand(bool isPromoted); 294514f5e3Sopenharmony_ci void Stop(); 304514f5e3Sopenharmony_ci void ResetAllocator(); 314514f5e3Sopenharmony_ci void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ci const uintptr_t *GetAllocationTopAddress() 344514f5e3Sopenharmony_ci { 354514f5e3Sopenharmony_ci return allocator_.GetTopAddress(); 364514f5e3Sopenharmony_ci } 374514f5e3Sopenharmony_ci const uintptr_t *GetAllocationEndAddress() 384514f5e3Sopenharmony_ci { 394514f5e3Sopenharmony_ci return allocator_.GetEndAddress(); 404514f5e3Sopenharmony_ci } 414514f5e3Sopenharmony_ci size_t GetOvershootSize() const 424514f5e3Sopenharmony_ci { 434514f5e3Sopenharmony_ci return overShootSize_; 444514f5e3Sopenharmony_ci } 454514f5e3Sopenharmony_ci void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize); 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_ci void RecordCurrentRegionAsHalfFresh() 484514f5e3Sopenharmony_ci { 494514f5e3Sopenharmony_ci Region *region = GetCurrentRegion(); 504514f5e3Sopenharmony_ci ASSERT(region != nullptr); 514514f5e3Sopenharmony_ci ASSERT(!region->IsFreshRegion() && !region->IsHalfFreshRegion()); 524514f5e3Sopenharmony_ci region->SetRegionTypeFlag(RegionTypeFlag::HALF_FRESH); 534514f5e3Sopenharmony_ci freshObjectWaterLine_ = allocator_.GetTop(); 544514f5e3Sopenharmony_ci ASSERT(region->InRange(freshObjectWaterLine_)); 554514f5e3Sopenharmony_ci } 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_ci bool IsFreshObjectInHalfFreshRegion(TaggedObject *object) 584514f5e3Sopenharmony_ci { 594514f5e3Sopenharmony_ci uintptr_t addr = ToUintPtr(object); 604514f5e3Sopenharmony_ci ASSERT(Region::ObjectAddressToRange(object)->IsHalfFreshRegion()); 614514f5e3Sopenharmony_ci ASSERT(Region::ObjectAddressToRange(object)->InRange(addr)); 624514f5e3Sopenharmony_ci return addr >= freshObjectWaterLine_; 634514f5e3Sopenharmony_ci } 644514f5e3Sopenharmony_ci 654514f5e3Sopenharmony_ciprotected: 664514f5e3Sopenharmony_ci Heap *localHeap_; 674514f5e3Sopenharmony_ci JSThread *thread_ {nullptr}; 684514f5e3Sopenharmony_ci BumpPointerAllocator allocator_; 694514f5e3Sopenharmony_ci size_t overShootSize_ {0}; 704514f5e3Sopenharmony_ci size_t overShootSizeForConcurrentMark_ {0}; 714514f5e3Sopenharmony_ci size_t allocateAfterLastGC_ {0}; 724514f5e3Sopenharmony_ci size_t survivalObjectSize_ {0}; 734514f5e3Sopenharmony_ci uintptr_t waterLine_ {0}; 744514f5e3Sopenharmony_ci // This value is set in ConcurrentMark::InitializeMarking before post GC task, so do not need atomic store/load. 754514f5e3Sopenharmony_ci uintptr_t freshObjectWaterLine_ {0}; 764514f5e3Sopenharmony_ci}; 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_ciclass EdenSpace : public LinearSpace { 794514f5e3Sopenharmony_cipublic: 804514f5e3Sopenharmony_ci EdenSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 814514f5e3Sopenharmony_ci ~EdenSpace() override; 824514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(EdenSpace); 834514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(EdenSpace); 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci void Initialize() override; 864514f5e3Sopenharmony_ci void Restart(); 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ci uintptr_t AllocateSync(size_t size); 894514f5e3Sopenharmony_ci uintptr_t Allocate(size_t size); 904514f5e3Sopenharmony_ci bool Expand(); 914514f5e3Sopenharmony_ci void SetOverShootSize(size_t size); 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ci uintptr_t GetWaterLine() const 944514f5e3Sopenharmony_ci { 954514f5e3Sopenharmony_ci return waterLine_; 964514f5e3Sopenharmony_ci } 974514f5e3Sopenharmony_ci uintptr_t GetTop() const 984514f5e3Sopenharmony_ci { 994514f5e3Sopenharmony_ci return allocator_.GetTop(); 1004514f5e3Sopenharmony_ci } 1014514f5e3Sopenharmony_ci size_t GetHeapObjectSize() const; 1024514f5e3Sopenharmony_ci size_t GetSurvivalObjectSize() const; 1034514f5e3Sopenharmony_ci size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 1044514f5e3Sopenharmony_ci void ReclaimRegions(size_t cachedSize = 0); 1054514f5e3Sopenharmony_ci void AllowTryEnable() 1064514f5e3Sopenharmony_ci { 1074514f5e3Sopenharmony_ci shouldTryEnable_ = true; 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci bool ShouldTryEnable() 1104514f5e3Sopenharmony_ci { 1114514f5e3Sopenharmony_ci if (shouldTryEnable_) { 1124514f5e3Sopenharmony_ci shouldTryEnable_ = false; 1134514f5e3Sopenharmony_ci return true; 1144514f5e3Sopenharmony_ci } 1154514f5e3Sopenharmony_ci return false; 1164514f5e3Sopenharmony_ci } 1174514f5e3Sopenharmony_ci 1184514f5e3Sopenharmony_ciprivate: 1194514f5e3Sopenharmony_ci Region *AllocRegion(); 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci static constexpr int GROWING_FACTOR = 2; 1224514f5e3Sopenharmony_ci bool isFull_ {true}; 1234514f5e3Sopenharmony_ci Mutex lock_; 1244514f5e3Sopenharmony_ci MemMap memMap_; 1254514f5e3Sopenharmony_ci std::deque<MemMap> freeRegions_; 1264514f5e3Sopenharmony_ci bool shouldTryEnable_ {false}; 1274514f5e3Sopenharmony_ci}; 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ciclass SemiSpace : public LinearSpace { 1304514f5e3Sopenharmony_cipublic: 1314514f5e3Sopenharmony_ci SemiSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 1324514f5e3Sopenharmony_ci ~SemiSpace() override = default; 1334514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(SemiSpace); 1344514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(SemiSpace); 1354514f5e3Sopenharmony_ci 1364514f5e3Sopenharmony_ci void Initialize() override; 1374514f5e3Sopenharmony_ci void Restart(size_t overShootSize = 0); 1384514f5e3Sopenharmony_ci size_t CalculateNewOverShootSize(); 1394514f5e3Sopenharmony_ci bool CommittedSizeIsLarge(); 1404514f5e3Sopenharmony_ci 1414514f5e3Sopenharmony_ci uintptr_t AllocateSync(size_t size); 1424514f5e3Sopenharmony_ci 1434514f5e3Sopenharmony_ci void SetOverShootSize(size_t size); 1444514f5e3Sopenharmony_ci void AddOverShootSize(size_t size); 1454514f5e3Sopenharmony_ci bool AdjustCapacity(size_t allocatedSizeSinceGC, JSThread *thread); 1464514f5e3Sopenharmony_ci void SetWaterLine(); 1474514f5e3Sopenharmony_ci 1484514f5e3Sopenharmony_ci uintptr_t GetWaterLine() const 1494514f5e3Sopenharmony_ci { 1504514f5e3Sopenharmony_ci return waterLine_; 1514514f5e3Sopenharmony_ci } 1524514f5e3Sopenharmony_ci uintptr_t GetTop() const 1534514f5e3Sopenharmony_ci { 1544514f5e3Sopenharmony_ci return allocator_.GetTop(); 1554514f5e3Sopenharmony_ci } 1564514f5e3Sopenharmony_ci size_t GetHeapObjectSize() const; 1574514f5e3Sopenharmony_ci size_t GetSurvivalObjectSize() const; 1584514f5e3Sopenharmony_ci size_t GetAllocatedSizeSinceGC(uintptr_t top = 0) const; 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci bool SwapRegion(Region *region, SemiSpace *fromSpace); 1614514f5e3Sopenharmony_ci 1624514f5e3Sopenharmony_ciprivate: 1634514f5e3Sopenharmony_ci static constexpr int GROWING_FACTOR = 2; 1644514f5e3Sopenharmony_ci Mutex lock_; 1654514f5e3Sopenharmony_ci size_t minimumCapacity_; 1664514f5e3Sopenharmony_ci}; 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ciclass SnapshotSpace : public LinearSpace { 1694514f5e3Sopenharmony_cipublic: 1704514f5e3Sopenharmony_ci SnapshotSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity); 1714514f5e3Sopenharmony_ci ~SnapshotSpace() override = default; 1724514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(SnapshotSpace); 1734514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(SnapshotSpace); 1744514f5e3Sopenharmony_ci 1754514f5e3Sopenharmony_ci size_t GetHeapObjectSize() const 1764514f5e3Sopenharmony_ci { 1774514f5e3Sopenharmony_ci return liveObjectSize_; 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci 1804514f5e3Sopenharmony_ci void IncreaseLiveObjectSize(size_t size) 1814514f5e3Sopenharmony_ci { 1824514f5e3Sopenharmony_ci liveObjectSize_ += size; 1834514f5e3Sopenharmony_ci } 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_ciprivate: 1864514f5e3Sopenharmony_ci size_t liveObjectSize_ {0}; 1874514f5e3Sopenharmony_ci}; 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ciclass ReadOnlySpace : public LinearSpace { 1904514f5e3Sopenharmony_cipublic: 1914514f5e3Sopenharmony_ci ReadOnlySpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity, 1924514f5e3Sopenharmony_ci MemSpaceType type = MemSpaceType::READ_ONLY_SPACE); 1934514f5e3Sopenharmony_ci ~ReadOnlySpace() override = default; 1944514f5e3Sopenharmony_ci void SetReadOnly() 1954514f5e3Sopenharmony_ci { 1964514f5e3Sopenharmony_ci auto cb = [](Region *region) { 1974514f5e3Sopenharmony_ci region->SetReadOnlyAndMarked(); 1984514f5e3Sopenharmony_ci }; 1994514f5e3Sopenharmony_ci EnumerateRegions(cb); 2004514f5e3Sopenharmony_ci } 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci void ClearReadOnly() 2034514f5e3Sopenharmony_ci { 2044514f5e3Sopenharmony_ci auto cb = [](Region *region) { 2054514f5e3Sopenharmony_ci region->ClearReadOnly(); 2064514f5e3Sopenharmony_ci }; 2074514f5e3Sopenharmony_ci EnumerateRegions(cb); 2084514f5e3Sopenharmony_ci } 2094514f5e3Sopenharmony_ci 2104514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(ReadOnlySpace); 2114514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(ReadOnlySpace); 2124514f5e3Sopenharmony_ci}; 2134514f5e3Sopenharmony_ci} // namespace panda::ecmascript 2144514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_LINEAR_SPACE_H 215