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 "gc_root.h" 23 #include "jvalue.h" 24 #include "object.h" 25 26 namespace art { 27 28 template<class T> class Handle; 29 class InstructionOperands; 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 // Returns true if the MethodType specified is compatible with the 103 // method type associated with the specified AccessMode. The 104 // supplied MethodType is assumed to be from the point of invocation 105 // so it is valid for the supplied MethodType to have a void return 106 // value when the return value for the AccessMode is non-void. This 107 // corresponds to the result of the accessor being discarded. 108 bool IsMethodTypeCompatible(AccessMode access_mode, MethodType* method_type) 109 REQUIRES_SHARED(Locks::mutator_lock_); 110 111 // Returns true if the MethodType specified is compatible with the 112 // specified access_mode if the first parameter of method_type is 113 // ignored. This is useful for comparing MethodType instances when 114 // invoking a VarHandleAccessor via a MethodHandle invoker. 115 bool IsInvokerMethodTypeCompatible(AccessMode access_mode, MethodType* method_type) 116 REQUIRES_SHARED(Locks::mutator_lock_); 117 118 // Allocates and returns the MethodType associated with the 119 // AccessMode. No check is made for whether the AccessMode is a 120 // supported operation so the MethodType can be used when raising a 121 // WrongMethodTypeException exception. 122 MethodType* GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode) 123 REQUIRES_SHARED(Locks::mutator_lock_); 124 125 bool Access(AccessMode access_mode, 126 ShadowFrame* shadow_frame, 127 InstructionOperands* operands, 128 JValue* result) 129 REQUIRES_SHARED(Locks::mutator_lock_); 130 131 // Gets the variable type that is operated on by this VarHandle instance. 132 Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_); 133 134 // Gets the return type descriptor for a named accessor method, 135 // nullptr if accessor_method is not supported. 136 static const char* GetReturnTypeDescriptor(const char* accessor_method); 137 138 // Returns the AccessMode corresponding to a VarHandle accessor intrinsic. 139 static AccessMode GetAccessModeByIntrinsic(Intrinsics ordinal); 140 141 // Returns true and sets access_mode if method_name corresponds to a 142 // VarHandle access method, such as "setOpaque". Returns false otherwise. 143 static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode); 144 145 static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); 146 static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); 147 static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); 148 static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 149 150 private: 151 Class* GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_); 152 Class* GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_); 153 int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_); 154 155 static MethodType* GetMethodTypeForAccessMode(Thread* self, 156 ObjPtr<VarHandle> var_handle, 157 AccessMode access_mode) 158 REQUIRES_SHARED(Locks::mutator_lock_); 159 VarTypeOffset()160 static MemberOffset VarTypeOffset() { 161 return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_)); 162 } 163 CoordinateType0Offset()164 static MemberOffset CoordinateType0Offset() { 165 return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type0_)); 166 } 167 CoordinateType1Offset()168 static MemberOffset CoordinateType1Offset() { 169 return MemberOffset(OFFSETOF_MEMBER(VarHandle, coordinate_type1_)); 170 } 171 AccessModesBitMaskOffset()172 static MemberOffset AccessModesBitMaskOffset() { 173 return MemberOffset(OFFSETOF_MEMBER(VarHandle, access_modes_bit_mask_)); 174 } 175 176 HeapReference<mirror::Class> coordinate_type0_; 177 HeapReference<mirror::Class> coordinate_type1_; 178 HeapReference<mirror::Class> var_type_; 179 int32_t access_modes_bit_mask_; 180 181 // Root representing java.lang.invoke.VarHandle.class. 182 static GcRoot<mirror::Class> static_class_; 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 InstructionOperands* operands, 196 JValue* result) 197 REQUIRES_SHARED(Locks::mutator_lock_); 198 199 ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_); 200 201 static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); 202 static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); 203 static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); 204 static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 205 206 private: ArtFieldOffset()207 static MemberOffset ArtFieldOffset() { 208 return MemberOffset(OFFSETOF_MEMBER(FieldVarHandle, art_field_)); 209 } 210 211 // ArtField instance corresponding to variable for accessors. 212 int64_t art_field_; 213 214 // Root representing java.lang.invoke.FieldVarHandle.class. 215 static GcRoot<mirror::Class> static_class_; 216 217 friend class VarHandleTest; // for var_handle_test. 218 friend struct art::FieldVarHandleOffsets; // for verifying offset information 219 DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle); 220 }; 221 222 // Represents a VarHandle providing accessors to an array. 223 // The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle. 224 class MANAGED ArrayElementVarHandle : public VarHandle { 225 public: 226 bool Access(AccessMode access_mode, 227 ShadowFrame* shadow_frame, 228 InstructionOperands* operands, 229 JValue* result) 230 REQUIRES_SHARED(Locks::mutator_lock_); 231 232 static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); 233 static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); 234 static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); 235 static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 236 237 private: 238 // Root representing java.lang.invoke.ArrayElementVarHandle.class. 239 static GcRoot<mirror::Class> static_class_; 240 241 friend class VarHandleTest; 242 DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayElementVarHandle); 243 }; 244 245 // Represents a VarHandle providing accessors to a view of a ByteArray. 246 // The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle. 247 class MANAGED ByteArrayViewVarHandle : public VarHandle { 248 public: 249 bool Access(AccessMode access_mode, 250 ShadowFrame* shadow_frame, 251 InstructionOperands* operands, 252 JValue* result) 253 REQUIRES_SHARED(Locks::mutator_lock_); 254 255 bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_); 256 257 static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); 258 static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); 259 static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); 260 static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 261 262 private: NativeByteOrderOffset()263 static MemberOffset NativeByteOrderOffset() { 264 return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_)); 265 } 266 267 // Flag indicating that accessors should use native byte-ordering. 268 uint8_t native_byte_order_; 269 270 // Root representing java.lang.invoke.ByteArrayViewVarHandle.class. 271 static GcRoot<mirror::Class> static_class_; 272 273 friend class VarHandleTest; // for var_handle_test. 274 friend struct art::ByteArrayViewVarHandleOffsets; // for verifying offset information 275 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayViewVarHandle); 276 }; 277 278 // Represents a VarHandle providing accessors to a view of a ByteBuffer 279 // The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle. 280 class MANAGED ByteBufferViewVarHandle : public VarHandle { 281 public: 282 bool Access(AccessMode access_mode, 283 ShadowFrame* shadow_frame, 284 InstructionOperands* operands, 285 JValue* result) 286 REQUIRES_SHARED(Locks::mutator_lock_); 287 288 bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_); 289 290 static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); 291 static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); 292 static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); 293 static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 294 295 private: 296 bool AccessHeapBuffer(AccessMode access_mode, 297 ObjPtr<Object> byte_buffer, 298 int buffer_offset, 299 ObjPtr<ByteArray> heap_byte_array, 300 ShadowFrameGetter* getter, 301 JValue* result) 302 REQUIRES_SHARED(Locks::mutator_lock_); 303 304 bool AccessFixedMemory(AccessMode access_mode, 305 ObjPtr<Object> byte_buffer, 306 int buffer_offset, 307 ShadowFrameGetter* getter, 308 JValue* result) 309 REQUIRES_SHARED(Locks::mutator_lock_); 310 NativeByteOrderOffset()311 static MemberOffset NativeByteOrderOffset() { 312 return MemberOffset(OFFSETOF_MEMBER(ByteBufferViewVarHandle, native_byte_order_)); 313 } 314 315 // Flag indicating that accessors should use native byte-ordering. 316 uint8_t native_byte_order_; 317 318 // Root representing java.lang.invoke.ByteBufferViewVarHandle.class. 319 static GcRoot<mirror::Class> static_class_; 320 321 friend class VarHandleTest; // for var_handle_test. 322 friend struct art::ByteBufferViewVarHandleOffsets; // for verifying offset information 323 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteBufferViewVarHandle); 324 }; 325 326 } // namespace mirror 327 } // namespace art 328 329 #endif // ART_RUNTIME_MIRROR_VAR_HANDLE_H_ 330