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