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