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