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