1 /* 2 * Copyright (c) 2021 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_HEAP_H 17 #define ECMASCRIPT_MEM_HEAP_H 18 19 #include "ecmascript/base/config.h" 20 #include "ecmascript/js_thread.h" 21 #include "ecmascript/mem/chunk_containers.h" 22 #include "ecmascript/mem/mark_stack.h" 23 #include "ecmascript/mem/parallel_work_helper.h" 24 #include "ecmascript/mem/linear_space.h" 25 #include "ecmascript/mem/sparse_space.h" 26 #include "ecmascript/platform/platform.h" 27 28 namespace panda::ecmascript { 29 class EcmaVM; 30 class STWYoungGC; 31 class MixGC; 32 class FullGC; 33 class BumpPointerAllocator; 34 class NativeAreaAllocator; 35 class HeapRegionAllocator; 36 class HeapTracker; 37 class MemController; 38 class ConcurrentSweeper; 39 class ConcurrentMarker; 40 class Marker; 41 class ParallelEvacuation; 42 class WorkerHelper; 43 44 using DerivedDataKey = std::pair<uintptr_t, uintptr_t>; 45 46 enum class MarkType : uint8_t { 47 SEMI_MARK, 48 FULL_MARK 49 }; 50 51 class Heap { 52 public: 53 explicit Heap(EcmaVM *ecmaVm); 54 ~Heap() = default; 55 NO_COPY_SEMANTIC(Heap); 56 NO_MOVE_SEMANTIC(Heap); 57 void Initialize(); 58 void Destroy(); 59 void Prepare(); 60 void Resume(TriggerGCType gcType); 61 GetNewSpace()62 SemiSpace *GetNewSpace() const 63 { 64 return toSpace_; 65 } 66 GetFromSpace()67 SemiSpace *GetFromSpace() const 68 { 69 return fromSpace_; 70 } 71 GetOldSpace()72 OldSpace *GetOldSpace() const 73 { 74 return oldSpace_; 75 } 76 GetNonMovableSpace()77 NonMovableSpace *GetNonMovableSpace() const 78 { 79 return nonMovableSpace_; 80 } 81 GetHugeObjectSpace()82 HugeObjectSpace *GetHugeObjectSpace() const 83 { 84 return hugeObjectSpace_; 85 } 86 GetMachineCodeSpace()87 MachineCodeSpace *GetMachineCodeSpace() const 88 { 89 return machineCodeSpace_; 90 } 91 GetSnapShotSpace()92 SnapShotSpace *GetSnapShotSpace() const 93 { 94 return snapshotSpace_; 95 } 96 GetSpaceWithType(MemSpaceType type)97 SparseSpace *GetSpaceWithType(MemSpaceType type) const 98 { 99 switch (type) { 100 case MemSpaceType::OLD_SPACE: 101 return oldSpace_; 102 break; 103 case MemSpaceType::NON_MOVABLE: 104 return nonMovableSpace_; 105 break; 106 case MemSpaceType::MACHINE_CODE_SPACE: 107 return machineCodeSpace_; 108 break; 109 default: 110 UNREACHABLE(); 111 break; 112 } 113 } 114 GetSTWYoungGC()115 STWYoungGC *GetSTWYoungGC() const 116 { 117 return stwYoungGC_; 118 } 119 GetMixGC()120 MixGC *GetMixGC() const 121 { 122 return mixGC_; 123 } 124 GetFullGC()125 FullGC *GetFullGC() const 126 { 127 return fullGC_; 128 } 129 GetSweeper()130 ConcurrentSweeper *GetSweeper() const 131 { 132 return sweeper_; 133 } 134 GetEvacuation()135 ParallelEvacuation *GetEvacuation() const 136 { 137 return evacuation_; 138 } 139 GetConcurrentMarker()140 ConcurrentMarker *GetConcurrentMarker() const 141 { 142 return concurrentMarker_; 143 } 144 GetNonMovableMarker()145 Marker *GetNonMovableMarker() const 146 { 147 return nonMovableMarker_; 148 } 149 GetSemiGcMarker()150 Marker *GetSemiGcMarker() const 151 { 152 return semiGcMarker_; 153 } 154 GetCompressGcMarker()155 Marker *GetCompressGcMarker() const 156 { 157 return compressGcMarker_; 158 } 159 GetEcmaVM()160 EcmaVM *GetEcmaVM() const 161 { 162 return ecmaVm_; 163 } 164 GetJSThread()165 JSThread *GetJSThread() const 166 { 167 return thread_; 168 } 169 GetWorkList()170 WorkerHelper *GetWorkList() const 171 { 172 return workList_; 173 } 174 GetMemController()175 MemController *GetMemController() const 176 { 177 return memController_; 178 } 179 180 inline void SwapNewSpace(); 181 182 template<class Callback> 183 void EnumerateOldSpaceRegions(const Callback &cb, Region *region = nullptr) const; 184 185 template<class Callback> 186 void EnumerateNonNewSpaceRegions(const Callback &cb) const; 187 188 template<class Callback> 189 void EnumerateNewSpaceRegions(const Callback &cb) const; 190 191 template<class Callback> 192 void EnumerateSnapShotSpaceRegions(const Callback &cb) const; 193 194 template<class Callback> 195 void EnumerateNonMovableRegions(const Callback &cb) const; 196 197 template<class Callback> 198 inline void EnumerateRegions(const Callback &cb) const; 199 200 template<class Callback> 201 void IteratorOverObjects(const Callback &cb) const; 202 203 TriggerGCType SelectGCType() const; 204 void CollectGarbage(TriggerGCType gcType); 205 206 // Young 207 inline TaggedObject *AllocateYoungOrHugeObject(JSHClass *hclass); 208 inline TaggedObject *AllocateYoungOrHugeObject(JSHClass *hclass, size_t size); 209 inline uintptr_t AllocateYoungSync(size_t size); 210 inline TaggedObject *TryAllocateYoungGeneration(JSHClass *hclass, size_t size); 211 // Old 212 inline TaggedObject *AllocateOldOrHugeObject(JSHClass *hclass); 213 inline TaggedObject *AllocateOldOrHugeObject(JSHClass *hclass, size_t size); 214 // Nonmovable 215 inline TaggedObject *AllocateNonMovableOrHugeObject(JSHClass *hclass); 216 inline TaggedObject *AllocateNonMovableOrHugeObject(JSHClass *hclass, size_t size); 217 inline TaggedObject *AllocateDynClassClass(JSHClass *hclass, size_t size); 218 // Huge 219 inline TaggedObject *AllocateHugeObject(JSHClass *hclass, size_t size); 220 // Machine code 221 inline TaggedObject *AllocateMachineCodeObject(JSHClass *hclass, size_t size); 222 // Snapshot 223 inline uintptr_t AllocateSnapShotSpace(size_t size); 224 225 inline bool MoveYoungRegionSync(Region *region); 226 inline void MergeToOldSpaceSync(LocalSpace *localSpace); 227 228 void ThrowOutOfMemoryError(size_t size, std::string functionName); 229 StartHeapTracking(HeapTracker * tracker)230 void StartHeapTracking(HeapTracker *tracker) 231 { 232 tracker_ = tracker; 233 } 234 StopHeapTracking()235 void StopHeapTracking() 236 { 237 tracker_ = nullptr; 238 } 239 240 inline void OnAllocateEvent(uintptr_t address); 241 inline void OnMoveEvent(uintptr_t address, uintptr_t forwardAddress); 242 243 void TryTriggerConcurrentMarking(); 244 245 void TriggerConcurrentMarking(); 246 247 bool CheckConcurrentMark(); 248 249 void CheckAndTriggerOldGC(); 250 GetNativeAreaAllocator()251 NativeAreaAllocator *GetNativeAreaAllocator() const 252 { 253 return nativeAreaAllocator_; 254 } 255 GetHeapRegionAllocator()256 const HeapRegionAllocator *GetHeapRegionAllocator() const 257 { 258 return heapRegionAllocator_; 259 } 260 261 bool IsLive(TaggedObject *object) const; 262 bool ContainObject(TaggedObject *object) const; 263 264 void RecomputeLimits(); 265 266 size_t VerifyHeapObjects() const; 267 268 inline void ClearSlotsRange(Region *current, uintptr_t freeStart, uintptr_t freeEnd); 269 GetDerivedPointers()270 ChunkMap<DerivedDataKey, uintptr_t> *GetDerivedPointers() const 271 { 272 return derivedPointers_; 273 } 274 #if ECMASCRIPT_ENABLE_HEAP_VERIFY GetIsVerifying()275 bool GetIsVerifying() const 276 { 277 return isVerifying_; 278 } 279 #endif 280 281 void UpdateDerivedObjectInStack(); 282 static constexpr uint32_t STACK_MAP_DEFALUT_DERIVED_SIZE = 8U; 283 284 void WaitRunningTaskFinished(); 285 286 bool CheckCanDistributeTask(); 287 288 void PostParallelGCTask(ParallelGCTaskPhase gcTask); 289 IsParallelGCEnabled()290 bool IsParallelGCEnabled() const 291 { 292 return paralledGc_; 293 } 294 295 void WaitConcurrentMarkingFinished(); 296 SetConcurrentMarkingEnable(bool flag)297 void SetConcurrentMarkingEnable(bool flag) 298 { 299 concurrentMarkingEnabled_ = flag; 300 } 301 ConcurrentMarkingEnable()302 bool ConcurrentMarkingEnable() const 303 { 304 return concurrentMarkingEnabled_; 305 } 306 SetMarkType(MarkType markType)307 void SetMarkType(MarkType markType) 308 { 309 markType_ = markType; 310 } 311 IsFullMark()312 bool IsFullMark() const 313 { 314 return markType_ == MarkType::FULL_MARK; 315 } 316 317 size_t GetArrayBufferSize() const; 318 319 inline size_t GetCommittedSize() const; 320 321 inline size_t GetHeapObjectSize() const; 322 323 void AdjustOldSpaceLimit(); 324 GetPromotedSize()325 size_t GetPromotedSize() const 326 { 327 return promotedSize_; 328 } 329 GetSemiSpaceCopiedSize()330 size_t GetSemiSpaceCopiedSize() const 331 { 332 return semiSpaceCopiedSize_; 333 } 334 private: 335 void IncreaseTaskCount(); 336 337 void ReduceTaskCount(); 338 339 class ParallelGCTask : public Task { 340 public: ParallelGCTask(Heap * heap,ParallelGCTaskPhase taskPhase)341 ParallelGCTask(Heap *heap, ParallelGCTaskPhase taskPhase) : heap_(heap), taskPhase_(taskPhase) {}; 342 ~ParallelGCTask() override = default; 343 bool Run(uint32_t threadIndex) override; 344 345 NO_COPY_SEMANTIC(ParallelGCTask); 346 NO_MOVE_SEMANTIC(ParallelGCTask); 347 348 private: 349 Heap *heap_ {nullptr}; 350 ParallelGCTaskPhase taskPhase_; 351 }; 352 353 class AsyncClearTask : public Task { 354 public: AsyncClearTask(Heap * heap,TriggerGCType type)355 AsyncClearTask(Heap *heap, TriggerGCType type) : heap_(heap), gcType_(type) {} 356 ~AsyncClearTask() override = default; 357 bool Run(uint32_t threadIndex) override; 358 359 NO_COPY_SEMANTIC(AsyncClearTask); 360 NO_MOVE_SEMANTIC(AsyncClearTask); 361 private: 362 Heap *heap_; 363 TriggerGCType gcType_; 364 }; 365 366 inline void ReclaimRegions(TriggerGCType gcType); 367 void WaitClearTaskFinished(); 368 369 EcmaVM *ecmaVm_ {nullptr}; 370 JSThread *thread_ {nullptr}; 371 SemiSpace *fromSpace_ {nullptr}; 372 SemiSpace *toSpace_ {nullptr}; 373 OldSpace *oldSpace_ {nullptr}; 374 OldSpace *compressSpace_ {nullptr}; 375 NonMovableSpace *nonMovableSpace_ {nullptr}; 376 MachineCodeSpace *machineCodeSpace_ {nullptr}; 377 HugeObjectSpace *hugeObjectSpace_ {nullptr}; 378 SnapShotSpace *snapshotSpace_ {nullptr}; 379 STWYoungGC *stwYoungGC_ {nullptr}; 380 MixGC *mixGC_ {nullptr}; 381 FullGC *fullGC_ {nullptr}; 382 ConcurrentSweeper *sweeper_ {nullptr}; 383 ConcurrentMarker *concurrentMarker_; 384 WorkerHelper *workList_ {nullptr}; 385 Marker *nonMovableMarker_ {nullptr}; 386 Marker *semiGcMarker_ {nullptr}; 387 Marker *compressGcMarker_ {nullptr}; 388 ParallelEvacuation *evacuation_ {nullptr}; 389 NativeAreaAllocator *nativeAreaAllocator_ {nullptr}; 390 HeapRegionAllocator *heapRegionAllocator_ {nullptr}; 391 HeapTracker *tracker_ {nullptr}; 392 MemController *memController_ {nullptr}; 393 size_t globalSpaceAllocLimit_ {GLOBAL_SPACE_LIMIT_BEGIN}; 394 ChunkMap<DerivedDataKey, uintptr_t> *derivedPointers_ {nullptr}; 395 #if ECMASCRIPT_ENABLE_HEAP_VERIFY 396 bool isVerifying_ {false}; 397 #endif 398 399 bool isClearTaskFinished_ = true; 400 os::memory::Mutex waitClearTaskFinishedMutex_; 401 os::memory::ConditionVariable waitClearTaskFinishedCV_; 402 uint32_t runningTastCount_ {0}; 403 os::memory::Mutex waitTaskFinishedMutex_; 404 os::memory::ConditionVariable waitTaskFinishedCV_; 405 bool paralledGc_ {true}; 406 407 MarkType markType_; 408 bool concurrentMarkingEnabled_ {true}; 409 bool isFullGCRequested_ {false}; 410 bool oldSpaceLimitAdjusted_ {false}; 411 size_t startNewSpaceSize_ {0}; 412 size_t promotedSize_ {0}; 413 size_t semiSpaceCopiedSize_ {0}; 414 }; 415 } // namespace panda::ecmascript 416 417 #endif // ECMASCRIPT_MEM_HEAP_H 418