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