• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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_MIRROR_VAR_HANDLE_H_
18 #define ART_RUNTIME_MIRROR_VAR_HANDLE_H_
19 
20 #include "handle.h"
21 #include "interpreter/shadow_frame.h"
22 #include "gc_root.h"
23 #include "jvalue.h"
24 #include "object.h"
25 
26 namespace art {
27 
28 template<class T> class Handle;
29 class InstructionOperands;
30 
31 enum class Intrinsics;
32 
33 struct VarHandleOffsets;
34 struct FieldVarHandleOffsets;
35 struct ArrayElementVarHandleOffsets;
36 struct ByteArrayViewVarHandleOffsets;
37 struct ByteBufferViewVarHandleOffsets;
38 
39 class ShadowFrameGetter;
40 
41 namespace mirror {
42 
43 class MethodType;
44 class VarHandleTest;
45 
46 // C++ mirror of java.lang.invoke.VarHandle
47 class MANAGED VarHandle : public Object {
48  public:
49   // The maximum number of parameters a VarHandle accessor method can
50   // take. The Worst case is equivalent to a compare-and-swap
51   // operation on an array element which requires four parameters
52   // (array, index, old, new).
53   static constexpr int kMaxAccessorParameters = 4;
54 
55   // The maximum number of VarType parameters a VarHandle accessor
56   // method can take.
57   static constexpr size_t kMaxVarTypeParameters = 2;
58 
59   // Enumeration of the possible access modes. This mirrors the enum
60   // in java.lang.invoke.VarHandle.
61   enum class AccessMode : uint32_t {
62     kGet,
63     kSet,
64     kGetVolatile,
65     kSetVolatile,
66     kGetAcquire,
67     kSetRelease,
68     kGetOpaque,
69     kSetOpaque,
70     kCompareAndSet,
71     kCompareAndExchange,
72     kCompareAndExchangeAcquire,
73     kCompareAndExchangeRelease,
74     kWeakCompareAndSetPlain,
75     kWeakCompareAndSet,
76     kWeakCompareAndSetAcquire,
77     kWeakCompareAndSetRelease,
78     kGetAndSet,
79     kGetAndSetAcquire,
80     kGetAndSetRelease,
81     kGetAndAdd,
82     kGetAndAddAcquire,
83     kGetAndAddRelease,
84     kGetAndBitwiseOr,
85     kGetAndBitwiseOrRelease,
86     kGetAndBitwiseOrAcquire,
87     kGetAndBitwiseAnd,
88     kGetAndBitwiseAndRelease,
89     kGetAndBitwiseAndAcquire,
90     kGetAndBitwiseXor,
91     kGetAndBitwiseXorRelease,
92     kGetAndBitwiseXorAcquire,
93     kLast = kGetAndBitwiseXorAcquire,
94   };
95   constexpr static size_t kNumberOfAccessModes = static_cast<size_t>(AccessMode::kLast) + 1u;
96 
97   // Returns true if the AccessMode specified is a supported operation.
IsAccessModeSupported(AccessMode accessMode)98   bool IsAccessModeSupported(AccessMode accessMode) REQUIRES_SHARED(Locks::mutator_lock_) {
99     return (GetAccessModesBitMask() & (1u << static_cast<uint32_t>(accessMode))) != 0;
100   }
101 
102   // Returns true if the MethodType specified is compatible with the
103   // method type associated with the specified AccessMode. The
104   // supplied MethodType is assumed to be from the point of invocation
105   // so it is valid for the supplied MethodType to have a void return
106   // value when the return value for the AccessMode is non-void. This
107   // corresponds to the result of the accessor being discarded.
108   bool IsMethodTypeCompatible(AccessMode access_mode, MethodType* method_type)
109       REQUIRES_SHARED(Locks::mutator_lock_);
110 
111   // Returns true if the MethodType specified is compatible with the
112   // specified access_mode if the first parameter of method_type is
113   // ignored. This is useful for comparing MethodType instances when
114   // invoking a VarHandleAccessor via a MethodHandle invoker.
115   bool IsInvokerMethodTypeCompatible(AccessMode access_mode, MethodType* method_type)
116       REQUIRES_SHARED(Locks::mutator_lock_);
117 
118   // Allocates and returns the MethodType associated with the
119   // AccessMode. No check is made for whether the AccessMode is a
120   // supported operation so the MethodType can be used when raising a
121   // WrongMethodTypeException exception.
122   MethodType* GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
123       REQUIRES_SHARED(Locks::mutator_lock_);
124 
125   bool Access(AccessMode access_mode,
126               ShadowFrame* shadow_frame,
127               InstructionOperands* operands,
128               JValue* result)
129       REQUIRES_SHARED(Locks::mutator_lock_);
130 
131   // Gets the variable type that is operated on by this VarHandle instance.
132   Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
133 
134   // Gets the return type descriptor for a named accessor method,
135   // nullptr if accessor_method is not supported.
136   static const char* GetReturnTypeDescriptor(const char* accessor_method);
137 
138   // Returns the AccessMode corresponding to a VarHandle accessor intrinsic.
139   static AccessMode GetAccessModeByIntrinsic(Intrinsics ordinal);
140 
141   // Returns true and sets access_mode if method_name corresponds to a
142   // VarHandle access method, such as "setOpaque". Returns false otherwise.
143   static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);
144 
145   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
146   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
147   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
148   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
149 
150  private:
151   Class* GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
152   Class* GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
153   int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
154 
155   static MethodType* GetMethodTypeForAccessMode(Thread* self,
156                                                 ObjPtr<VarHandle> var_handle,
157                                                 AccessMode access_mode)
158       REQUIRES_SHARED(Locks::mutator_lock_);
159 
VarTypeOffset()160   static MemberOffset VarTypeOffset() {
161     return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_));
162   }
163 
CoordinateType0Offset()164   static MemberOffset CoordinateType0Offset() {
165     return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type0_));
166   }
167 
CoordinateType1Offset()168   static MemberOffset CoordinateType1Offset() {
169     return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type1_));
170   }
171 
AccessModesBitMaskOffset()172   static MemberOffset AccessModesBitMaskOffset() {
173     return MemberOffset(OFFSETOF_MEMBER(VarHandle, access_modes_bit_mask_));
174   }
175 
176   HeapReference<mirror::Class> coordinate_type0_;
177   HeapReference<mirror::Class> coordinate_type1_;
178   HeapReference<mirror::Class> var_type_;
179   int32_t access_modes_bit_mask_;
180 
181   // Root representing java.lang.invoke.VarHandle.class.
182   static GcRoot<mirror::Class> static_class_;
183 
184   friend class VarHandleTest;  // for testing purposes
185   friend struct art::VarHandleOffsets;  // for verifying offset information
186   DISALLOW_IMPLICIT_CONSTRUCTORS(VarHandle);
187 };
188 
189 // Represents a VarHandle to a static or instance field.
190 // The corresponding managed class in libart java.lang.invoke.FieldVarHandle.
191 class MANAGED FieldVarHandle : public VarHandle {
192  public:
193   bool Access(AccessMode access_mode,
194               ShadowFrame* shadow_frame,
195               InstructionOperands* operands,
196               JValue* result)
197       REQUIRES_SHARED(Locks::mutator_lock_);
198 
199   ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_);
200 
201   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
202   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
203   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
204   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
205 
206  private:
ArtFieldOffset()207   static MemberOffset ArtFieldOffset() {
208     return MemberOffset(OFFSETOF_MEMBER(FieldVarHandle, art_field_));
209   }
210 
211   // ArtField instance corresponding to variable for accessors.
212   int64_t art_field_;
213 
214   // Root representing java.lang.invoke.FieldVarHandle.class.
215   static GcRoot<mirror::Class> static_class_;
216 
217   friend class VarHandleTest;  // for var_handle_test.
218   friend struct art::FieldVarHandleOffsets;  // for verifying offset information
219   DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle);
220 };
221 
222 // Represents a VarHandle providing accessors to an array.
223 // The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle.
224 class MANAGED ArrayElementVarHandle : public VarHandle {
225  public:
226     bool Access(AccessMode access_mode,
227                 ShadowFrame* shadow_frame,
228                 InstructionOperands* operands,
229                 JValue* result)
230       REQUIRES_SHARED(Locks::mutator_lock_);
231 
232   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
233   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
234   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
235   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
236 
237  private:
238   // Root representing java.lang.invoke.ArrayElementVarHandle.class.
239   static GcRoot<mirror::Class> static_class_;
240 
241   friend class VarHandleTest;
242   DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayElementVarHandle);
243 };
244 
245 // Represents a VarHandle providing accessors to a view of a ByteArray.
246 // The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle.
247 class MANAGED ByteArrayViewVarHandle : public VarHandle {
248  public:
249   bool Access(AccessMode access_mode,
250               ShadowFrame* shadow_frame,
251               InstructionOperands* operands,
252               JValue* result)
253       REQUIRES_SHARED(Locks::mutator_lock_);
254 
255   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
256 
257   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
258   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
259   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
260   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
261 
262  private:
NativeByteOrderOffset()263   static MemberOffset NativeByteOrderOffset() {
264     return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_));
265   }
266 
267   // Flag indicating that accessors should use native byte-ordering.
268   uint8_t native_byte_order_;
269 
270   // Root representing java.lang.invoke.ByteArrayViewVarHandle.class.
271   static GcRoot<mirror::Class> static_class_;
272 
273   friend class VarHandleTest;  // for var_handle_test.
274   friend struct art::ByteArrayViewVarHandleOffsets;  // for verifying offset information
275   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayViewVarHandle);
276 };
277 
278 // Represents a VarHandle providing accessors to a view of a ByteBuffer
279 // The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle.
280 class MANAGED ByteBufferViewVarHandle : public VarHandle {
281  public:
282   bool Access(AccessMode access_mode,
283               ShadowFrame* shadow_frame,
284               InstructionOperands* operands,
285               JValue* result)
286       REQUIRES_SHARED(Locks::mutator_lock_);
287 
288   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
289 
290   static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
291   static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
292   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
293   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
294 
295  private:
296   bool AccessHeapBuffer(AccessMode access_mode,
297                         ObjPtr<Object> byte_buffer,
298                         int buffer_offset,
299                         ObjPtr<ByteArray> heap_byte_array,
300                         ShadowFrameGetter* getter,
301                         JValue* result)
302       REQUIRES_SHARED(Locks::mutator_lock_);
303 
304   bool AccessFixedMemory(AccessMode access_mode,
305                          ObjPtr<Object> byte_buffer,
306                          int buffer_offset,
307                          ShadowFrameGetter* getter,
308                          JValue* result)
309       REQUIRES_SHARED(Locks::mutator_lock_);
310 
NativeByteOrderOffset()311   static MemberOffset NativeByteOrderOffset() {
312     return MemberOffset(OFFSETOF_MEMBER(ByteBufferViewVarHandle, native_byte_order_));
313   }
314 
315   // Flag indicating that accessors should use native byte-ordering.
316   uint8_t native_byte_order_;
317 
318   // Root representing java.lang.invoke.ByteBufferViewVarHandle.class.
319   static GcRoot<mirror::Class> static_class_;
320 
321   friend class VarHandleTest;  // for var_handle_test.
322   friend struct art::ByteBufferViewVarHandleOffsets;  // for verifying offset information
323   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteBufferViewVarHandle);
324 };
325 
326 }  // namespace mirror
327 }  // namespace art
328 
329 #endif  // ART_RUNTIME_MIRROR_VAR_HANDLE_H_
330