Alex Light | 55eccdf | 2019-10-07 13:51:13 +0000 | [diff] [blame] | 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> |
| 54 | ALWAYS_INLINE void VisitTargets(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) { |
| 55 | FunctionReflectiveValueVisitor v(&visitor); |
| 56 | VisitTargets(&v); |
| 57 | } |
| 58 | |
| 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 | |
| 66 | BaseReflectiveHandleScope* GetLink() { |
| 67 | return link_; |
| 68 | } |
| 69 | |
| 70 | Thread* GetThread() { |
| 71 | return self_; |
| 72 | } |
| 73 | |
| 74 | void Describe(std::ostream& os) const; |
| 75 | |
| 76 | protected: |
| 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>)>> |
| 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> |
| 117 | ALWAYS_INLINE ReflectiveHandleWrapper<T> NewReflectiveHandleWrapper(T** t) |
| 118 | REQUIRES_SHARED(art::Locks::mutator_lock_) { |
| 119 | return ReflectiveHandleWrapper<T>(t, NewHandle(*t)); |
| 120 | } |
| 121 | |
| 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 | } |
| 130 | ALWAYS_INLINE ReflectiveHandleWrapper<ArtField> NewReflectiveFieldHandleWrapper(ArtField** f) |
| 131 | REQUIRES_SHARED(art::Locks::mutator_lock_) { |
| 132 | return ReflectiveHandleWrapper<ArtField>(f, NewMethodHandle(*f)); |
| 133 | } |
| 134 | |
| 135 | ALWAYS_INLINE ArtField* GetField(size_t i) { |
| 136 | static_assert(kHasFields, "No fields"); |
| 137 | return GetFieldReference(i)->Ptr(); |
| 138 | } |
| 139 | ALWAYS_INLINE ReflectiveHandle<ArtField> GetFieldHandle(size_t i) { |
| 140 | static_assert(kHasFields, "No fields"); |
| 141 | return ReflectiveHandle<ArtField>(GetFieldReference(i)); |
| 142 | } |
| 143 | ALWAYS_INLINE MutableReflectiveHandle<ArtField> GetMutableFieldHandle(size_t i) { |
| 144 | static_assert(kHasFields, "No fields"); |
| 145 | return MutableReflectiveHandle<ArtField>(GetFieldReference(i)); |
| 146 | } |
| 147 | |
| 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 | } |
| 156 | ALWAYS_INLINE ReflectiveHandleWrapper<ArtMethod> NewReflectiveMethodHandleWrapper(ArtMethod** m) |
| 157 | REQUIRES_SHARED(art::Locks::mutator_lock_) { |
| 158 | return ReflectiveHandleWrapper<ArtMethod>(m, NewMethodHandle(*m)); |
| 159 | } |
| 160 | |
| 161 | ALWAYS_INLINE ArtMethod* GetMethod(size_t i) { |
| 162 | static_assert(kHasMethods, "No methods"); |
| 163 | return GetMethodReference(i)->Ptr(); |
| 164 | } |
| 165 | ALWAYS_INLINE ReflectiveHandle<ArtMethod> GetMethodHandle(size_t i) { |
| 166 | static_assert(kHasMethods, "No methods"); |
| 167 | return ReflectiveHandle<ArtMethod>(GetMethodReference(i)); |
| 168 | } |
| 169 | ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> GetMutableMethodHandle(size_t i) { |
| 170 | static_assert(kHasMethods, "No methods"); |
| 171 | return MutableReflectiveHandle<ArtMethod>(GetMethodReference(i)); |
| 172 | } |
| 173 | |
| 174 | size_t RemainingFieldSlots() const { |
| 175 | return kNumFields - field_pos_; |
| 176 | } |
| 177 | |
| 178 | size_t RemainingMethodSlots() const { |
| 179 | return kNumMethods - method_pos_; |
| 180 | } |
| 181 | |
| 182 | private: |
| 183 | ReflectiveReference<ArtMethod>* GetMethodReference(size_t i) { |
| 184 | DCHECK_LT(i, method_pos_); |
| 185 | return &methods_[i]; |
| 186 | } |
| 187 | |
| 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_ |