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_REGION_INL_H
17 #define ECMASCRIPT_MEM_REGION_INL_H
18
19 #include "ecmascript/mem/region.h"
20
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/mem/mem.h"
23 #include "ecmascript/mem/native_area_allocator.h"
24
25 namespace panda::ecmascript {
CreateRememberedSet()26 inline RememberedSet *Region::CreateRememberedSet()
27 {
28 auto bitSize = GCBitset::SizeOfGCBitset(GetCapacity());
29 auto setAddr = thread_->GetNativeAreaAllocator()->Allocate(bitSize + RememberedSet::GCBITSET_DATA_OFFSET);
30 auto ret = new (setAddr) RememberedSet(bitSize);
31 ret->ClearAll();
32 std::atomic_thread_fence(std::memory_order_seq_cst);
33 return ret;
34 }
35
GetOrCreateCrossRegionRememberedSet()36 inline RememberedSet *Region::GetOrCreateCrossRegionRememberedSet()
37 {
38 if (UNLIKELY(crossRegionSet_ == nullptr)) {
39 LockHolder lock(*lock_);
40 if (crossRegionSet_ == nullptr) {
41 crossRegionSet_ = CreateRememberedSet();
42 }
43 }
44 return crossRegionSet_;
45 }
46
GetOrCreateOldToNewRememberedSet()47 inline RememberedSet *Region::GetOrCreateOldToNewRememberedSet()
48 {
49 if (UNLIKELY(packedData_.oldToNewSet_ == nullptr)) {
50 LockHolder lock(*lock_);
51 if (packedData_.oldToNewSet_ == nullptr) {
52 if (sweepingRSet_ != nullptr && IsGCFlagSet(RegionGCFlags::HAS_BEEN_SWEPT)) {
53 packedData_.oldToNewSet_ = sweepingRSet_;
54 sweepingRSet_ = nullptr;
55 } else {
56 packedData_.oldToNewSet_ = CreateRememberedSet();
57 }
58 }
59 }
60 return packedData_.oldToNewSet_;
61 }
62
MergeRSetForConcurrentSweeping()63 inline void Region::MergeRSetForConcurrentSweeping()
64 {
65 if (sweepingRSet_ == nullptr) {
66 return;
67 }
68 if (packedData_.oldToNewSet_ == nullptr) {
69 packedData_.oldToNewSet_ = sweepingRSet_;
70 sweepingRSet_ = nullptr;
71 } else {
72 packedData_.oldToNewSet_->Merge(sweepingRSet_);
73 DeleteSweepingRSet();
74 sweepingRSet_ = nullptr;
75 }
76 }
77
GetMarkGCBitset()78 inline GCBitset *Region::GetMarkGCBitset() const
79 {
80 return packedData_.markGCBitset_;
81 }
82
AtomicMark(void * address)83 inline bool Region::AtomicMark(void *address)
84 {
85 auto addrPtr = reinterpret_cast<uintptr_t>(address);
86 ASSERT(InRange(addrPtr));
87 return packedData_.markGCBitset_->SetBit<AccessType::ATOMIC>(
88 (addrPtr & DEFAULT_REGION_MASK) >> TAGGED_TYPE_SIZE_LOG);
89 }
90
ClearMark(void * address)91 inline void Region::ClearMark(void *address)
92 {
93 auto addrPtr = reinterpret_cast<uintptr_t>(address);
94 ASSERT(InRange(addrPtr));
95 packedData_.markGCBitset_->ClearBit((addrPtr & DEFAULT_REGION_MASK) >> TAGGED_TYPE_SIZE_LOG);
96 }
97
Test(void * addr)98 inline bool Region::Test(void *addr) const
99 {
100 auto addrPtr = reinterpret_cast<uintptr_t>(addr);
101 ASSERT(InRange(addrPtr));
102 return packedData_.markGCBitset_->TestBit((addrPtr & DEFAULT_REGION_MASK) >> TAGGED_TYPE_SIZE_LOG);
103 }
104
105 // ONLY used for heap verification.
TestOldToNew(uintptr_t addr)106 inline bool Region::TestOldToNew(uintptr_t addr)
107 {
108 ASSERT(InRange(addr));
109 // Only used for heap verification, so donot need to use lock
110 auto set = packedData_.oldToNewSet_;
111 if (set == nullptr) {
112 return false;
113 }
114 return set->TestBit(ToUintPtr(this), addr);
115 }
116
117 template <typename Visitor>
IterateAllMarkedBits(Visitor visitor)118 inline void Region::IterateAllMarkedBits(Visitor visitor) const
119 {
120 packedData_.markGCBitset_->IterateMarkedBitsConst(
121 reinterpret_cast<uintptr_t>(this), packedData_.bitsetSize_, visitor);
122 }
123
ClearMarkGCBitset()124 inline void Region::ClearMarkGCBitset()
125 {
126 if (packedData_.markGCBitset_ != nullptr) {
127 packedData_.markGCBitset_->Clear(packedData_.bitsetSize_);
128 }
129 }
130
InsertCrossRegionRSet(uintptr_t addr)131 inline void Region::InsertCrossRegionRSet(uintptr_t addr)
132 {
133 auto set = GetOrCreateCrossRegionRememberedSet();
134 set->Insert(ToUintPtr(this), addr);
135 }
136
AtomicInsertCrossRegionRSet(uintptr_t addr)137 inline void Region::AtomicInsertCrossRegionRSet(uintptr_t addr)
138 {
139 auto set = GetOrCreateCrossRegionRememberedSet();
140 set->AtomicInsert(ToUintPtr(this), addr);
141 }
142
143 template <typename Visitor>
IterateAllCrossRegionBits(Visitor visitor)144 inline void Region::IterateAllCrossRegionBits(Visitor visitor) const
145 {
146 if (crossRegionSet_ != nullptr) {
147 crossRegionSet_->IterateAllMarkedBitsConst(ToUintPtr(this), visitor);
148 }
149 }
150
ClearCrossRegionRSet()151 inline void Region::ClearCrossRegionRSet()
152 {
153 if (crossRegionSet_ != nullptr) {
154 crossRegionSet_->ClearAll();
155 }
156 }
157
ClearCrossRegionRSetInRange(uintptr_t start,uintptr_t end)158 inline void Region::ClearCrossRegionRSetInRange(uintptr_t start, uintptr_t end)
159 {
160 if (crossRegionSet_ != nullptr) {
161 crossRegionSet_->ClearRange(ToUintPtr(this), start, end);
162 }
163 }
164
AtomicClearCrossRegionRSetInRange(uintptr_t start,uintptr_t end)165 inline void Region::AtomicClearCrossRegionRSetInRange(uintptr_t start, uintptr_t end)
166 {
167 if (crossRegionSet_ != nullptr) {
168 crossRegionSet_->AtomicClearRange(ToUintPtr(this), start, end);
169 }
170 }
171
DeleteCrossRegionRSet()172 inline void Region::DeleteCrossRegionRSet()
173 {
174 if (crossRegionSet_ != nullptr) {
175 thread_->GetNativeAreaAllocator()->Free(crossRegionSet_, crossRegionSet_->Size());
176 crossRegionSet_ = nullptr;
177 }
178 }
179
InsertOldToNewRSet(uintptr_t addr)180 inline void Region::InsertOldToNewRSet(uintptr_t addr)
181 {
182 auto set = GetOrCreateOldToNewRememberedSet();
183 set->Insert(ToUintPtr(this), addr);
184 }
185
ClearOldToNewRSet(uintptr_t addr)186 inline void Region::ClearOldToNewRSet(uintptr_t addr)
187 {
188 auto set = GetOrCreateOldToNewRememberedSet();
189 set->ClearBit(ToUintPtr(this), addr);
190 }
191
192 template <typename Visitor>
IterateAllOldToNewBits(Visitor visitor)193 inline void Region::IterateAllOldToNewBits(Visitor visitor)
194 {
195 if (packedData_.oldToNewSet_ != nullptr) {
196 packedData_.oldToNewSet_->IterateAllMarkedBits(ToUintPtr(this), visitor);
197 }
198 }
199
200 template <typename Visitor>
AtomicIterateAllSweepingRSetBits(Visitor visitor)201 inline void Region::AtomicIterateAllSweepingRSetBits(Visitor visitor)
202 {
203 if (sweepingRSet_ != nullptr) {
204 sweepingRSet_->AtomicIterateAllMarkedBits(ToUintPtr(this), visitor);
205 }
206 }
207
208 template <typename Visitor>
IterateAllSweepingRSetBits(Visitor visitor)209 inline void Region::IterateAllSweepingRSetBits(Visitor visitor)
210 {
211 if (sweepingRSet_ != nullptr) {
212 sweepingRSet_->IterateAllMarkedBits(ToUintPtr(this), visitor);
213 }
214 }
215
ClearOldToNewRSet()216 inline void Region::ClearOldToNewRSet()
217 {
218 if (packedData_.oldToNewSet_ != nullptr) {
219 packedData_.oldToNewSet_->ClearAll();
220 }
221 }
222
ClearOldToNewRSetInRange(uintptr_t start,uintptr_t end)223 inline void Region::ClearOldToNewRSetInRange(uintptr_t start, uintptr_t end)
224 {
225 if (packedData_.oldToNewSet_ != nullptr) {
226 packedData_.oldToNewSet_->ClearRange(ToUintPtr(this), start, end);
227 }
228 }
229
DeleteOldToNewRSet()230 inline void Region::DeleteOldToNewRSet()
231 {
232 if (packedData_.oldToNewSet_ != nullptr) {
233 thread_->GetNativeAreaAllocator()->Free(packedData_.oldToNewSet_, packedData_.oldToNewSet_->Size());
234 packedData_.oldToNewSet_ = nullptr;
235 }
236 }
237
AtomicClearSweepingRSetInRange(uintptr_t start,uintptr_t end)238 inline void Region::AtomicClearSweepingRSetInRange(uintptr_t start, uintptr_t end)
239 {
240 if (sweepingRSet_ != nullptr) {
241 sweepingRSet_->AtomicClearRange(ToUintPtr(this), start, end);
242 }
243 }
244
ClearSweepingRSetInRange(uintptr_t start,uintptr_t end)245 inline void Region::ClearSweepingRSetInRange(uintptr_t start, uintptr_t end)
246 {
247 if (sweepingRSet_ != nullptr) {
248 sweepingRSet_->ClearRange(ToUintPtr(this), start, end);
249 }
250 }
251
DeleteSweepingRSet()252 inline void Region::DeleteSweepingRSet()
253 {
254 if (sweepingRSet_ != nullptr) {
255 thread_->GetNativeAreaAllocator()->Free(sweepingRSet_, sweepingRSet_->Size());
256 sweepingRSet_ = nullptr;
257 }
258 }
259 } // namespace panda::ecmascript
260 #endif // ECMASCRIPT_MEM_REGION_INL_H
261