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