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