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