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