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 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   enum MatchKind : uint8_t {
103     kNone,
104     kWithConversions,
105     kExact
106   };
107 
108   // Returns match information on the compatability between the exact method type for
109   // 'access_mode' and the provided 'method_type'.
110   MatchKind GetMethodTypeMatchForAccessMode(AccessMode access_mode, ObjPtr<MethodType> method_type)
111         REQUIRES_SHARED(Locks::mutator_lock_);
112 
113   // Returns true if the MethodType specified is compatible with the
114   // specified access_mode if the first parameter of method_type is
115   // ignored. This is useful for comparing MethodType instances when
116   // invoking a VarHandleAccessor via a MethodHandle invoker.
117   bool IsInvokerMethodTypeCompatible(AccessMode access_mode, ObjPtr<MethodType> method_type)
118       REQUIRES_SHARED(Locks::mutator_lock_);
119 
120   // Allocates and returns the MethodType associated with the
121   // AccessMode. No check is made for whether the AccessMode is a
122   // supported operation so the MethodType can be used when raising a
123   // WrongMethodTypeException exception.
124   ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
125       REQUIRES_SHARED(Locks::mutator_lock_);
126 
127   // Returns a string representing the descriptor of the MethodType associated with
128   // this AccessMode.
129   std::string PrettyDescriptorForAccessMode(AccessMode access_mode)
130       REQUIRES_SHARED(Locks::mutator_lock_);
131 
132   bool Access(AccessMode access_mode,
133               ShadowFrame* shadow_frame,
134               const InstructionOperands* const operands,
135               JValue* result)
136       REQUIRES_SHARED(Locks::mutator_lock_);
137 
138   // Gets the variable type that is operated on by this VarHandle instance.
139   ObjPtr<Class> GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
140 
141   // Gets the return type descriptor for a named accessor method,
142   // nullptr if accessor_method is not supported.
143   static const char* GetReturnTypeDescriptor(const char* accessor_method);
144 
145   // Returns the AccessMode corresponding to a VarHandle accessor intrinsic.
146   static AccessMode GetAccessModeByIntrinsic(Intrinsics ordinal);
147 
148   // Returns true and sets access_mode if method_name corresponds to a
149   // VarHandle access method, such as "setOpaque". Returns false otherwise.
150   static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);
151 
152  private:
153   ObjPtr<Class> GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
154   ObjPtr<Class> GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
155   int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
156 
157   static ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self,
158                                                        ObjPtr<VarHandle> var_handle,
159                                                        AccessMode access_mode)
160       REQUIRES_SHARED(Locks::mutator_lock_);
161 
VarTypeOffset()162   static MemberOffset VarTypeOffset() {
163     return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_));
164   }
165 
CoordinateType0Offset()166   static MemberOffset CoordinateType0Offset() {
167     return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type0_));
168   }
169 
CoordinateType1Offset()170   static MemberOffset CoordinateType1Offset() {
171     return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type1_));
172   }
173 
AccessModesBitMaskOffset()174   static MemberOffset AccessModesBitMaskOffset() {
175     return MemberOffset(OFFSETOF_MEMBER(VarHandle, access_modes_bit_mask_));
176   }
177 
178   HeapReference<mirror::Class> coordinate_type0_;
179   HeapReference<mirror::Class> coordinate_type1_;
180   HeapReference<mirror::Class> var_type_;
181   int32_t access_modes_bit_mask_;
182 
183   friend class VarHandleTest;  // for testing purposes
184   friend struct art::VarHandleOffsets;  // for verifying offset information
185   DISALLOW_IMPLICIT_CONSTRUCTORS(VarHandle);
186 };
187 
188 // Represents a VarHandle to a static or instance field.
189 // The corresponding managed class in libart java.lang.invoke.FieldVarHandle.
190 class MANAGED FieldVarHandle : public VarHandle {
191  public:
192   bool Access(AccessMode access_mode,
193               ShadowFrame* shadow_frame,
194               const InstructionOperands* const operands,
195               JValue* result)
196       REQUIRES_SHARED(Locks::mutator_lock_);
197 
198   ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_);
199 
200  private:
ArtFieldOffset()201   static MemberOffset ArtFieldOffset() {
202     return MemberOffset(OFFSETOF_MEMBER(FieldVarHandle, art_field_));
203   }
204 
205   // ArtField instance corresponding to variable for accessors.
206   int64_t art_field_;
207 
208   friend class VarHandleTest;  // for var_handle_test.
209   friend struct art::FieldVarHandleOffsets;  // for verifying offset information
210   DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle);
211 };
212 
213 // Represents a VarHandle providing accessors to an array.
214 // The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle.
215 class MANAGED ArrayElementVarHandle : public VarHandle {
216  public:
217     bool Access(AccessMode access_mode,
218                 ShadowFrame* shadow_frame,
219                 const InstructionOperands* const operands,
220                 JValue* result)
221       REQUIRES_SHARED(Locks::mutator_lock_);
222 
223  private:
224   friend class VarHandleTest;
225   DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayElementVarHandle);
226 };
227 
228 // Represents a VarHandle providing accessors to a view of a ByteArray.
229 // The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle.
230 class MANAGED ByteArrayViewVarHandle : public VarHandle {
231  public:
232   bool Access(AccessMode access_mode,
233               ShadowFrame* shadow_frame,
234               const InstructionOperands* const operands,
235               JValue* result)
236       REQUIRES_SHARED(Locks::mutator_lock_);
237 
238   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
239 
240  private:
NativeByteOrderOffset()241   static MemberOffset NativeByteOrderOffset() {
242     return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_));
243   }
244 
245   // Flag indicating that accessors should use native byte-ordering.
246   uint8_t native_byte_order_;
247 
248   friend class VarHandleTest;  // for var_handle_test.
249   friend struct art::ByteArrayViewVarHandleOffsets;  // for verifying offset information
250   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayViewVarHandle);
251 };
252 
253 // Represents a VarHandle providing accessors to a view of a ByteBuffer
254 // The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle.
255 class MANAGED ByteBufferViewVarHandle : public VarHandle {
256  public:
257   bool Access(AccessMode access_mode,
258               ShadowFrame* shadow_frame,
259               const InstructionOperands* const operands,
260               JValue* result)
261       REQUIRES_SHARED(Locks::mutator_lock_);
262 
263   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
264 
265  private:
266   bool AccessHeapBuffer(AccessMode access_mode,
267                         ObjPtr<Object> byte_buffer,
268                         int buffer_offset,
269                         ObjPtr<ByteArray> heap_byte_array,
270                         ShadowFrameGetter* getter,
271                         JValue* result)
272       REQUIRES_SHARED(Locks::mutator_lock_);
273 
274   bool AccessFixedMemory(AccessMode access_mode,
275                          ObjPtr<Object> byte_buffer,
276                          int buffer_offset,
277                          ShadowFrameGetter* getter,
278                          JValue* result)
279       REQUIRES_SHARED(Locks::mutator_lock_);
280 
NativeByteOrderOffset()281   static MemberOffset NativeByteOrderOffset() {
282     return MemberOffset(OFFSETOF_MEMBER(ByteBufferViewVarHandle, native_byte_order_));
283   }
284 
285   // Flag indicating that accessors should use native byte-ordering.
286   uint8_t native_byte_order_;
287 
288   friend class VarHandleTest;  // for var_handle_test.
289   friend struct art::ByteBufferViewVarHandleOffsets;  // for verifying offset information
290   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteBufferViewVarHandle);
291 };
292 
293 }  // namespace mirror
294 }  // namespace art
295 
296 #endif  // ART_RUNTIME_MIRROR_VAR_HANDLE_H_
297