1/* 2 * Copyright (c) 2021-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_SPACE_H 17#define ECMASCRIPT_MEM_SPACE_H 18 19#include "ecmascript/mem/allocation_inspector.h" 20#include "ecmascript/mem/allocator.h" 21#include "ecmascript/mem/c_containers.h" 22#include "ecmascript/mem/ecma_list.h" 23#include "ecmascript/mem/heap_region_allocator.h" 24#include "ecmascript/mem/mem.h" 25#include "ecmascript/mem/region.h" 26 27#include "securec.h" 28 29namespace panda::ecmascript { 30enum MemSpaceType { 31 OLD_SPACE = 0, 32 NON_MOVABLE, 33 MACHINE_CODE_SPACE, 34 HUGE_OBJECT_SPACE, 35 EDEN_SPACE, 36 SEMI_SPACE, 37 SNAPSHOT_SPACE, 38 COMPRESS_SPACE, 39 LOCAL_SPACE, 40 READ_ONLY_SPACE, 41 APPSPAWN_SPACE, 42 HUGE_MACHINE_CODE_SPACE, 43 SHARED_OLD_SPACE, 44 SHARED_NON_MOVABLE, 45 SHARED_READ_ONLY_SPACE, 46 SHARED_HUGE_OBJECT_SPACE, 47 SHARED_LOCAL_SPACE, 48 SHARED_COMPRESS_SPACE, 49 SHARED_APPSPAWN_SPACE, 50 SPACE_TYPE_LAST, // Count of different types 51 52 SHARED_BEGIN = SHARED_OLD_SPACE, 53 SHARED_END = SHARED_HUGE_OBJECT_SPACE, 54 // Free region means memory maybe always in use and can not be evacuated 55 FREE_LIST_NUM = MACHINE_CODE_SPACE - OLD_SPACE + 1, 56 SHARED_SWEEPING_SPACE_BEGIN = SHARED_OLD_SPACE, 57 SHARED_SWEEPING_SPACE_END = SHARED_NON_MOVABLE, 58 SHARED_SWEEPING_SPACE_NUM = SHARED_SWEEPING_SPACE_END - SHARED_SWEEPING_SPACE_BEGIN + 1, 59}; 60 61enum class MemSpaceKind { 62 LOCAL = 0, 63 SHARED = 1 64}; 65 66enum class AllocateEventType { 67 NORMAL, 68 DESERIALIZE, 69}; 70 71static inline bool IsSMemSpace(MemSpaceType type) 72{ 73 return (type >= MemSpaceType::SHARED_BEGIN) && (type <= MemSpaceType::SHARED_END); 74} 75 76static inline std::string ToSpaceTypeName(MemSpaceType type) 77{ 78 switch (type) { 79 case OLD_SPACE: 80 return "old space"; 81 case NON_MOVABLE: 82 return "non movable space"; 83 case MACHINE_CODE_SPACE: 84 return "machine code space"; 85 case HUGE_OBJECT_SPACE: 86 return "huge object space"; 87 case EDEN_SPACE: 88 return "eden space"; 89 case SEMI_SPACE: 90 return "semi space"; 91 case SNAPSHOT_SPACE: 92 return "snapshot space"; 93 case COMPRESS_SPACE: 94 return "compress space"; 95 case LOCAL_SPACE: 96 return "local space"; 97 case READ_ONLY_SPACE: 98 return "read only space"; 99 case APPSPAWN_SPACE: 100 return "appspawn space"; 101 case HUGE_MACHINE_CODE_SPACE: 102 return "huge machine code space"; 103 case SHARED_NON_MOVABLE: 104 return "shared non movable space"; 105 case SHARED_OLD_SPACE: 106 return "shared old space"; 107 case SHARED_READ_ONLY_SPACE: 108 return "shared read only space"; 109 case SHARED_HUGE_OBJECT_SPACE: 110 return "shared huge object space"; 111 case SHARED_COMPRESS_SPACE: 112 return "compress space"; 113 case SHARED_LOCAL_SPACE: 114 return "shared local space"; 115 case SHARED_APPSPAWN_SPACE: 116 return "shared appspawn space"; 117 default: 118 return "unknown space"; 119 } 120} 121 122class Space { 123public: 124 Space(BaseHeap* heap, HeapRegionAllocator *regionAllocator, MemSpaceType spaceType, size_t initialCapacity, 125 size_t maximumCapacity); 126 virtual ~Space() = default; 127 NO_COPY_SEMANTIC(Space); 128 NO_MOVE_SEMANTIC(Space); 129 130 size_t GetMaximumCapacity() const 131 { 132 return maximumCapacity_; 133 } 134 135 void SetMaximumCapacity(size_t maximumCapacity) 136 { 137 maximumCapacity_ = maximumCapacity; 138 } 139 140 size_t GetOverShootMaximumCapacity() const 141 { 142 return maximumCapacity_ + outOfMemoryOvershootSize_; 143 } 144 145 size_t GetInitialCapacity() const 146 { 147 return initialCapacity_; 148 } 149 150 void SetInitialCapacity(size_t initialCapacity) 151 { 152 initialCapacity_ = initialCapacity; 153 } 154 155 size_t GetCommittedSize() const 156 { 157 return committedSize_; 158 } 159 160 void IncreaseCommitted(size_t bytes) 161 { 162 committedSize_ += bytes; 163 } 164 165 void DecreaseCommitted(size_t bytes) 166 { 167 committedSize_ -= bytes; 168 } 169 170 void IncreaseObjectSize(size_t bytes) 171 { 172 objectSize_ += bytes; 173 } 174 175 void DecreaseObjectSize(size_t bytes) 176 { 177 objectSize_ -= bytes; 178 } 179 180 size_t GetObjectSize() 181 { 182 return objectSize_; 183 } 184 185 size_t GetOutOfMemoryOvershootSize() const 186 { 187 return outOfMemoryOvershootSize_; 188 } 189 190 void IncreaseOutOfMemoryOvershootSize(size_t size) 191 { 192 outOfMemoryOvershootSize_ += size; 193 } 194 195 void DecreaseOutOfMemoryOvershootSize(size_t size) 196 { 197 ASSERT(outOfMemoryOvershootSize_ >= size); 198 outOfMemoryOvershootSize_ -= size; 199 } 200 201 MemSpaceType GetSpaceType() const 202 { 203 return spaceType_; 204 } 205 206 inline RegionSpaceFlag GetRegionFlag() const; 207 208 uintptr_t GetAllocateAreaBegin() const 209 { 210 return regionList_.GetLast()->GetBegin(); 211 } 212 213 uintptr_t GetAllocateAreaEnd() const 214 { 215 return regionList_.GetLast()->GetEnd(); 216 } 217 218 Region *GetCurrentRegion() const 219 { 220 return regionList_.GetLast(); 221 } 222 223 Region *GetFirstRegion() const 224 { 225 return regionList_.GetFirst(); 226 } 227 228 uint32_t GetRegionCount() 229 { 230 return regionList_.GetLength(); 231 } 232 233 EcmaList<Region> &GetRegionList() 234 { 235 return regionList_; 236 } 237 238 const EcmaList<Region> &GetRegionList() const 239 { 240 return regionList_; 241 } 242 243 void SetRecordRegion() 244 { 245 recordRegion_ = GetCurrentRegion(); 246 } 247 248 bool IsOOMDumpSpace() 249 { 250 return spaceType_ == SEMI_SPACE || spaceType_ == OLD_SPACE || spaceType_ == NON_MOVABLE || 251 spaceType_ == HUGE_OBJECT_SPACE; 252 } 253 254 // methods for allocation inspector 255 void AddAllocationInspector(AllocationInspector* inspector); 256 void ClearAllocationInspector(); 257 void SwapAllocationCounter(Space *space); 258 259 template <class Callback> 260 inline void EnumerateRegions(const Callback &cb, Region *region = nullptr) const; 261 template <class Callback> 262 inline void EnumerateRegionsWithRecord(const Callback &cb) const; 263 264 inline void AddRegion(Region *region); 265 inline void RemoveRegion(Region *region); 266 267 virtual void Initialize() {}; 268 void Destroy(); 269 270 void ReclaimRegions(size_t cachedSize = 0); 271 272protected: 273 void ClearAndFreeRegion(Region *region, size_t cachedSize = 0); 274 275 BaseHeap *heap_ {nullptr}; 276 HeapRegionAllocator *heapRegionAllocator_ {nullptr}; 277 EcmaList<Region> regionList_ {}; 278 MemSpaceType spaceType_ {}; 279 size_t initialCapacity_ {0}; 280 size_t maximumCapacity_ {0}; 281 size_t committedSize_ {0}; 282 size_t objectSize_ {0}; 283 size_t outOfMemoryOvershootSize_ {0}; 284 Region *recordRegion_ {nullptr}; 285 AllocationCounter allocationCounter_; 286}; 287 288class HugeObjectSpace : public Space { 289public: 290 HugeObjectSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 291 size_t maximumCapacity); 292 HugeObjectSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 293 size_t maximumCapacity, MemSpaceType spaceType); 294 ~HugeObjectSpace() override = default; 295 NO_COPY_SEMANTIC(HugeObjectSpace); 296 NO_MOVE_SEMANTIC(HugeObjectSpace); 297 // Sometimes it is unsafe to checkSafePoint here, e.g. in deserialize, if do checkSafePoint JSThread may be 298 // suspended and then do SharedGC, which will free some regions in SharedHeap that are allocated at the beginning 299 // of deserializing for further object allocating, but no object has been allocated on at this moment. 300 uintptr_t Allocate(size_t objectSize, JSThread *thread, AllocateEventType allocType = AllocateEventType::NORMAL); 301 void Sweep(); 302 size_t GetHeapObjectSize() const; 303 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const; 304 305 void ReclaimHugeRegion(); 306 307 void InvokeAllocationInspector(Address object, size_t objectSize); 308 309protected: 310 static constexpr size_t HUGE_OBJECT_BITSET_SIZE = 16; 311private: 312 EcmaList<Region> hugeNeedFreeList_ {}; 313}; 314 315class HugeMachineCodeSpace : public HugeObjectSpace { 316public: 317 HugeMachineCodeSpace(Heap *heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity, 318 size_t maximumCapacity); 319 uintptr_t GetMachineCodeObject(uintptr_t pc) const; 320 uintptr_t Allocate(size_t objectSize, JSThread *thread, void *desc, 321 AllocateEventType allocType = AllocateEventType::NORMAL); 322 uintptr_t Allocate(size_t objectSize, JSThread *thread); 323 Region *PUBLIC_API AllocateFort(size_t objectSize, JSThread *thread, void *desc); 324}; 325 326} // namespace panda::ecmascript 327#endif // ECMASCRIPT_MEM_SPACE_H 328