• 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_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