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 SPACE_TYPE_LAST, // Count of different types
43
44 FREE_LIST_NUM = MACHINE_CODE_SPACE - OLD_SPACE + 1,
45 };
46
ToSpaceTypeName(MemSpaceType type)47 static inline std::string ToSpaceTypeName(MemSpaceType type)
48 {
49 switch (type) {
50 case OLD_SPACE:
51 return "old space";
52 case NON_MOVABLE:
53 return "non movable space";
54 case MACHINE_CODE_SPACE:
55 return "machine code space";
56 case HUGE_OBJECT_SPACE:
57 return "huge object space";
58 case SEMI_SPACE:
59 return "semi space";
60 case SNAPSHOT_SPACE:
61 return "snapshot space";
62 case COMPRESS_SPACE:
63 return "compress space";
64 case LOCAL_SPACE:
65 return "local space";
66 case READ_ONLY_SPACE:
67 return "read only space";
68 case APPSPAWN_SPACE:
69 return "appspawn space";
70 case HUGE_MACHINE_CODE_SPACE:
71 return "huge machine code space";
72 default:
73 return "unknown space";
74 }
75 }
76
77 class Space {
78 public:
79 Space(Heap* heap, HeapRegionAllocator *regionAllocator, MemSpaceType spaceType, size_t initialCapacity,
80 size_t maximumCapacity);
81 virtual ~Space() = default;
82 NO_COPY_SEMANTIC(Space);
83 NO_MOVE_SEMANTIC(Space);
84
GetMaximumCapacity()85 size_t GetMaximumCapacity() const
86 {
87 return maximumCapacity_;
88 }
89
SetMaximumCapacity(size_t maximumCapacity)90 void SetMaximumCapacity(size_t maximumCapacity)
91 {
92 maximumCapacity_ = maximumCapacity;
93 }
94
GetOverShootMaximumCapacity()95 size_t GetOverShootMaximumCapacity() const
96 {
97 return maximumCapacity_ + outOfMemoryOvershootSize_;
98 }
99
GetInitialCapacity()100 size_t GetInitialCapacity() const
101 {
102 return initialCapacity_;
103 }
104
SetInitialCapacity(size_t initialCapacity)105 void SetInitialCapacity(size_t initialCapacity)
106 {
107 initialCapacity_ = initialCapacity;
108 }
109
GetCommittedSize()110 size_t GetCommittedSize() const
111 {
112 return committedSize_;
113 }
114
IncreaseCommitted(size_t bytes)115 void IncreaseCommitted(size_t bytes)
116 {
117 committedSize_ += bytes;
118 }
119
DecreaseCommitted(size_t bytes)120 void DecreaseCommitted(size_t bytes)
121 {
122 committedSize_ -= bytes;
123 }
124
IncreaseObjectSize(size_t bytes)125 void IncreaseObjectSize(size_t bytes)
126 {
127 objectSize_ += bytes;
128 }
129
DecreaseObjectSize(size_t bytes)130 void DecreaseObjectSize(size_t bytes)
131 {
132 objectSize_ -= bytes;
133 }
134
GetObjectSize()135 size_t GetObjectSize()
136 {
137 return objectSize_;
138 }
139
GetOutOfMemoryOvershootSize()140 size_t GetOutOfMemoryOvershootSize() const
141 {
142 return outOfMemoryOvershootSize_;
143 }
144
IncreaseOutOfMemoryOvershootSize(size_t size)145 void IncreaseOutOfMemoryOvershootSize(size_t size)
146 {
147 outOfMemoryOvershootSize_ += size;
148 }
149
GetSpaceType()150 MemSpaceType GetSpaceType() const
151 {
152 return spaceType_;
153 }
154
155 inline RegionSpaceFlag GetRegionFlag() const;
156
GetAllocateAreaBegin()157 uintptr_t GetAllocateAreaBegin() const
158 {
159 return regionList_.GetLast()->GetBegin();
160 }
161
GetAllocateAreaEnd()162 uintptr_t GetAllocateAreaEnd() const
163 {
164 return regionList_.GetLast()->GetEnd();
165 }
166
GetCurrentRegion()167 Region *GetCurrentRegion() const
168 {
169 return regionList_.GetLast();
170 }
171
GetFirstRegion()172 Region *GetFirstRegion() const
173 {
174 return regionList_.GetFirst();
175 }
176
GetRegionCount()177 uint32_t GetRegionCount()
178 {
179 return regionList_.GetLength();
180 }
181
GetRegionList()182 EcmaList<Region> &GetRegionList()
183 {
184 return regionList_;
185 }
186
GetRegionList()187 const EcmaList<Region> &GetRegionList() const
188 {
189 return regionList_;
190 }
191
SetRecordRegion()192 void SetRecordRegion()
193 {
194 recordRegion_ = GetCurrentRegion();
195 }
196
IsOOMDumpSpace()197 bool IsOOMDumpSpace()
198 {
199 return spaceType_ == OLD_SPACE || spaceType_ == NON_MOVABLE || spaceType_ == HUGE_OBJECT_SPACE ||
200 spaceType_ == MACHINE_CODE_SPACE;
201 }
202
203 // methods for allocation inspector
204 void AddAllocationInspector(AllocationInspector* inspector);
205 void ClearAllocationInspector();
206 void SwapAllocationCounter(Space *space);
207
208 template <class Callback>
209 inline void EnumerateRegions(const Callback &cb, Region *region = nullptr) const;
210 template <class Callback>
211 inline void EnumerateRegionsWithRecord(const Callback &cb) const;
212
213 inline void AddRegion(Region *region);
214 inline void RemoveRegion(Region *region);
215
Initialize()216 virtual void Initialize() {};
217 void Destroy();
218
219 void ReclaimRegions(size_t cachedSize = 0);
220
221 protected:
222 void ClearAndFreeRegion(Region *region, size_t cachedSize = 0);
223
224 Heap *heap_ {nullptr};
225 HeapRegionAllocator *heapRegionAllocator_ {nullptr};
226 EcmaList<Region> regionList_ {};
227 MemSpaceType spaceType_ {};
228 size_t initialCapacity_ {0};
229 size_t maximumCapacity_ {0};
230 size_t committedSize_ {0};
231 size_t objectSize_ {0};
232 size_t outOfMemoryOvershootSize_ {0};
233 Region *recordRegion_ {nullptr};
234 AllocationCounter allocationCounter_;
235 };
236
237 class HugeObjectSpace : public Space {
238 public:
239 HugeObjectSpace(Heap* heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity,
240 size_t maximumCapacity);
241 HugeObjectSpace(Heap* heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity,
242 size_t maximumCapacity, MemSpaceType spaceType);
243 ~HugeObjectSpace() override = default;
244 NO_COPY_SEMANTIC(HugeObjectSpace);
245 NO_MOVE_SEMANTIC(HugeObjectSpace);
246 uintptr_t Allocate(size_t objectSize, JSThread *thread);
247 void Sweep();
248 size_t GetHeapObjectSize() const;
249 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const;
250
251 void ReclaimHugeRegion();
252
253 void InvokeAllocationInspector(Address object, size_t objectSize);
254
255 private:
256 static constexpr size_t HUGE_OBJECT_BITSET_SIZE = 16;
257 EcmaList<Region> hugeNeedFreeList_ {};
258 };
259
260 class HugeMachineCodeSpace : public HugeObjectSpace {
261 public:
262 HugeMachineCodeSpace(Heap* heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity,
263 size_t maximumCapacity);
264 };
265
266 } // namespace panda::ecmascript
267 #endif // ECMASCRIPT_MEM_SPACE_H
268