blob: a46b466bb99065f3f58b0852f0d89249211284b4 [file] [log] [blame]
Orion Hodson005ac512017-10-24 15:43:43 +01001/*
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"
Orion Hodson928033d2018-02-07 05:30:54 +000021#include "interpreter/shadow_frame.h"
Orion Hodson928033d2018-02-07 05:30:54 +000022#include "jvalue.h"
Orion Hodson005ac512017-10-24 15:43:43 +010023#include "object.h"
24
25namespace art {
26
27template<class T> class Handle;
Orion Hodson928033d2018-02-07 05:30:54 +000028class InstructionOperands;
Vladimir Markoa8bba7d2018-05-30 15:18:48 +010029template<class T> class ObjPtr;
Orion Hodson928033d2018-02-07 05:30:54 +000030
Orion Hodsonb8b93872018-01-30 07:51:10 +000031enum class Intrinsics;
32
Orion Hodson005ac512017-10-24 15:43:43 +010033struct VarHandleOffsets;
34struct FieldVarHandleOffsets;
Orion Hodsonffad6682018-01-02 10:18:58 +000035struct ArrayElementVarHandleOffsets;
Orion Hodson005ac512017-10-24 15:43:43 +010036struct ByteArrayViewVarHandleOffsets;
37struct ByteBufferViewVarHandleOffsets;
38
Orion Hodson928033d2018-02-07 05:30:54 +000039class ShadowFrameGetter;
40
Orion Hodson005ac512017-10-24 15:43:43 +010041namespace mirror {
42
43class MethodType;
44class VarHandleTest;
45
46// C++ mirror of java.lang.invoke.VarHandle
47class 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
Orion Hodson928033d2018-02-07 05:30:54 +000055 // The maximum number of VarType parameters a VarHandle accessor
56 // method can take.
57 static constexpr size_t kMaxVarTypeParameters = 2;
58
Orion Hodson005ac512017-10-24 15:43:43 +010059 // 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,
Orion Hodsonfe92d122018-01-02 10:45:17 +000093 kLast = kGetAndBitwiseXorAcquire,
Orion Hodson005ac512017-10-24 15:43:43 +010094 };
Orion Hodsonfe92d122018-01-02 10:45:17 +000095 constexpr static size_t kNumberOfAccessModes = static_cast<size_t>(AccessMode::kLast) + 1u;
Orion Hodson005ac512017-10-24 15:43:43 +010096
97 // Returns true if the AccessMode specified is a supported operation.
98 bool IsAccessModeSupported(AccessMode accessMode) REQUIRES_SHARED(Locks::mutator_lock_) {
99 return (GetAccessModesBitMask() & (1u << static_cast<uint32_t>(accessMode))) != 0;
100 }
101
Orion Hodsonc4d5c132018-05-15 13:57:58 +0100102 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'.
Vladimir Marko5aead702019-03-27 11:00:36 +0000110 MatchKind GetMethodTypeMatchForAccessMode(AccessMode access_mode, ObjPtr<MethodType> method_type)
Orion Hodsonc4d5c132018-05-15 13:57:58 +0100111 REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodson005ac512017-10-24 15:43:43 +0100112
Orion Hodsonb8b93872018-01-30 07:51:10 +0000113 // 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.
Vladimir Marko5aead702019-03-27 11:00:36 +0000117 bool IsInvokerMethodTypeCompatible(AccessMode access_mode, ObjPtr<MethodType> method_type)
Orion Hodsonb8b93872018-01-30 07:51:10 +0000118 REQUIRES_SHARED(Locks::mutator_lock_);
119
Orion Hodson005ac512017-10-24 15:43:43 +0100120 // 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.
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100124 ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode)
Orion Hodson928033d2018-02-07 05:30:54 +0000125 REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodson005ac512017-10-24 15:43:43 +0100126
Orion Hodson3f383462018-05-17 14:03:39 +0100127 // 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
Orion Hodson928033d2018-02-07 05:30:54 +0000132 bool Access(AccessMode access_mode,
133 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +0100134 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +0000135 JValue* result)
136 REQUIRES_SHARED(Locks::mutator_lock_);
137
138 // Gets the variable type that is operated on by this VarHandle instance.
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100139 ObjPtr<Class> GetVarType() REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodson005ac512017-10-24 15:43:43 +0100140
Orion Hodsonfe92d122018-01-02 10:45:17 +0000141 // 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
Orion Hodsonb8b93872018-01-30 07:51:10 +0000145 // Returns the AccessMode corresponding to a VarHandle accessor intrinsic.
146 static AccessMode GetAccessModeByIntrinsic(Intrinsics ordinal);
147
Orion Hodsonfe92d122018-01-02 10:45:17 +0000148 // 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
Orion Hodson005ac512017-10-24 15:43:43 +0100152 private:
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100153 ObjPtr<Class> GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
154 ObjPtr<Class> GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodson005ac512017-10-24 15:43:43 +0100155 int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_);
156
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100157 static ObjPtr<MethodType> GetMethodTypeForAccessMode(Thread* self,
158 ObjPtr<VarHandle> var_handle,
159 AccessMode access_mode)
Orion Hodson005ac512017-10-24 15:43:43 +0100160 REQUIRES_SHARED(Locks::mutator_lock_);
161
162 static MemberOffset VarTypeOffset() {
163 return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_));
164 }
165
166 static MemberOffset CoordinateType0Offset() {
167 return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type0_));
168 }
169
170 static MemberOffset CoordinateType1Offset() {
171 return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type1_));
172 }
173
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
Orion Hodson005ac512017-10-24 15:43:43 +0100183 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.
190class MANAGED FieldVarHandle : public VarHandle {
191 public:
Orion Hodson928033d2018-02-07 05:30:54 +0000192 bool Access(AccessMode access_mode,
193 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +0100194 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +0000195 JValue* result)
196 REQUIRES_SHARED(Locks::mutator_lock_);
197
Orion Hodson005ac512017-10-24 15:43:43 +0100198 ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_);
199
Orion Hodson005ac512017-10-24 15:43:43 +0100200 private:
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
Orion Hodson005ac512017-10-24 15:43:43 +0100208 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.
215class MANAGED ArrayElementVarHandle : public VarHandle {
216 public:
Orion Hodson928033d2018-02-07 05:30:54 +0000217 bool Access(AccessMode access_mode,
218 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +0100219 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +0000220 JValue* result)
221 REQUIRES_SHARED(Locks::mutator_lock_);
222
Orion Hodson005ac512017-10-24 15:43:43 +0100223 private:
Orion Hodson005ac512017-10-24 15:43:43 +0100224 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.
230class MANAGED ByteArrayViewVarHandle : public VarHandle {
231 public:
Orion Hodson928033d2018-02-07 05:30:54 +0000232 bool Access(AccessMode access_mode,
233 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +0100234 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +0000235 JValue* result)
236 REQUIRES_SHARED(Locks::mutator_lock_);
237
Orion Hodson005ac512017-10-24 15:43:43 +0100238 bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
239
Orion Hodson005ac512017-10-24 15:43:43 +0100240 private:
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
Orion Hodson005ac512017-10-24 15:43:43 +0100248 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.
255class MANAGED ByteBufferViewVarHandle : public VarHandle {
256 public:
Orion Hodson928033d2018-02-07 05:30:54 +0000257 bool Access(AccessMode access_mode,
258 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +0100259 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +0000260 JValue* result)
261 REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodson005ac512017-10-24 15:43:43 +0100262
Orion Hodson928033d2018-02-07 05:30:54 +0000263 bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
Orion Hodsonc4d3bf42018-02-06 16:02:49 +0000264
Orion Hodson005ac512017-10-24 15:43:43 +0100265 private:
Orion Hodson928033d2018-02-07 05:30:54 +0000266 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
Orion Hodson005ac512017-10-24 15:43:43 +0100281 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
Orion Hodson005ac512017-10-24 15:43:43 +0100288 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_