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