blob: 46cff8bce714c7138a464253a604f0cdc11ebe57 [file] [log] [blame]
Alex Light55eccdf2019-10-07 13:51:13 +00001/*
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
37namespace art {
38
39class ArtField;
40class ArtMethod;
41class BaseReflectiveHandleScope;
42class 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.
51class 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};
90std::ostream& operator<<(std::ostream& os, const BaseReflectiveHandleScope& brhs);
91
92template <size_t kNumFields, size_t kNumMethods>
93class 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
199template <size_t kNumMethods>
200using StackArtMethodHandleScope = StackReflectiveHandleScope</*kNumFields=*/0, kNumMethods>;
201
202template <size_t kNumFields>
203using StackArtFieldHandleScope = StackReflectiveHandleScope<kNumFields, /*kNumMethods=*/0>;
204
205} // namespace art
206
207#endif // ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_