• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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