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