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