• 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 
21 #define CHECK_OBJECT_AND_INC_OBJ_SIZE(size) \
22     if (object != 0) {                      \
23         IncrementLiveObjectSize(size);      \
24         return object;                      \
25     }
26 
27 enum class SweepState : uint8_t {
28     NO_SWEEP,
29     SWEEPING,
30     SWEPT
31 };
32 
33 namespace panda::ecmascript {
34 class LocalSpace;
35 
36 class SparseSpace : public Space {
37 public:
38     explicit SparseSpace(Heap *heap, MemSpaceType type, size_t initialCapacity, size_t maximumCapacity);
~SparseSpace()39     ~SparseSpace()
40     {
41         delete allocator_;
42     }
43     NO_COPY_SEMANTIC(SparseSpace);
44     NO_MOVE_SEMANTIC(SparseSpace);
45 
46     void Initialize() override;
47     void Reset();
48 
49     uintptr_t Allocate(size_t size, bool isAllowGC = true);
50     bool Expand();
51 
52     // For sweeping
53     void PrepareSweeping();
54     void AsyncSweeping(bool isMain);
55     void Sweeping();
56 
57     bool FillSweptRegion();
58 
59     void AddSweepingRegion(Region *region);
60     void SortSweepingRegion();
61     Region *GetSweepingRegionSafe();
62     void AddSweptRegionSafe(Region *region);
63     Region *GetSweptRegionSafe();
64 
65     void FreeRegion(Region *current, bool isMain = true);
66     void FreeLiveRange(Region *current, uintptr_t freeStart, uintptr_t freeEnd, bool isMain);
67 
68     void DetachFreeObjectSet(Region *region);
69 
70     void IterateOverObjects(const std::function<void(TaggedObject *object)> &objectVisitor) const;
71 
72     size_t GetHeapObjectSize() const;
IncrementLiveObjectSize(size_t size)73     void IncrementLiveObjectSize(size_t size)
74     {
75         liveObjectSize_ += size;
76     }
77 
DecrementLiveObjectSize(size_t size)78     void DecrementLiveObjectSize(size_t size)
79     {
80         liveObjectSize_ -= size;
81     }
82 
83     size_t GetTotalAllocatedSize() const;
84 
85 protected:
86     FreeListAllocator *allocator_;
87     SweepState sweepState_ = SweepState::NO_SWEEP;
88 
89 private:
90     // For sweeping
91     uintptr_t AllocateAfterSweepingCompleted(size_t size);
92 
93     os::memory::Mutex lock_;
94     std::vector<Region *> sweepingList_;
95     std::vector<Region *> sweptList_;
96     size_t liveObjectSize_ {0};
97 };
98 
99 class OldSpace : public SparseSpace {
100 public:
101     explicit OldSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
102     ~OldSpace() override = default;
103     NO_COPY_SEMANTIC(OldSpace);
104     NO_MOVE_SEMANTIC(OldSpace);
105 
106     /* The most extreme situation:
107      * All the younger generation were promoted, and there was no free space in the old space.
108      */
CanExpand(size_t promoteSize)109     bool CanExpand(size_t promoteSize)
110     {
111         return initialCapacity_ > committedSize_ + promoteSize;
112     }
113     Region *TryToGetExclusiveRegion(size_t size);
114 
115     // CSet
116     void SelectCSet();
117     void CheckRegionSize();
118     void RevertCSet();
119     void ReclaimCSet();
IsCSetEmpty()120     bool IsCSetEmpty() const
121     {
122         return isCSetEmpty_;
123     }
GetSelectedRegionNumber()124     unsigned long GetSelectedRegionNumber() const
125     {
126         return std::max(committedSize_ / PARTIAL_GC_MAX_COLLECT_REGION_RATE, PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE);
127     }
128 
129     template<class Callback>
EnumerateCollectRegionSet(const Callback & cb)130     void EnumerateCollectRegionSet(const Callback &cb) const
131     {
132         for (Region *current : collectRegionSet_) {
133             if (current != nullptr) {
134                 cb(current);
135             }
136         }
137     }
138 
139     void Merge(LocalSpace *localSpace);
140 private:
141     static constexpr unsigned long PARTIAL_GC_MAX_COLLECT_REGION_RATE =  1024 * 1024 * 2;
142     static constexpr unsigned long PARTIAL_GC_INITIAL_COLLECT_REGION_SIZE = 16;
143     static constexpr size_t PARTIAL_GC_MIN_COLLECT_REGION_SIZE = 5;
144 
145     CVector<Region *> collectRegionSet_;
146     bool isCSetEmpty_ {true};
147     os::memory::Mutex lock_;
148 };
149 
150 class NonMovableSpace : public SparseSpace {
151 public:
152     explicit NonMovableSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
153     ~NonMovableSpace() override = default;
154     NO_COPY_SEMANTIC(NonMovableSpace);
155     NO_MOVE_SEMANTIC(NonMovableSpace);
156 };
157 
158 class LocalSpace : public SparseSpace {
159 public:
160     LocalSpace() = delete;
161     explicit LocalSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
162     ~LocalSpace() override = default;
163     NO_COPY_SEMANTIC(LocalSpace);
164     NO_MOVE_SEMANTIC(LocalSpace);
165 
166     uintptr_t Allocate(size_t size, bool isExpand = true);
167     bool AddRegionToList(Region *region);
168     void FreeBumpPoint();
169 };
170 
171 class MachineCodeSpace : public SparseSpace {
172 public:
173     explicit MachineCodeSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity);
174     ~MachineCodeSpace() override = default;
175     NO_COPY_SEMANTIC(MachineCodeSpace);
176     NO_MOVE_SEMANTIC(MachineCodeSpace);  // Note: Expand() left for define
177 };
178 }  // namespace panda::ecmascript
179 #endif  // ECMASCRIPT_MEM_SPARSE_SPACE_H
180