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