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