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