xref: /aosp_15_r20/art/runtime/reflective_handle_scope.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2019 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_REFLECTIVE_HANDLE_SCOPE_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <array>
23*795d594fSAndroid Build Coastguard Worker #include <compare>
24*795d594fSAndroid Build Coastguard Worker #include <functional>
25*795d594fSAndroid Build Coastguard Worker #include <stack>
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h"
33*795d594fSAndroid Build Coastguard Worker #include "reflective_handle.h"
34*795d594fSAndroid Build Coastguard Worker #include "reflective_reference.h"
35*795d594fSAndroid Build Coastguard Worker #include "reflective_value_visitor.h"
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker class ArtField;
40*795d594fSAndroid Build Coastguard Worker class ArtMethod;
41*795d594fSAndroid Build Coastguard Worker class BaseReflectiveHandleScope;
42*795d594fSAndroid Build Coastguard Worker class Thread;
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker // This is a holder similar to StackHandleScope that is used to hold reflective references to
45*795d594fSAndroid Build Coastguard Worker // ArtField and ArtMethod structures. A reflective reference is one that must be updated if the
46*795d594fSAndroid Build Coastguard Worker // underlying class or instances are replaced due to structural redefinition or some other process.
47*795d594fSAndroid Build Coastguard Worker // In general these don't need to be used. It's only when it's important that a reference to a field
48*795d594fSAndroid Build Coastguard Worker // not become obsolete and it needs to be held over a suspend point that this should be used. This
49*795d594fSAndroid Build Coastguard Worker // takes care of the book-keeping to allow the runtime to visit and update ReflectiveHandles when
50*795d594fSAndroid Build Coastguard Worker // structural redefinition occurs.
51*795d594fSAndroid Build Coastguard Worker class BaseReflectiveHandleScope {
52*795d594fSAndroid Build Coastguard Worker  public:
53*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
VisitTargets(Visitor & visitor)54*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE void VisitTargets(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
55*795d594fSAndroid Build Coastguard Worker     FunctionReflectiveValueVisitor v(&visitor);
56*795d594fSAndroid Build Coastguard Worker     VisitTargets(&v);
57*795d594fSAndroid Build Coastguard Worker   }
58*795d594fSAndroid Build Coastguard Worker 
~BaseReflectiveHandleScope()59*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE virtual ~BaseReflectiveHandleScope() {
60*795d594fSAndroid Build Coastguard Worker     DCHECK(link_ == nullptr);
61*795d594fSAndroid Build Coastguard Worker   }
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker   virtual void VisitTargets(ReflectiveValueVisitor* visitor)
64*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) = 0;
65*795d594fSAndroid Build Coastguard Worker 
GetLink()66*795d594fSAndroid Build Coastguard Worker   BaseReflectiveHandleScope* GetLink() {
67*795d594fSAndroid Build Coastguard Worker     return link_;
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
GetThread()70*795d594fSAndroid Build Coastguard Worker   Thread* GetThread() {
71*795d594fSAndroid Build Coastguard Worker     return self_;
72*795d594fSAndroid Build Coastguard Worker   }
73*795d594fSAndroid Build Coastguard Worker 
74*795d594fSAndroid Build Coastguard Worker   void Describe(std::ostream& os) const;
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker  protected:
BaseReflectiveHandleScope()77*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE BaseReflectiveHandleScope() : self_(nullptr), link_(nullptr) {}
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE inline void PushScope(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
80*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE inline void PopScope() REQUIRES_SHARED(Locks::mutator_lock_);
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker   // Thread this node is rooted in.
83*795d594fSAndroid Build Coastguard Worker   Thread* self_;
84*795d594fSAndroid Build Coastguard Worker   // Next node in the handle-scope linked list. Root is held by Thread.
85*795d594fSAndroid Build Coastguard Worker   BaseReflectiveHandleScope* link_;
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker  private:
88*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(BaseReflectiveHandleScope);
89*795d594fSAndroid Build Coastguard Worker };
90*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const BaseReflectiveHandleScope& brhs);
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker template <size_t kNumFields, size_t kNumMethods>
93*795d594fSAndroid Build Coastguard Worker class StackReflectiveHandleScope : public BaseReflectiveHandleScope {
94*795d594fSAndroid Build Coastguard Worker  private:
95*795d594fSAndroid Build Coastguard Worker   static constexpr bool kHasFields = kNumFields > 0;
96*795d594fSAndroid Build Coastguard Worker   static constexpr bool kHasMethods = kNumMethods > 0;
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker  public:
99*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit StackReflectiveHandleScope(Thread* self)
100*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
101*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ~StackReflectiveHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   void VisitTargets(ReflectiveValueVisitor* visitor) override REQUIRES_SHARED(Locks::mutator_lock_);
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker   template <typename T,
106*795d594fSAndroid Build Coastguard Worker             typename = typename std::enable_if_t<(kHasFields && std::is_same_v<T, ArtField>) ||
107*795d594fSAndroid Build Coastguard Worker                                                  (kHasMethods && std::is_same_v<T, ArtMethod>)>>
NewHandle(T * t)108*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE MutableReflectiveHandle<T> NewHandle(T* t) REQUIRES_SHARED(Locks::mutator_lock_) {
109*795d594fSAndroid Build Coastguard Worker     if constexpr (std::is_same_v<T, ArtField>) {
110*795d594fSAndroid Build Coastguard Worker       return NewFieldHandle(t);
111*795d594fSAndroid Build Coastguard Worker     } else {
112*795d594fSAndroid Build Coastguard Worker       static_assert(std::is_same_v<T, ArtMethod>, "Expected ArtField or ArtMethod");
113*795d594fSAndroid Build Coastguard Worker       return NewMethodHandle(t);
114*795d594fSAndroid Build Coastguard Worker     }
115*795d594fSAndroid Build Coastguard Worker   }
116*795d594fSAndroid Build Coastguard Worker   template<typename T>
NewReflectiveHandleWrapper(T ** t)117*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ReflectiveHandleWrapper<T> NewReflectiveHandleWrapper(T** t)
118*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
119*795d594fSAndroid Build Coastguard Worker     return ReflectiveHandleWrapper<T>(t, NewHandle(*t));
120*795d594fSAndroid Build Coastguard Worker   }
121*795d594fSAndroid Build Coastguard Worker 
NewFieldHandle(ArtField * f)122*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE MutableReflectiveHandle<ArtField> NewFieldHandle(ArtField* f)
123*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
124*795d594fSAndroid Build Coastguard Worker     static_assert(kHasFields, "No fields");
125*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(field_pos_, kNumFields);
126*795d594fSAndroid Build Coastguard Worker     MutableReflectiveHandle<ArtField> fh(GetMutableFieldHandle(field_pos_++));
127*795d594fSAndroid Build Coastguard Worker     fh.Assign(f);
128*795d594fSAndroid Build Coastguard Worker     return fh;
129*795d594fSAndroid Build Coastguard Worker   }
NewReflectiveFieldHandleWrapper(ArtField ** f)130*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ReflectiveHandleWrapper<ArtField> NewReflectiveFieldHandleWrapper(ArtField** f)
131*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
132*795d594fSAndroid Build Coastguard Worker     return ReflectiveHandleWrapper<ArtField>(f, NewMethodHandle(*f));
133*795d594fSAndroid Build Coastguard Worker   }
134*795d594fSAndroid Build Coastguard Worker 
GetField(size_t i)135*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ArtField* GetField(size_t i) {
136*795d594fSAndroid Build Coastguard Worker     static_assert(kHasFields, "No fields");
137*795d594fSAndroid Build Coastguard Worker     return GetFieldReference(i)->Ptr();
138*795d594fSAndroid Build Coastguard Worker   }
GetFieldHandle(size_t i)139*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ReflectiveHandle<ArtField> GetFieldHandle(size_t i) {
140*795d594fSAndroid Build Coastguard Worker     static_assert(kHasFields, "No fields");
141*795d594fSAndroid Build Coastguard Worker     return ReflectiveHandle<ArtField>(GetFieldReference(i));
142*795d594fSAndroid Build Coastguard Worker   }
GetMutableFieldHandle(size_t i)143*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE MutableReflectiveHandle<ArtField> GetMutableFieldHandle(size_t i) {
144*795d594fSAndroid Build Coastguard Worker     static_assert(kHasFields, "No fields");
145*795d594fSAndroid Build Coastguard Worker     return MutableReflectiveHandle<ArtField>(GetFieldReference(i));
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker 
NewMethodHandle(ArtMethod * m)148*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> NewMethodHandle(ArtMethod* m)
149*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
150*795d594fSAndroid Build Coastguard Worker     static_assert(kHasMethods, "No methods");
151*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(method_pos_, kNumMethods);
152*795d594fSAndroid Build Coastguard Worker     MutableReflectiveHandle<ArtMethod> mh(GetMutableMethodHandle(method_pos_++));
153*795d594fSAndroid Build Coastguard Worker     mh.Assign(m);
154*795d594fSAndroid Build Coastguard Worker     return mh;
155*795d594fSAndroid Build Coastguard Worker   }
NewReflectiveMethodHandleWrapper(ArtMethod ** m)156*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ReflectiveHandleWrapper<ArtMethod> NewReflectiveMethodHandleWrapper(ArtMethod** m)
157*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
158*795d594fSAndroid Build Coastguard Worker     return ReflectiveHandleWrapper<ArtMethod>(m, NewMethodHandle(*m));
159*795d594fSAndroid Build Coastguard Worker   }
160*795d594fSAndroid Build Coastguard Worker 
GetMethod(size_t i)161*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ArtMethod* GetMethod(size_t i) {
162*795d594fSAndroid Build Coastguard Worker     static_assert(kHasMethods, "No methods");
163*795d594fSAndroid Build Coastguard Worker     return GetMethodReference(i)->Ptr();
164*795d594fSAndroid Build Coastguard Worker   }
GetMethodHandle(size_t i)165*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ReflectiveHandle<ArtMethod> GetMethodHandle(size_t i) {
166*795d594fSAndroid Build Coastguard Worker     static_assert(kHasMethods, "No methods");
167*795d594fSAndroid Build Coastguard Worker     return ReflectiveHandle<ArtMethod>(GetMethodReference(i));
168*795d594fSAndroid Build Coastguard Worker   }
GetMutableMethodHandle(size_t i)169*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> GetMutableMethodHandle(size_t i) {
170*795d594fSAndroid Build Coastguard Worker     static_assert(kHasMethods, "No methods");
171*795d594fSAndroid Build Coastguard Worker     return MutableReflectiveHandle<ArtMethod>(GetMethodReference(i));
172*795d594fSAndroid Build Coastguard Worker   }
173*795d594fSAndroid Build Coastguard Worker 
RemainingFieldSlots()174*795d594fSAndroid Build Coastguard Worker   size_t RemainingFieldSlots() const {
175*795d594fSAndroid Build Coastguard Worker     return kNumFields - field_pos_;
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker 
RemainingMethodSlots()178*795d594fSAndroid Build Coastguard Worker   size_t RemainingMethodSlots() const {
179*795d594fSAndroid Build Coastguard Worker     return kNumMethods - method_pos_;
180*795d594fSAndroid Build Coastguard Worker   }
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker  private:
GetMethodReference(size_t i)183*795d594fSAndroid Build Coastguard Worker   ReflectiveReference<ArtMethod>* GetMethodReference(size_t i) {
184*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(i, method_pos_);
185*795d594fSAndroid Build Coastguard Worker     return &methods_[i];
186*795d594fSAndroid Build Coastguard Worker   }
187*795d594fSAndroid Build Coastguard Worker 
GetFieldReference(size_t i)188*795d594fSAndroid Build Coastguard Worker   ReflectiveReference<ArtField>* GetFieldReference(size_t i) {
189*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(i, field_pos_);
190*795d594fSAndroid Build Coastguard Worker     return &fields_[i];
191*795d594fSAndroid Build Coastguard Worker   }
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker   size_t field_pos_;
194*795d594fSAndroid Build Coastguard Worker   size_t method_pos_;
195*795d594fSAndroid Build Coastguard Worker   std::array<ReflectiveReference<ArtField>, kNumFields> fields_;
196*795d594fSAndroid Build Coastguard Worker   std::array<ReflectiveReference<ArtMethod>, kNumMethods> methods_;
197*795d594fSAndroid Build Coastguard Worker };
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker template <size_t kNumMethods>
200*795d594fSAndroid Build Coastguard Worker using StackArtMethodHandleScope = StackReflectiveHandleScope</*kNumFields=*/0, kNumMethods>;
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker template <size_t kNumFields>
203*795d594fSAndroid Build Coastguard Worker using StackArtFieldHandleScope = StackReflectiveHandleScope<kNumFields, /*kNumMethods=*/0>;
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker }  // namespace art
206*795d594fSAndroid Build Coastguard Worker 
207*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_
208