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/allocator.h"
20 #include "ecmascript/mem/c_containers.h"
21 #include "ecmascript/mem/ecma_list.h"
22 #include "ecmascript/mem/heap_region_allocator.h"
23 #include "ecmascript/mem/mem.h"
24 #include "ecmascript/mem/region.h"
25
26 #include "libpandabase/utils/type_helpers.h"
27
28 #include "securec.h"
29
30 namespace panda::ecmascript {
31 enum MemSpaceType {
32 OLD_SPACE = 0,
33 NON_MOVABLE,
34 MACHINE_CODE_SPACE,
35 HUGE_OBJECT_SPACE,
36 SEMI_SPACE,
37 SNAPSHOT_SPACE,
38 COMPRESS_SPACE,
39 LOCAL_SPACE,
40 READ_ONLY_SPACE,
41 APPSPAWN_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 default:
71 return "unknown space";
72 }
73 }
74
75 class Space {
76 public:
77 Space(HeapRegionAllocator *regionAllocator, MemSpaceType spaceType, size_t initialCapacity, size_t maximumCapacity);
78 virtual ~Space() = default;
79 NO_COPY_SEMANTIC(Space);
80 NO_MOVE_SEMANTIC(Space);
81
GetMaximumCapacity()82 size_t GetMaximumCapacity() const
83 {
84 return maximumCapacity_;
85 }
86
SetMaximumCapacity(size_t maximumCapacity)87 void SetMaximumCapacity(size_t maximumCapacity)
88 {
89 maximumCapacity_ = maximumCapacity;
90 }
91
GetOverShootMaximumCapacity()92 size_t GetOverShootMaximumCapacity() const
93 {
94 return maximumCapacity_ + outOfMemoryOvershootSize_;
95 }
96
GetInitialCapacity()97 size_t GetInitialCapacity() const
98 {
99 return initialCapacity_;
100 }
101
SetInitialCapacity(size_t initialCapacity)102 void SetInitialCapacity(size_t initialCapacity)
103 {
104 initialCapacity_ = initialCapacity;
105 }
106
GetCommittedSize()107 size_t GetCommittedSize() const
108 {
109 return committedSize_;
110 }
111
IncreaseCommitted(size_t bytes)112 void IncreaseCommitted(size_t bytes)
113 {
114 committedSize_ += bytes;
115 }
116
DecreaseCommitted(size_t bytes)117 void DecreaseCommitted(size_t bytes)
118 {
119 committedSize_ -= bytes;
120 }
121
IncreaseObjectSize(size_t bytes)122 void IncreaseObjectSize(size_t bytes)
123 {
124 objectSize_ += bytes;
125 }
126
DecreaseObjectSize(size_t bytes)127 void DecreaseObjectSize(size_t bytes)
128 {
129 objectSize_ -= bytes;
130 }
131
GetOutOfMemoryOvershootSize()132 size_t GetOutOfMemoryOvershootSize() const
133 {
134 return outOfMemoryOvershootSize_;
135 }
136
IncreaseOutOfMemoryOvershootSize(size_t size)137 void IncreaseOutOfMemoryOvershootSize(size_t size)
138 {
139 outOfMemoryOvershootSize_ += size;
140 }
141
GetSpaceType()142 MemSpaceType GetSpaceType() const
143 {
144 return spaceType_;
145 }
146
147 inline RegionSpaceFlag GetRegionFlag() const;
148
GetAllocateAreaBegin()149 uintptr_t GetAllocateAreaBegin() const
150 {
151 return regionList_.GetLast()->GetBegin();
152 }
153
GetAllocateAreaEnd()154 uintptr_t GetAllocateAreaEnd() const
155 {
156 return regionList_.GetLast()->GetEnd();
157 }
158
GetCurrentRegion()159 Region *GetCurrentRegion() const
160 {
161 return regionList_.GetLast();
162 }
163
GetFirstRegion()164 Region *GetFirstRegion() const
165 {
166 return regionList_.GetFirst();
167 }
168
GetRegionCount()169 uint32_t GetRegionCount()
170 {
171 return regionList_.GetLength();
172 }
173
GetRegionList()174 EcmaList<Region> &GetRegionList()
175 {
176 return regionList_;
177 }
178
GetRegionList()179 const EcmaList<Region> &GetRegionList() const
180 {
181 return regionList_;
182 }
183
SetRecordRegion()184 void SetRecordRegion()
185 {
186 recordRegion_ = GetCurrentRegion();
187 }
188
189 template <class Callback>
190 inline void EnumerateRegions(const Callback &cb, Region *region = nullptr) const;
191 template <class Callback>
192 inline void EnumerateRegionsWithRecord(const Callback &cb) const;
193
194 inline void AddRegion(Region *region);
195 inline void RemoveRegion(Region *region);
196
Initialize()197 virtual void Initialize() {};
198 void Destroy();
199
200 void ReclaimRegions();
201
202 protected:
203 void ClearAndFreeRegion(Region *region);
204
205 HeapRegionAllocator *heapRegionAllocator_ {nullptr};
206 EcmaList<Region> regionList_ {};
207 MemSpaceType spaceType_ {};
208 size_t initialCapacity_ {0};
209 size_t maximumCapacity_ {0};
210 size_t committedSize_ {0};
211 size_t objectSize_ {0};
212 size_t outOfMemoryOvershootSize_ {0};
213 Region *recordRegion_ {nullptr};
214 };
215
216 class HugeObjectSpace : public Space {
217 public:
218 explicit HugeObjectSpace(Heap* heap, HeapRegionAllocator *regionAllocator, size_t initialCapacity,
219 size_t maximumCapacity);
220 ~HugeObjectSpace() override = default;
221 NO_COPY_SEMANTIC(HugeObjectSpace);
222 NO_MOVE_SEMANTIC(HugeObjectSpace);
223 uintptr_t Allocate(size_t objectSize, JSThread *thread);
224 void Sweep();
225 size_t GetHeapObjectSize() const;
226 void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const;
227
228 void ReclaimHugeRegion();
229
230 private:
231 static constexpr size_t HUGE_OBJECT_BITSET_SIZE = 16;
232 EcmaList<Region> hugeNeedFreeList_ {};
233 Heap* heap_;
234 };
235 } // namespace panda::ecmascript
236 #endif // ECMASCRIPT_MEM_SPACE_H
237