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