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