• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_SPARSE_SPACE_H
17 #define ECMASCRIPT_MEM_SPARSE_SPACE_H
18 
19 #include "ecmascript/mem/space-inl.h"
20 #include "ecmascript/mem/mem_common.h"
21 
22 #ifdef ECMASCRIPT_SUPPORT_HEAPSAMPLING
23 #define CHECK_OBJECT_AND_INC_OBJ_SIZE(size)                                   \
24     if (object != 0) {                                                        \
25         IncreaseLiveObjectSize(size);                                         \
26         if (!heap_->IsFullMark() || heap_->GetJSThread()->IsReadyToMark()) {  \
27             Region::ObjectAddressToRange(object)->IncreaseAliveObject(size);  \
28         }                                                                     \
29         InvokeAllocationInspector(object, size, size);                        \
30         return object;                                                        \
31     }
32 #else
33 #define CHECK_OBJECT_AND_INC_OBJ_SIZE(size)                                   \
34     if (object != 0) {                                                        \
35         IncreaseLiveObjectSize(size);                                         \
36         if (!heap_->IsFullMark() || heap_->GetJSThread()->IsReadyToMark()) {  \
37             Region::ObjectAddressToRange(object)->IncreaseAliveObject(size);  \
38         }                                                                     \
39         return object;                                                        \
40     }
41 #endif
42 
43 enum class SweepState : uint8_t {
44     NO_SWEEP,
45     SWEEPING,
46     SWEPT
47 };
48 
49 namespace panda::ecmascript {
50 class LocalSpace;
51 
52 class SparseSpace : public Space {
53 public:
54     SparseSpace(Heap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity);
~SparseSpace()55     ~SparseSpace() override
56     {
57         delete allocator_;
58     }
59     NO_COPY_SEMANTIC(SparseSpace);
60     NO_MOVE_SEMANTIC(SparseSpace);
61 
62     void Initialize() override;
63     void Reset();
64 
65     uintptr_t Allocate(size_t size, bool allowGC = true);
66     bool Expand();
67 
68     // For sweeping
69     void PrepareSweeping();
70     void AsyncSweep(bool isMain);
71     void Sweep();
72 
73     bool TryFillSweptRegion();
74     // Ensure All region finished sweeping
75     bool FinishFillSweptRegion();
76 
77     void AddSweepingRegion(Region *region);
78     void SortSweepingRegion();
79     Region *GetSweepingRegionSafe();
80     void AddSweptRegionSafe(Region *region);
81     Region *GetSweptRegionSafe();
82     void FreeRegionFromSpace(Region *region);
83     Region *TryToGetSuitableSweptRegion(size_t size);
84 
85     void FreeRegion(Region *current, bool isMain = true);
86     void FreeLiveRange(Region *current, uintptr_t freeStart, uintptr_t freeEnd, bool isMain);
87 
88     void DetachFreeObjectSet(Region *region);
89 
90     void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const;
91     void IterateOldToNewOverObjects(
92         const std::function<void(TaggedObject *object, JSTaggedValue value)> &visitor) const;
93 
94     size_t GetHeapObjectSize() const;
95 
96     void IncreaseAllocatedSize(size_t size);
97 
IncreaseLiveObjectSize(size_t size)98     void IncreaseLiveObjectSize(size_t size)
99     {
100         liveObjectSize_ += size;
101     }
102 
DecreaseLiveObjectSize(size_t size)103     void DecreaseLiveObjectSize(size_t size)
104     {
105         liveObjectSize_ -= size;
106     }
107 
108     size_t GetTotalAllocatedSize() const;
109 
110     void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize);
111 
112 protected:
113     FreeListAllocator *allocator_;
114     SweepState sweepState_ = SweepState::NO_SWEEP;
115     Heap *heap_ {nullptr};
116 
117 private:
118     // For sweeping
119     uintptr_t AllocateAfterSweepingCompleted(size_t size);
120 
121     os::memory::Mutex lock_;
122     std::vector<Region *> sweepingList_;
123     std::vector<Region *> sweptList_;
124     size_t liveObjectSize_ {0};
125 };
126 
127 class OldSpace : public SparseSpace {
128 public:
129     OldSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
130     ~OldSpace() override = default;
131     NO_COPY_SEMANTIC(OldSpace);
132     NO_MOVE_SEMANTIC(OldSpace);
133 
134     Region *TrySweepToGetSuitableRegion(size_t size);
135     Region *TryToGetExclusiveRegion(size_t size);
136 
137     // CSet
138     void SelectCSet();
139     void CheckRegionSize();
140     void RevertCSet();
141     void ReclaimCSet();
142 
GetSelectedRegionNumber()143     unsigned long GetSelectedRegionNumber() const
144     {
145         return std::max(committedSize_ / PARTIAL_GC_MAX_COLLECT_REGION_RATE, PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE);
146     }
147 
GetMergeSize()148     size_t GetMergeSize() const
149     {
150         return mergeSize_;
151     }
152 
IncreaseMergeSize(size_t size)153     void IncreaseMergeSize(size_t size)
154     {
155         mergeSize_ += size;
156     }
157 
ResetMergeSize()158     void ResetMergeSize()
159     {
160         mergeSize_ = 0;
161     }
162 
163     template<class Callback>
EnumerateCollectRegionSet(const Callback & cb)164     void EnumerateCollectRegionSet(const Callback &cb) const
165     {
166         for (Region *current : collectRegionSet_) {
167             if (current != nullptr) {
168                 cb(current);
169             }
170         }
171     }
172 
173     void Merge(LocalSpace *localSpace);
174 private:
175     static constexpr int64_t PARTIAL_GC_MAX_EVACUATION_SIZE_FOREGROUND = 2_MB;
176     static constexpr int64_t PARTIAL_GC_MAX_EVACUATION_SIZE_BACKGROUND = 6_MB;
177     static constexpr unsigned long long PARTIAL_GC_MAX_COLLECT_REGION_RATE = 2_MB;
178     static constexpr unsigned long long PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE = 24;
179     static constexpr size_t PARTIAL_GC_MIN_COLLECT_REGION_SIZE = 5;
180 
181     CVector<Region *> collectRegionSet_;
182     os::memory::Mutex lock_;
183     size_t mergeSize_ {0};
184 };
185 
186 class NonMovableSpace : public SparseSpace {
187 public:
188     NonMovableSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
189     ~NonMovableSpace() override = default;
190     NO_COPY_SEMANTIC(NonMovableSpace);
191     NO_MOVE_SEMANTIC(NonMovableSpace);
192 };
193 
194 class AppSpawnSpace : public SparseSpace {
195 public:
196     AppSpawnSpace(Heap *heap, size_t initialCapacity);
197     ~AppSpawnSpace() override = default;
198     NO_COPY_SEMANTIC(AppSpawnSpace);
199     NO_MOVE_SEMANTIC(AppSpawnSpace);
200 
201     void IterateOverMarkedObjects(const std::function<void(TaggedObject *object)> &visitor) const;
202 };
203 
204 class LocalSpace : public SparseSpace {
205 public:
206     LocalSpace() = delete;
207     LocalSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
208     ~LocalSpace() override = default;
209     NO_COPY_SEMANTIC(LocalSpace);
210     NO_MOVE_SEMANTIC(LocalSpace);
211 
212     uintptr_t Allocate(size_t size, bool isExpand = true);
213     bool AddRegionToList(Region *region);
214     void FreeBumpPoint();
215     void Stop();
216 };
217 
218 class MachineCodeSpace : public SparseSpace {
219 public:
220     MachineCodeSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
221     ~MachineCodeSpace() override = default;
222     NO_COPY_SEMANTIC(MachineCodeSpace);
223     NO_MOVE_SEMANTIC(MachineCodeSpace);  // Note: Expand() left for define
224 };
225 }  // namespace panda::ecmascript
226 #endif  // ECMASCRIPT_MEM_SPARSE_SPACE_H
227