xref: /aosp_15_r20/art/runtime/handle_scope-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_HANDLE_SCOPE_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_HANDLE_SCOPE_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "handle_scope.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
24*795d594fSAndroid Build Coastguard Worker #include "handle.h"
25*795d594fSAndroid Build Coastguard Worker #include "handle_wrapper.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/object_reference-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "verify_object.h"
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker template<size_t kNumReferences>
FixedSizeHandleScope(BaseHandleScope * link)34*795d594fSAndroid Build Coastguard Worker inline FixedSizeHandleScope<kNumReferences>::FixedSizeHandleScope(BaseHandleScope* link)
35*795d594fSAndroid Build Coastguard Worker     : HandleScope(link, kNumReferences) {
36*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
37*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
38*795d594fSAndroid Build Coastguard Worker   }
39*795d594fSAndroid Build Coastguard Worker   static_assert(kNumReferences >= 1, "FixedSizeHandleScope must contain at least 1 reference");
40*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(&storage_[0], GetReferences());  // TODO: Figure out how to use a compile assert.
41*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
42*795d594fSAndroid Build Coastguard Worker     // Fill storage with "DEAD HAndleSCope", mapping H->"4" and S->"5".
43*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < kNumReferences; ++i) {
44*795d594fSAndroid Build Coastguard Worker       GetReferences()[i].Assign(reinterpret_cast32<mirror::Object*>(0xdead4a5c));
45*795d594fSAndroid Build Coastguard Worker     }
46*795d594fSAndroid Build Coastguard Worker   }
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker 
49*795d594fSAndroid Build Coastguard Worker template<size_t kNumReferences>
StackHandleScope(Thread * self)50*795d594fSAndroid Build Coastguard Worker inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self)
51*795d594fSAndroid Build Coastguard Worker     : FixedSizeHandleScope<kNumReferences>(self->GetTopHandleScope()),
52*795d594fSAndroid Build Coastguard Worker       self_(self) {
53*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(self, Thread::Current());
54*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
55*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(self_);
56*795d594fSAndroid Build Coastguard Worker   }
57*795d594fSAndroid Build Coastguard Worker   self_->PushHandleScope(this);
58*795d594fSAndroid Build Coastguard Worker }
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker template<size_t kNumReferences>
~StackHandleScope()61*795d594fSAndroid Build Coastguard Worker inline StackHandleScope<kNumReferences>::~StackHandleScope() {
62*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
63*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(self_);
64*795d594fSAndroid Build Coastguard Worker   }
65*795d594fSAndroid Build Coastguard Worker   BaseHandleScope* top_handle_scope = self_->PopHandleScope();
66*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(top_handle_scope, this);
67*795d594fSAndroid Build Coastguard Worker }
68*795d594fSAndroid Build Coastguard Worker 
GetReference(size_t i)69*795d594fSAndroid Build Coastguard Worker inline ObjPtr<mirror::Object> HandleScope::GetReference(size_t i) const {
70*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(i, Size());
71*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
72*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker   return GetReferences()[i].AsMirrorPtr();
75*795d594fSAndroid Build Coastguard Worker }
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker template<class T>
GetHandle(size_t i)78*795d594fSAndroid Build Coastguard Worker inline Handle<T> HandleScope::GetHandle(size_t i) {
79*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(i, Size());
80*795d594fSAndroid Build Coastguard Worker   return Handle<T>(&GetReferences()[i]);
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker template<class T>
GetMutableHandle(size_t i)84*795d594fSAndroid Build Coastguard Worker inline MutableHandle<T> HandleScope::GetMutableHandle(size_t i) {
85*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(i, Size());
86*795d594fSAndroid Build Coastguard Worker   return MutableHandle<T>(&GetReferences()[i]);
87*795d594fSAndroid Build Coastguard Worker }
88*795d594fSAndroid Build Coastguard Worker 
SetReference(size_t i,ObjPtr<mirror::Object> object)89*795d594fSAndroid Build Coastguard Worker inline void HandleScope::SetReference(size_t i, ObjPtr<mirror::Object> object) {
90*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
91*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
92*795d594fSAndroid Build Coastguard Worker   }
93*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(i, Size());
94*795d594fSAndroid Build Coastguard Worker   VerifyObject(object);
95*795d594fSAndroid Build Coastguard Worker   GetReferences()[i].Assign(object);
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker template<class T>
NewHandle(T * object)99*795d594fSAndroid Build Coastguard Worker inline MutableHandle<T> HandleScope::NewHandle(T* object) {
100*795d594fSAndroid Build Coastguard Worker   return NewHandle(ObjPtr<T>(object));
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker template<class MirrorType>
NewHandle(ObjPtr<MirrorType> object)104*795d594fSAndroid Build Coastguard Worker inline MutableHandle<MirrorType> HandleScope::NewHandle(
105*795d594fSAndroid Build Coastguard Worker     ObjPtr<MirrorType> object) {
106*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(Size(), Capacity());
107*795d594fSAndroid Build Coastguard Worker   size_t pos = size_;
108*795d594fSAndroid Build Coastguard Worker   ++size_;
109*795d594fSAndroid Build Coastguard Worker   SetReference(pos, object);
110*795d594fSAndroid Build Coastguard Worker   MutableHandle<MirrorType> h(GetMutableHandle<MirrorType>(pos));
111*795d594fSAndroid Build Coastguard Worker   return h;
112*795d594fSAndroid Build Coastguard Worker }
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker template<class T>
NewHandleWrapper(T ** object)115*795d594fSAndroid Build Coastguard Worker inline HandleWrapper<T> HandleScope::NewHandleWrapper(T** object) {
116*795d594fSAndroid Build Coastguard Worker   return HandleWrapper<T>(object, NewHandle(*object));
117*795d594fSAndroid Build Coastguard Worker }
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker template<class T>
NewHandleWrapper(ObjPtr<T> * object)120*795d594fSAndroid Build Coastguard Worker inline HandleWrapperObjPtr<T> HandleScope::NewHandleWrapper(
121*795d594fSAndroid Build Coastguard Worker     ObjPtr<T>* object) {
122*795d594fSAndroid Build Coastguard Worker   return HandleWrapperObjPtr<T>(object, NewHandle(*object));
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker 
Contains(StackReference<mirror::Object> * handle_scope_entry)125*795d594fSAndroid Build Coastguard Worker inline bool HandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const {
126*795d594fSAndroid Build Coastguard Worker   return GetReferences() <= handle_scope_entry && handle_scope_entry < GetReferences() + size_;
127*795d594fSAndroid Build Coastguard Worker }
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitRoots(Visitor & visitor)130*795d594fSAndroid Build Coastguard Worker inline void HandleScope::VisitRoots(Visitor& visitor) {
131*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0, size = Size(); i < size; ++i) {
132*795d594fSAndroid Build Coastguard Worker     // GetReference returns a pointer to the stack reference within the handle scope. If this
133*795d594fSAndroid Build Coastguard Worker     // needs to be updated, it will be done by the root visitor.
134*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(GetHandle<mirror::Object>(i).GetReference());
135*795d594fSAndroid Build Coastguard Worker   }
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitHandles(Visitor & visitor)139*795d594fSAndroid Build Coastguard Worker inline void HandleScope::VisitHandles(Visitor& visitor) {
140*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0, size = Size(); i < size; ++i) {
141*795d594fSAndroid Build Coastguard Worker     if (GetHandle<mirror::Object>(i) != nullptr) {
142*795d594fSAndroid Build Coastguard Worker       visitor.Visit(GetHandle<mirror::Object>(i));
143*795d594fSAndroid Build Coastguard Worker     }
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker }
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker // The current size of this handle scope.
Size()148*795d594fSAndroid Build Coastguard Worker inline uint32_t BaseHandleScope::Size() const {
149*795d594fSAndroid Build Coastguard Worker   return LIKELY(!IsVariableSized())
150*795d594fSAndroid Build Coastguard Worker       ? AsHandleScope()->Size()
151*795d594fSAndroid Build Coastguard Worker       : AsVariableSized()->Size();
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker // The current capacity of this handle scope.
Capacity()155*795d594fSAndroid Build Coastguard Worker inline uint32_t BaseHandleScope::Capacity() const {
156*795d594fSAndroid Build Coastguard Worker   return LIKELY(!IsVariableSized())
157*795d594fSAndroid Build Coastguard Worker       ? AsHandleScope()->Capacity()
158*795d594fSAndroid Build Coastguard Worker       : AsVariableSized()->Capacity();
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker 
Contains(StackReference<mirror::Object> * handle_scope_entry)161*795d594fSAndroid Build Coastguard Worker inline bool BaseHandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const {
162*795d594fSAndroid Build Coastguard Worker   return LIKELY(!IsVariableSized())
163*795d594fSAndroid Build Coastguard Worker       ? AsHandleScope()->Contains(handle_scope_entry)
164*795d594fSAndroid Build Coastguard Worker       : AsVariableSized()->Contains(handle_scope_entry);
165*795d594fSAndroid Build Coastguard Worker }
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitRoots(Visitor & visitor)168*795d594fSAndroid Build Coastguard Worker inline void BaseHandleScope::VisitRoots(Visitor& visitor) {
169*795d594fSAndroid Build Coastguard Worker   if (LIKELY(!IsVariableSized())) {
170*795d594fSAndroid Build Coastguard Worker     AsHandleScope()->VisitRoots(visitor);
171*795d594fSAndroid Build Coastguard Worker   } else {
172*795d594fSAndroid Build Coastguard Worker     AsVariableSized()->VisitRoots(visitor);
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitHandles(Visitor & visitor)177*795d594fSAndroid Build Coastguard Worker inline void BaseHandleScope::VisitHandles(Visitor& visitor) {
178*795d594fSAndroid Build Coastguard Worker   if (LIKELY(!IsVariableSized())) {
179*795d594fSAndroid Build Coastguard Worker     AsHandleScope()->VisitHandles(visitor);
180*795d594fSAndroid Build Coastguard Worker   } else {
181*795d594fSAndroid Build Coastguard Worker     AsVariableSized()->VisitHandles(visitor);
182*795d594fSAndroid Build Coastguard Worker   }
183*795d594fSAndroid Build Coastguard Worker }
184*795d594fSAndroid Build Coastguard Worker 
AsVariableSized()185*795d594fSAndroid Build Coastguard Worker inline VariableSizedHandleScope* BaseHandleScope::AsVariableSized() {
186*795d594fSAndroid Build Coastguard Worker   DCHECK(IsVariableSized());
187*795d594fSAndroid Build Coastguard Worker   return down_cast<VariableSizedHandleScope*>(this);
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker 
AsHandleScope()190*795d594fSAndroid Build Coastguard Worker inline HandleScope* BaseHandleScope::AsHandleScope() {
191*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsVariableSized());
192*795d594fSAndroid Build Coastguard Worker   return down_cast<HandleScope*>(this);
193*795d594fSAndroid Build Coastguard Worker }
194*795d594fSAndroid Build Coastguard Worker 
AsVariableSized()195*795d594fSAndroid Build Coastguard Worker inline const VariableSizedHandleScope* BaseHandleScope::AsVariableSized() const {
196*795d594fSAndroid Build Coastguard Worker   DCHECK(IsVariableSized());
197*795d594fSAndroid Build Coastguard Worker   return down_cast<const VariableSizedHandleScope*>(this);
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker 
AsHandleScope()200*795d594fSAndroid Build Coastguard Worker inline const HandleScope* BaseHandleScope::AsHandleScope() const {
201*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsVariableSized());
202*795d594fSAndroid Build Coastguard Worker   return down_cast<const HandleScope*>(this);
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker template<class T>
NewHandle(T * object)206*795d594fSAndroid Build Coastguard Worker inline MutableHandle<T> VariableSizedHandleScope::NewHandle(T* object) {
207*795d594fSAndroid Build Coastguard Worker   return NewHandle(ObjPtr<T>(object));
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker template<class MirrorType>
NewHandle(ObjPtr<MirrorType> ptr)211*795d594fSAndroid Build Coastguard Worker inline MutableHandle<MirrorType> VariableSizedHandleScope::NewHandle(ObjPtr<MirrorType> ptr) {
212*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(current_scope_->Capacity(), kNumReferencesPerScope);
213*795d594fSAndroid Build Coastguard Worker   if (current_scope_->Size() == kNumReferencesPerScope) {
214*795d594fSAndroid Build Coastguard Worker     current_scope_ = new LocalScopeType(current_scope_);
215*795d594fSAndroid Build Coastguard Worker   }
216*795d594fSAndroid Build Coastguard Worker   return current_scope_->NewHandle(ptr);
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker 
VariableSizedHandleScope(Thread * const self)219*795d594fSAndroid Build Coastguard Worker inline VariableSizedHandleScope::VariableSizedHandleScope(Thread* const self)
220*795d594fSAndroid Build Coastguard Worker     : BaseHandleScope(self->GetTopHandleScope()),
221*795d594fSAndroid Build Coastguard Worker       self_(self),
222*795d594fSAndroid Build Coastguard Worker       current_scope_(&first_scope_),
223*795d594fSAndroid Build Coastguard Worker       first_scope_(/*link=*/ nullptr) {
224*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(self, Thread::Current());
225*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
226*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(self_);
227*795d594fSAndroid Build Coastguard Worker   }
228*795d594fSAndroid Build Coastguard Worker   self_->PushHandleScope(this);
229*795d594fSAndroid Build Coastguard Worker }
230*795d594fSAndroid Build Coastguard Worker 
~VariableSizedHandleScope()231*795d594fSAndroid Build Coastguard Worker inline VariableSizedHandleScope::~VariableSizedHandleScope() {
232*795d594fSAndroid Build Coastguard Worker   if (kDebugLocking) {
233*795d594fSAndroid Build Coastguard Worker     Locks::mutator_lock_->AssertSharedHeld(self_);
234*795d594fSAndroid Build Coastguard Worker   }
235*795d594fSAndroid Build Coastguard Worker   BaseHandleScope* top_handle_scope = self_->PopHandleScope();
236*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(top_handle_scope, this);
237*795d594fSAndroid Build Coastguard Worker   // Don't delete first_scope_ since it is not heap allocated.
238*795d594fSAndroid Build Coastguard Worker   while (current_scope_ != &first_scope_) {
239*795d594fSAndroid Build Coastguard Worker     LocalScopeType* next = down_cast<LocalScopeType*>(current_scope_->GetLink());
240*795d594fSAndroid Build Coastguard Worker     delete current_scope_;
241*795d594fSAndroid Build Coastguard Worker     current_scope_ = next;
242*795d594fSAndroid Build Coastguard Worker   }
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker 
Size()245*795d594fSAndroid Build Coastguard Worker inline uint32_t VariableSizedHandleScope::Size() const {
246*795d594fSAndroid Build Coastguard Worker   const LocalScopeType* cur = current_scope_;
247*795d594fSAndroid Build Coastguard Worker   DCHECK(cur != nullptr);
248*795d594fSAndroid Build Coastguard Worker   // The linked list of local scopes starts from the latest which may not be fully filled.
249*795d594fSAndroid Build Coastguard Worker   uint32_t sum = cur->Size();
250*795d594fSAndroid Build Coastguard Worker   cur = down_cast<const LocalScopeType*>(cur->GetLink());
251*795d594fSAndroid Build Coastguard Worker   while (cur != nullptr) {
252*795d594fSAndroid Build Coastguard Worker     // All other local scopes are fully filled.
253*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(cur->Size(), kNumReferencesPerScope);
254*795d594fSAndroid Build Coastguard Worker     sum += kNumReferencesPerScope;
255*795d594fSAndroid Build Coastguard Worker     cur = down_cast<const LocalScopeType*>(cur->GetLink());
256*795d594fSAndroid Build Coastguard Worker   }
257*795d594fSAndroid Build Coastguard Worker   return sum;
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker 
Capacity()260*795d594fSAndroid Build Coastguard Worker inline uint32_t VariableSizedHandleScope::Capacity() const {
261*795d594fSAndroid Build Coastguard Worker   uint32_t sum = 0;
262*795d594fSAndroid Build Coastguard Worker   const LocalScopeType* cur = current_scope_;
263*795d594fSAndroid Build Coastguard Worker   while (cur != nullptr) {
264*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(cur->Capacity(), kNumReferencesPerScope);
265*795d594fSAndroid Build Coastguard Worker     sum += kNumReferencesPerScope;
266*795d594fSAndroid Build Coastguard Worker     cur = down_cast<const LocalScopeType*>(cur->GetLink());
267*795d594fSAndroid Build Coastguard Worker   }
268*795d594fSAndroid Build Coastguard Worker   return sum;
269*795d594fSAndroid Build Coastguard Worker }
270*795d594fSAndroid Build Coastguard Worker 
Contains(StackReference<mirror::Object> * handle_scope_entry)271*795d594fSAndroid Build Coastguard Worker inline bool VariableSizedHandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry)
272*795d594fSAndroid Build Coastguard Worker     const {
273*795d594fSAndroid Build Coastguard Worker   const LocalScopeType* cur = current_scope_;
274*795d594fSAndroid Build Coastguard Worker   while (cur != nullptr) {
275*795d594fSAndroid Build Coastguard Worker     if (cur->Contains(handle_scope_entry)) {
276*795d594fSAndroid Build Coastguard Worker       return true;
277*795d594fSAndroid Build Coastguard Worker     }
278*795d594fSAndroid Build Coastguard Worker     cur = down_cast<const LocalScopeType*>(cur->GetLink());
279*795d594fSAndroid Build Coastguard Worker   }
280*795d594fSAndroid Build Coastguard Worker   return false;
281*795d594fSAndroid Build Coastguard Worker }
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker template<class T>
GetHandle(size_t i)284*795d594fSAndroid Build Coastguard Worker Handle<T> VariableSizedHandleScope::GetHandle(size_t i) {
285*795d594fSAndroid Build Coastguard Worker   // Handle the most common path efficiently.
286*795d594fSAndroid Build Coastguard Worker   if (i < kNumReferencesPerScope) {
287*795d594fSAndroid Build Coastguard Worker     return first_scope_.GetHandle<T>(i);
288*795d594fSAndroid Build Coastguard Worker   }
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker   uint32_t size = Size();
291*795d594fSAndroid Build Coastguard Worker   DCHECK_GT(size, kNumReferencesPerScope);
292*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(i, size);
293*795d594fSAndroid Build Coastguard Worker   LocalScopeType* cur = current_scope_;
294*795d594fSAndroid Build Coastguard Worker   DCHECK(cur != &first_scope_);
295*795d594fSAndroid Build Coastguard Worker   // The linked list of local scopes starts from the latest which may not be fully filled.
296*795d594fSAndroid Build Coastguard Worker   uint32_t cur_start = size - cur->Size();
297*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(cur_start % kNumReferencesPerScope, 0u);  // All other local scopes are fully filled.
298*795d594fSAndroid Build Coastguard Worker   while (i < cur_start) {
299*795d594fSAndroid Build Coastguard Worker     cur = down_cast<LocalScopeType*>(cur->GetLink());
300*795d594fSAndroid Build Coastguard Worker     DCHECK(cur != nullptr);
301*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(cur->Size(), kNumReferencesPerScope);
302*795d594fSAndroid Build Coastguard Worker     cur_start -= kNumReferencesPerScope;
303*795d594fSAndroid Build Coastguard Worker   }
304*795d594fSAndroid Build Coastguard Worker   return cur->GetHandle<T>(i - cur_start);
305*795d594fSAndroid Build Coastguard Worker }
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitRoots(Visitor & visitor)308*795d594fSAndroid Build Coastguard Worker inline void VariableSizedHandleScope::VisitRoots(Visitor& visitor) {
309*795d594fSAndroid Build Coastguard Worker   LocalScopeType* cur = current_scope_;
310*795d594fSAndroid Build Coastguard Worker   while (cur != nullptr) {
311*795d594fSAndroid Build Coastguard Worker     cur->VisitRoots(visitor);
312*795d594fSAndroid Build Coastguard Worker     cur = down_cast<LocalScopeType*>(cur->GetLink());
313*795d594fSAndroid Build Coastguard Worker   }
314*795d594fSAndroid Build Coastguard Worker }
315*795d594fSAndroid Build Coastguard Worker 
316*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitHandles(Visitor & visitor)317*795d594fSAndroid Build Coastguard Worker inline void VariableSizedHandleScope::VisitHandles(Visitor& visitor) {
318*795d594fSAndroid Build Coastguard Worker   LocalScopeType* cur = current_scope_;
319*795d594fSAndroid Build Coastguard Worker   while (cur != nullptr) {
320*795d594fSAndroid Build Coastguard Worker     cur->VisitHandles(visitor);
321*795d594fSAndroid Build Coastguard Worker     cur = down_cast<LocalScopeType*>(cur->GetLink());
322*795d594fSAndroid Build Coastguard Worker   }
323*795d594fSAndroid Build Coastguard Worker }
324*795d594fSAndroid Build Coastguard Worker 
325*795d594fSAndroid Build Coastguard Worker }  // namespace art
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_HANDLE_SCOPE_INL_H_
328