14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-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_SPACE_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_SPACE_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/mem/allocation_inspector.h" 204514f5e3Sopenharmony_ci#include "ecmascript/mem/allocator.h" 214514f5e3Sopenharmony_ci#include "ecmascript/mem/c_containers.h" 224514f5e3Sopenharmony_ci#include "ecmascript/mem/ecma_list.h" 234514f5e3Sopenharmony_ci#include "ecmascript/mem/heap_region_allocator.h" 244514f5e3Sopenharmony_ci#include "ecmascript/mem/mem.h" 254514f5e3Sopenharmony_ci#include "ecmascript/mem/region.h" 264514f5e3Sopenharmony_ci 274514f5e3Sopenharmony_ci#include "securec.h" 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_cinamespace panda::ecmascript { 304514f5e3Sopenharmony_cienum MemSpaceType { 314514f5e3Sopenharmony_ci OLD_SPACE = 0, 324514f5e3Sopenharmony_ci NON_MOVABLE, 334514f5e3Sopenharmony_ci MACHINE_CODE_SPACE, 344514f5e3Sopenharmony_ci HUGE_OBJECT_SPACE, 354514f5e3Sopenharmony_ci EDEN_SPACE, 364514f5e3Sopenharmony_ci SEMI_SPACE, 374514f5e3Sopenharmony_ci SNAPSHOT_SPACE, 384514f5e3Sopenharmony_ci COMPRESS_SPACE, 394514f5e3Sopenharmony_ci LOCAL_SPACE, 404514f5e3Sopenharmony_ci READ_ONLY_SPACE, 414514f5e3Sopenharmony_ci APPSPAWN_SPACE, 424514f5e3Sopenharmony_ci HUGE_MACHINE_CODE_SPACE, 434514f5e3Sopenharmony_ci SHARED_OLD_SPACE, 444514f5e3Sopenharmony_ci SHARED_NON_MOVABLE, 454514f5e3Sopenharmony_ci SHARED_READ_ONLY_SPACE, 464514f5e3Sopenharmony_ci SHARED_HUGE_OBJECT_SPACE, 474514f5e3Sopenharmony_ci SHARED_LOCAL_SPACE, 484514f5e3Sopenharmony_ci SHARED_COMPRESS_SPACE, 494514f5e3Sopenharmony_ci SHARED_APPSPAWN_SPACE, 504514f5e3Sopenharmony_ci SPACE_TYPE_LAST, // Count of different types 514514f5e3Sopenharmony_ci 524514f5e3Sopenharmony_ci SHARED_BEGIN = SHARED_OLD_SPACE, 534514f5e3Sopenharmony_ci SHARED_END = SHARED_HUGE_OBJECT_SPACE, 544514f5e3Sopenharmony_ci // Free region means memory maybe always in use and can not be evacuated 554514f5e3Sopenharmony_ci FREE_LIST_NUM = MACHINE_CODE_SPACE - OLD_SPACE + 1, 564514f5e3Sopenharmony_ci SHARED_SWEEPING_SPACE_BEGIN = SHARED_OLD_SPACE, 574514f5e3Sopenharmony_ci SHARED_SWEEPING_SPACE_END = SHARED_NON_MOVABLE, 584514f5e3Sopenharmony_ci SHARED_SWEEPING_SPACE_NUM = SHARED_SWEEPING_SPACE_END - SHARED_SWEEPING_SPACE_BEGIN + 1, 594514f5e3Sopenharmony_ci}; 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_cienum class MemSpaceKind { 624514f5e3Sopenharmony_ci LOCAL = 0, 634514f5e3Sopenharmony_ci SHARED = 1 644514f5e3Sopenharmony_ci}; 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_cienum class AllocateEventType { 674514f5e3Sopenharmony_ci NORMAL, 684514f5e3Sopenharmony_ci DESERIALIZE, 694514f5e3Sopenharmony_ci}; 704514f5e3Sopenharmony_ci 714514f5e3Sopenharmony_cistatic inline bool IsSMemSpace(MemSpaceType type) 724514f5e3Sopenharmony_ci{ 734514f5e3Sopenharmony_ci return (type >= MemSpaceType::SHARED_BEGIN) && (type <= MemSpaceType::SHARED_END); 744514f5e3Sopenharmony_ci} 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_cistatic inline std::string ToSpaceTypeName(MemSpaceType type) 774514f5e3Sopenharmony_ci{ 784514f5e3Sopenharmony_ci switch (type) { 794514f5e3Sopenharmony_ci case OLD_SPACE: 804514f5e3Sopenharmony_ci return "old space"; 814514f5e3Sopenharmony_ci case NON_MOVABLE: 824514f5e3Sopenharmony_ci return "non movable space"; 834514f5e3Sopenharmony_ci case MACHINE_CODE_SPACE: 844514f5e3Sopenharmony_ci return "machine code space"; 854514f5e3Sopenharmony_ci case HUGE_OBJECT_SPACE: 864514f5e3Sopenharmony_ci return "huge object space"; 874514f5e3Sopenharmony_ci case EDEN_SPACE: 884514f5e3Sopenharmony_ci return "eden space"; 894514f5e3Sopenharmony_ci case SEMI_SPACE: 904514f5e3Sopenharmony_ci return "semi space"; 914514f5e3Sopenharmony_ci case SNAPSHOT_SPACE: 924514f5e3Sopenharmony_ci return "snapshot space"; 934514f5e3Sopenharmony_ci case COMPRESS_SPACE: 944514f5e3Sopenharmony_ci return "compress space"; 954514f5e3Sopenharmony_ci case LOCAL_SPACE: 964514f5e3Sopenharmony_ci return "local space"; 974514f5e3Sopenharmony_ci case READ_ONLY_SPACE: 984514f5e3Sopenharmony_ci return "read only space"; 994514f5e3Sopenharmony_ci case APPSPAWN_SPACE: 1004514f5e3Sopenharmony_ci return "appspawn space"; 1014514f5e3Sopenharmony_ci case HUGE_MACHINE_CODE_SPACE: 1024514f5e3Sopenharmony_ci return "huge machine code space"; 1034514f5e3Sopenharmony_ci case SHARED_NON_MOVABLE: 1044514f5e3Sopenharmony_ci return "shared non movable space"; 1054514f5e3Sopenharmony_ci case SHARED_OLD_SPACE: 1064514f5e3Sopenharmony_ci return "shared old space"; 1074514f5e3Sopenharmony_ci case SHARED_READ_ONLY_SPACE: 1084514f5e3Sopenharmony_ci return "shared read only space"; 1094514f5e3Sopenharmony_ci case SHARED_HUGE_OBJECT_SPACE: 1104514f5e3Sopenharmony_ci return "shared huge object space"; 1114514f5e3Sopenharmony_ci case SHARED_COMPRESS_SPACE: 1124514f5e3Sopenharmony_ci return "compress space"; 1134514f5e3Sopenharmony_ci case SHARED_LOCAL_SPACE: 1144514f5e3Sopenharmony_ci return "shared local space"; 1154514f5e3Sopenharmony_ci case SHARED_APPSPAWN_SPACE: 1164514f5e3Sopenharmony_ci return "shared appspawn space"; 1174514f5e3Sopenharmony_ci default: 1184514f5e3Sopenharmony_ci return "unknown space"; 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci} 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ciclass Space { 1234514f5e3Sopenharmony_cipublic: 1244514f5e3Sopenharmony_ci Space(BaseHeap* heap, HeapRegionAllocator *regionAllocator, MemSpaceType spaceType, size_t initialCapacity, 1254514f5e3Sopenharmony_ci size_t maximumCapacity); 1264514f5e3Sopenharmony_ci virtual ~Space() = default; 1274514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(Space); 1284514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(Space); 1294514f5e3Sopenharmony_ci 1304514f5e3Sopenharmony_ci size_t GetMaximumCapacity() const 1314514f5e3Sopenharmony_ci { 1324514f5e3Sopenharmony_ci return maximumCapacity_; 1334514f5e3Sopenharmony_ci } 1344514f5e3Sopenharmony_ci 1354514f5e3Sopenharmony_ci void SetMaximumCapacity(size_t maximumCapacity) 1364514f5e3Sopenharmony_ci { 1374514f5e3Sopenharmony_ci maximumCapacity_ = maximumCapacity; 1384514f5e3Sopenharmony_ci } 1394514f5e3Sopenharmony_ci 1404514f5e3Sopenharmony_ci size_t GetOverShootMaximumCapacity() const 1414514f5e3Sopenharmony_ci { 1424514f5e3Sopenharmony_ci return maximumCapacity_ + outOfMemoryOvershootSize_; 1434514f5e3Sopenharmony_ci } 1444514f5e3Sopenharmony_ci 1454514f5e3Sopenharmony_ci size_t GetInitialCapacity() const 1464514f5e3Sopenharmony_ci { 1474514f5e3Sopenharmony_ci return initialCapacity_; 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ci void SetInitialCapacity(size_t initialCapacity) 1514514f5e3Sopenharmony_ci { 1524514f5e3Sopenharmony_ci initialCapacity_ = initialCapacity; 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_ci size_t GetCommittedSize() const 1564514f5e3Sopenharmony_ci { 1574514f5e3Sopenharmony_ci return committedSize_; 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci void IncreaseCommitted(size_t bytes) 1614514f5e3Sopenharmony_ci { 1624514f5e3Sopenharmony_ci committedSize_ += bytes; 1634514f5e3Sopenharmony_ci } 1644514f5e3Sopenharmony_ci 1654514f5e3Sopenharmony_ci void DecreaseCommitted(size_t bytes) 1664514f5e3Sopenharmony_ci { 1674514f5e3Sopenharmony_ci committedSize_ -= bytes; 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ci 1704514f5e3Sopenharmony_ci void IncreaseObjectSize(size_t bytes) 1714514f5e3Sopenharmony_ci { 1724514f5e3Sopenharmony_ci objectSize_ += bytes; 1734514f5e3Sopenharmony_ci } 1744514f5e3Sopenharmony_ci 1754514f5e3Sopenharmony_ci void DecreaseObjectSize(size_t bytes) 1764514f5e3Sopenharmony_ci { 1774514f5e3Sopenharmony_ci objectSize_ -= bytes; 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci 1804514f5e3Sopenharmony_ci size_t GetObjectSize() 1814514f5e3Sopenharmony_ci { 1824514f5e3Sopenharmony_ci return objectSize_; 1834514f5e3Sopenharmony_ci } 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_ci size_t GetOutOfMemoryOvershootSize() const 1864514f5e3Sopenharmony_ci { 1874514f5e3Sopenharmony_ci return outOfMemoryOvershootSize_; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci 1904514f5e3Sopenharmony_ci void IncreaseOutOfMemoryOvershootSize(size_t size) 1914514f5e3Sopenharmony_ci { 1924514f5e3Sopenharmony_ci outOfMemoryOvershootSize_ += size; 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci 1954514f5e3Sopenharmony_ci void DecreaseOutOfMemoryOvershootSize(size_t size) 1964514f5e3Sopenharmony_ci { 1974514f5e3Sopenharmony_ci ASSERT(outOfMemoryOvershootSize_ >= size); 1984514f5e3Sopenharmony_ci outOfMemoryOvershootSize_ -= size; 1994514f5e3Sopenharmony_ci } 2004514f5e3Sopenharmony_ci 2014514f5e3Sopenharmony_ci MemSpaceType GetSpaceType() const 2024514f5e3Sopenharmony_ci { 2034514f5e3Sopenharmony_ci return spaceType_; 2044514f5e3Sopenharmony_ci } 2054514f5e3Sopenharmony_ci 2064514f5e3Sopenharmony_ci inline RegionSpaceFlag GetRegionFlag() const; 2074514f5e3Sopenharmony_ci 2084514f5e3Sopenharmony_ci uintptr_t GetAllocateAreaBegin() const 2094514f5e3Sopenharmony_ci { 2104514f5e3Sopenharmony_ci return regionList_.GetLast()->GetBegin(); 2114514f5e3Sopenharmony_ci } 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_ci uintptr_t GetAllocateAreaEnd() const 2144514f5e3Sopenharmony_ci { 2154514f5e3Sopenharmony_ci return regionList_.GetLast()->GetEnd(); 2164514f5e3Sopenharmony_ci } 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ci Region *GetCurrentRegion() const 2194514f5e3Sopenharmony_ci { 2204514f5e3Sopenharmony_ci return regionList_.GetLast(); 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci 2234514f5e3Sopenharmony_ci Region *GetFirstRegion() const 2244514f5e3Sopenharmony_ci { 2254514f5e3Sopenharmony_ci return regionList_.GetFirst(); 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci 2284514f5e3Sopenharmony_ci uint32_t GetRegionCount() 2294514f5e3Sopenharmony_ci { 2304514f5e3Sopenharmony_ci return regionList_.GetLength(); 2314514f5e3Sopenharmony_ci } 2324514f5e3Sopenharmony_ci 2334514f5e3Sopenharmony_ci EcmaList<Region> &GetRegionList() 2344514f5e3Sopenharmony_ci { 2354514f5e3Sopenharmony_ci return regionList_; 2364514f5e3Sopenharmony_ci } 2374514f5e3Sopenharmony_ci 2384514f5e3Sopenharmony_ci const EcmaList<Region> &GetRegionList() const 2394514f5e3Sopenharmony_ci { 2404514f5e3Sopenharmony_ci return regionList_; 2414514f5e3Sopenharmony_ci } 2424514f5e3Sopenharmony_ci 2434514f5e3Sopenharmony_ci void SetRecordRegion() 2444514f5e3Sopenharmony_ci { 2454514f5e3Sopenharmony_ci recordRegion_ = GetCurrentRegion(); 2464514f5e3Sopenharmony_ci } 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ci bool IsOOMDumpSpace() 2494514f5e3Sopenharmony_ci { 2504514f5e3Sopenharmony_ci return spaceType_ == SEMI_SPACE || spaceType_ == OLD_SPACE || spaceType_ == NON_MOVABLE || 2514514f5e3Sopenharmony_ci spaceType_ == HUGE_OBJECT_SPACE; 2524514f5e3Sopenharmony_ci } 2534514f5e3Sopenharmony_ci 2544514f5e3Sopenharmony_ci // methods for allocation inspector 2554514f5e3Sopenharmony_ci void AddAllocationInspector(AllocationInspector* inspector); 2564514f5e3Sopenharmony_ci void ClearAllocationInspector(); 2574514f5e3Sopenharmony_ci void SwapAllocationCounter(Space *space); 2584514f5e3Sopenharmony_ci 2594514f5e3Sopenharmony_ci template <class Callback> 2604514f5e3Sopenharmony_ci inline void EnumerateRegions(const Callback &cb, Region *region = nullptr) const; 2614514f5e3Sopenharmony_ci template <class Callback> 2624514f5e3Sopenharmony_ci inline void EnumerateRegionsWithRecord(const Callback &cb) const; 2634514f5e3Sopenharmony_ci 2644514f5e3Sopenharmony_ci inline void AddRegion(Region *region); 2654514f5e3Sopenharmony_ci inline void RemoveRegion(Region *region); 2664514f5e3Sopenharmony_ci 2674514f5e3Sopenharmony_ci virtual void Initialize() {}; 2684514f5e3Sopenharmony_ci void Destroy(); 2694514f5e3Sopenharmony_ci 2704514f5e3Sopenharmony_ci void ReclaimRegions(size_t cachedSize = 0); 2714514f5e3Sopenharmony_ci 2724514f5e3Sopenharmony_ciprotected: 2734514f5e3Sopenharmony_ci void ClearAndFreeRegion(Region *region, size_t cachedSize = 0); 2744514f5e3Sopenharmony_ci 2754514f5e3Sopenharmony_ci BaseHeap *heap_ {nullptr}; 2764514f5e3Sopenharmony_ci HeapRegionAllocator *heapRegionAllocator_ {nullptr}; 2774514f5e3Sopenharmony_ci EcmaList<Region> regionList_ {}; 2784514f5e3Sopenharmony_ci MemSpaceType spaceType_ {}; 2794514f5e3Sopenharmony_ci size_t initialCapacity_ {0}; 2804514f5e3Sopenharmony_ci size_t maximumCapacity_ {0}; 2814514f5e3Sopenharmony_ci size_t committedSize_ {0}; 2824514f5e3Sopenharmony_ci size_t objectSize_ {0}; 2834514f5e3Sopenharmony_ci size_t outOfMemoryOvershootSize_ {0}; 2844514f5e3Sopenharmony_ci Region *recordRegion_ {nullptr}; 2854514f5e3Sopenharmony_ci AllocationCounter allocationCounter_; 2864514f5e3Sopenharmony_ci}; 2874514f5e3Sopenharmony_ci 2884514f5e3Sopenharmony_ciclass HugeObjectSpace : public Space { 2894514f5e3Sopenharmony_cipublic: 2904514f5e3Sopenharmony_ci HugeObjectSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 2914514f5e3Sopenharmony_ci size_t maximumCapacity); 2924514f5e3Sopenharmony_ci HugeObjectSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 2934514f5e3Sopenharmony_ci size_t maximumCapacity, MemSpaceType spaceType); 2944514f5e3Sopenharmony_ci ~HugeObjectSpace() override = default; 2954514f5e3Sopenharmony_ci NO_COPY_SEMANTIC(HugeObjectSpace); 2964514f5e3Sopenharmony_ci NO_MOVE_SEMANTIC(HugeObjectSpace); 2974514f5e3Sopenharmony_ci // Sometimes it is unsafe to checkSafePoint here, e.g. in deserialize, if do checkSafePoint JSThread may be 2984514f5e3Sopenharmony_ci // suspended and then do SharedGC, which will free some regions in SharedHeap that are allocated at the beginning 2994514f5e3Sopenharmony_ci // of deserializing for further object allocating, but no object has been allocated on at this moment. 3004514f5e3Sopenharmony_ci uintptr_t Allocate(size_t objectSize, JSThread *thread, AllocateEventType allocType = AllocateEventType::NORMAL); 3014514f5e3Sopenharmony_ci void Sweep(); 3024514f5e3Sopenharmony_ci size_t GetHeapObjectSize() const; 3034514f5e3Sopenharmony_ci void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 3044514f5e3Sopenharmony_ci 3054514f5e3Sopenharmony_ci void ReclaimHugeRegion(); 3064514f5e3Sopenharmony_ci 3074514f5e3Sopenharmony_ci void InvokeAllocationInspector(Address object, size_t objectSize); 3084514f5e3Sopenharmony_ci 3094514f5e3Sopenharmony_ciprotected: 3104514f5e3Sopenharmony_ci static constexpr size_t HUGE_OBJECT_BITSET_SIZE = 16; 3114514f5e3Sopenharmony_ciprivate: 3124514f5e3Sopenharmony_ci EcmaList<Region> hugeNeedFreeList_ {}; 3134514f5e3Sopenharmony_ci}; 3144514f5e3Sopenharmony_ci 3154514f5e3Sopenharmony_ciclass HugeMachineCodeSpace : public HugeObjectSpace { 3164514f5e3Sopenharmony_cipublic: 3174514f5e3Sopenharmony_ci HugeMachineCodeSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 3184514f5e3Sopenharmony_ci size_t maximumCapacity); 3194514f5e3Sopenharmony_ci uintptr_t GetMachineCodeObject(uintptr_t pc) const; 3204514f5e3Sopenharmony_ci uintptr_t Allocate(size_t objectSize, JSThread *thread, void *desc, 3214514f5e3Sopenharmony_ci AllocateEventType allocType = AllocateEventType::NORMAL); 3224514f5e3Sopenharmony_ci uintptr_t Allocate(size_t objectSize, JSThread *thread); 3234514f5e3Sopenharmony_ci Region *PUBLIC_API AllocateFort(size_t objectSize, JSThread *thread, void *desc); 3244514f5e3Sopenharmony_ci}; 3254514f5e3Sopenharmony_ci 3264514f5e3Sopenharmony_ci} // namespace panda::ecmascript 3274514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_SPACE_H 328