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 #include "var_handle.h" 18 19 #include "array-inl.h" 20 #include "art_field-inl.h" 21 #include "base/casts.h" 22 #include "class-inl.h" 23 #include "class_linker.h" 24 #include "class_root.h" 25 #include "intrinsics_enum.h" 26 #include "jni/jni_internal.h" 27 #include "jvalue-inl.h" 28 #include "method_handles-inl.h" 29 #include "method_type-inl.h" 30 #include "object_array-alloc-inl.h" 31 #include "obj_ptr-inl.h" 32 #include "well_known_classes.h" 33 34 namespace art { 35 namespace mirror { 36 37 static constexpr bool kTransactionActive = true; 38 static constexpr bool kTransactionInactive = !kTransactionActive; 39 40 namespace { 41 42 struct VarHandleAccessorToAccessModeEntry { 43 const char* method_name; 44 VarHandle::AccessMode access_mode; 45 46 // Binary predicate function for finding access_mode by 47 // method_name. The access_mode field is ignored. 48 static bool CompareName(const VarHandleAccessorToAccessModeEntry& lhs, 49 const VarHandleAccessorToAccessModeEntry& rhs) { 50 return strcmp(lhs.method_name, rhs.method_name) < 0; 51 } 52 }; 53 54 // Map of VarHandle accessor method names to access mode values. The list is alpha-sorted to support 55 // binary search. For the usage scenario - lookups in the verifier - a linear scan would likely 56 // suffice since we expect VarHandles to be a lesser encountered class. We could use a std::hashmap 57 // here and this would be easier to maintain if new values are added here. However, this entails 58 // CPU cycles initializing the structure on every execution and uses O(N) more memory for 59 // intermediate nodes and makes that memory dirty. Compile-time magic using constexpr is possible 60 // here, but that's a tax when this code is recompiled. 61 const VarHandleAccessorToAccessModeEntry kAccessorToAccessMode[VarHandle::kNumberOfAccessModes] = { 62 { "compareAndExchange", VarHandle::AccessMode::kCompareAndExchange }, 63 { "compareAndExchangeAcquire", VarHandle::AccessMode::kCompareAndExchangeAcquire }, 64 { "compareAndExchangeRelease", VarHandle::AccessMode::kCompareAndExchangeRelease }, 65 { "compareAndSet", VarHandle::AccessMode::kCompareAndSet }, 66 { "get", VarHandle::AccessMode::kGet }, 67 { "getAcquire", VarHandle::AccessMode::kGetAcquire }, 68 { "getAndAdd", VarHandle::AccessMode::kGetAndAdd }, 69 { "getAndAddAcquire", VarHandle::AccessMode::kGetAndAddAcquire }, 70 { "getAndAddRelease", VarHandle::AccessMode::kGetAndAddRelease }, 71 { "getAndBitwiseAnd", VarHandle::AccessMode::kGetAndBitwiseAnd }, 72 { "getAndBitwiseAndAcquire", VarHandle::AccessMode::kGetAndBitwiseAndAcquire }, 73 { "getAndBitwiseAndRelease", VarHandle::AccessMode::kGetAndBitwiseAndRelease }, 74 { "getAndBitwiseOr", VarHandle::AccessMode::kGetAndBitwiseOr }, 75 { "getAndBitwiseOrAcquire", VarHandle::AccessMode::kGetAndBitwiseOrAcquire }, 76 { "getAndBitwiseOrRelease", VarHandle::AccessMode::kGetAndBitwiseOrRelease }, 77 { "getAndBitwiseXor", VarHandle::AccessMode::kGetAndBitwiseXor }, 78 { "getAndBitwiseXorAcquire", VarHandle::AccessMode::kGetAndBitwiseXorAcquire }, 79 { "getAndBitwiseXorRelease", VarHandle::AccessMode::kGetAndBitwiseXorRelease }, 80 { "getAndSet", VarHandle::AccessMode::kGetAndSet }, 81 { "getAndSetAcquire", VarHandle::AccessMode::kGetAndSetAcquire }, 82 { "getAndSetRelease", VarHandle::AccessMode::kGetAndSetRelease }, 83 { "getOpaque", VarHandle::AccessMode::kGetOpaque }, 84 { "getVolatile", VarHandle::AccessMode::kGetVolatile }, 85 { "set", VarHandle::AccessMode::kSet }, 86 { "setOpaque", VarHandle::AccessMode::kSetOpaque }, 87 { "setRelease", VarHandle::AccessMode::kSetRelease }, 88 { "setVolatile", VarHandle::AccessMode::kSetVolatile }, 89 { "weakCompareAndSet", VarHandle::AccessMode::kWeakCompareAndSet }, 90 { "weakCompareAndSetAcquire", VarHandle::AccessMode::kWeakCompareAndSetAcquire }, 91 { "weakCompareAndSetPlain", VarHandle::AccessMode::kWeakCompareAndSetPlain }, 92 { "weakCompareAndSetRelease", VarHandle::AccessMode::kWeakCompareAndSetRelease }, 93 }; 94 95 // Enumeration for describing the parameter and return types of an AccessMode. 96 enum class AccessModeTemplate : uint32_t { 97 kGet, // T Op(C0..CN) 98 kSet, // void Op(C0..CN, T) 99 kCompareAndSet, // boolean Op(C0..CN, T, T) 100 kCompareAndExchange, // T Op(C0..CN, T, T) 101 kGetAndUpdate, // T Op(C0..CN, T) 102 }; 103 104 // Look up the AccessModeTemplate for a given VarHandle 105 // AccessMode. This simplifies finding the correct signature for a 106 // VarHandle accessor method. 107 AccessModeTemplate GetAccessModeTemplate(VarHandle::AccessMode access_mode) { 108 switch (access_mode) { 109 case VarHandle::AccessMode::kGet: 110 return AccessModeTemplate::kGet; 111 case VarHandle::AccessMode::kSet: 112 return AccessModeTemplate::kSet; 113 case VarHandle::AccessMode::kGetVolatile: 114 return AccessModeTemplate::kGet; 115 case VarHandle::AccessMode::kSetVolatile: 116 return AccessModeTemplate::kSet; 117 case VarHandle::AccessMode::kGetAcquire: 118 return AccessModeTemplate::kGet; 119 case VarHandle::AccessMode::kSetRelease: 120 return AccessModeTemplate::kSet; 121 case VarHandle::AccessMode::kGetOpaque: 122 return AccessModeTemplate::kGet; 123 case VarHandle::AccessMode::kSetOpaque: 124 return AccessModeTemplate::kSet; 125 case VarHandle::AccessMode::kCompareAndSet: 126 return AccessModeTemplate::kCompareAndSet; 127 case VarHandle::AccessMode::kCompareAndExchange: 128 return AccessModeTemplate::kCompareAndExchange; 129 case VarHandle::AccessMode::kCompareAndExchangeAcquire: 130 return AccessModeTemplate::kCompareAndExchange; 131 case VarHandle::AccessMode::kCompareAndExchangeRelease: 132 return AccessModeTemplate::kCompareAndExchange; 133 case VarHandle::AccessMode::kWeakCompareAndSetPlain: 134 return AccessModeTemplate::kCompareAndSet; 135 case VarHandle::AccessMode::kWeakCompareAndSet: 136 return AccessModeTemplate::kCompareAndSet; 137 case VarHandle::AccessMode::kWeakCompareAndSetAcquire: 138 return AccessModeTemplate::kCompareAndSet; 139 case VarHandle::AccessMode::kWeakCompareAndSetRelease: 140 return AccessModeTemplate::kCompareAndSet; 141 case VarHandle::AccessMode::kGetAndSet: 142 return AccessModeTemplate::kGetAndUpdate; 143 case VarHandle::AccessMode::kGetAndSetAcquire: 144 return AccessModeTemplate::kGetAndUpdate; 145 case VarHandle::AccessMode::kGetAndSetRelease: 146 return AccessModeTemplate::kGetAndUpdate; 147 case VarHandle::AccessMode::kGetAndAdd: 148 return AccessModeTemplate::kGetAndUpdate; 149 case VarHandle::AccessMode::kGetAndAddAcquire: 150 return AccessModeTemplate::kGetAndUpdate; 151 case VarHandle::AccessMode::kGetAndAddRelease: 152 return AccessModeTemplate::kGetAndUpdate; 153 case VarHandle::AccessMode::kGetAndBitwiseOr: 154 return AccessModeTemplate::kGetAndUpdate; 155 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: 156 return AccessModeTemplate::kGetAndUpdate; 157 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: 158 return AccessModeTemplate::kGetAndUpdate; 159 case VarHandle::AccessMode::kGetAndBitwiseAnd: 160 return AccessModeTemplate::kGetAndUpdate; 161 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: 162 return AccessModeTemplate::kGetAndUpdate; 163 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: 164 return AccessModeTemplate::kGetAndUpdate; 165 case VarHandle::AccessMode::kGetAndBitwiseXor: 166 return AccessModeTemplate::kGetAndUpdate; 167 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: 168 return AccessModeTemplate::kGetAndUpdate; 169 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: 170 return AccessModeTemplate::kGetAndUpdate; 171 } 172 } 173 174 int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) { 175 switch (access_mode_template) { 176 case AccessModeTemplate::kGet: 177 return 0; 178 case AccessModeTemplate::kSet: 179 case AccessModeTemplate::kGetAndUpdate: 180 return 1; 181 case AccessModeTemplate::kCompareAndSet: 182 case AccessModeTemplate::kCompareAndExchange: 183 return 2; 184 } 185 UNREACHABLE(); 186 } 187 188 // Returns the number of parameters associated with an 189 // AccessModeTemplate and the supplied coordinate types. 190 int32_t GetNumberOfParameters(AccessModeTemplate access_mode_template, 191 ObjPtr<Class> coordinateType0, 192 ObjPtr<Class> coordinateType1) { 193 int32_t count = 0; 194 if (!coordinateType0.IsNull()) { 195 count++; 196 if (!coordinateType1.IsNull()) { 197 count++; 198 } 199 } 200 return count + GetNumberOfVarTypeParameters(access_mode_template); 201 } 202 203 void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) { 204 ThrowNullPointerException("Attempt to access memory on a null object"); 205 } 206 207 bool CheckElementIndex(Primitive::Type type, 208 int32_t relative_index, 209 int32_t start, 210 int32_t limit) REQUIRES_SHARED(Locks::mutator_lock_) { 211 int64_t index = start + relative_index; 212 int64_t max_index = limit - Primitive::ComponentSize(type); 213 if (index < start || index > max_index) { 214 ThrowIndexOutOfBoundsException(index, limit - start); 215 return false; 216 } 217 return true; 218 } 219 220 bool CheckElementIndex(Primitive::Type type, int32_t index, int32_t range_limit) 221 REQUIRES_SHARED(Locks::mutator_lock_) { 222 return CheckElementIndex(type, index, 0, range_limit); 223 } 224 225 // Returns true if access_mode only entails a memory read. False if 226 // access_mode may write to memory. 227 bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) { 228 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); 229 return access_mode_template == AccessModeTemplate::kGet; 230 } 231 232 // Writes the parameter types associated with the AccessModeTemplate 233 // into an array. The parameter types are derived from the specified 234 // variable type and coordinate types. Returns the number of 235 // parameters written. 236 int32_t BuildParameterArray(ObjPtr<Class> (¶meters)[VarHandle::kMaxAccessorParameters], 237 AccessModeTemplate access_mode_template, 238 ObjPtr<Class> varType, 239 ObjPtr<Class> coordinateType0, 240 ObjPtr<Class> coordinateType1) 241 REQUIRES_SHARED(Locks::mutator_lock_) { 242 DCHECK(varType != nullptr); 243 int32_t index = 0; 244 if (!coordinateType0.IsNull()) { 245 parameters[index++] = coordinateType0; 246 if (!coordinateType1.IsNull()) { 247 parameters[index++] = coordinateType1; 248 } 249 } else { 250 DCHECK(coordinateType1.IsNull()); 251 } 252 253 switch (access_mode_template) { 254 case AccessModeTemplate::kCompareAndExchange: 255 case AccessModeTemplate::kCompareAndSet: 256 parameters[index++] = varType; 257 parameters[index++] = varType; 258 return index; 259 case AccessModeTemplate::kGet: 260 return index; 261 case AccessModeTemplate::kGetAndUpdate: 262 case AccessModeTemplate::kSet: 263 parameters[index++] = varType; 264 return index; 265 } 266 return -1; 267 } 268 269 // Returns the return type associated with an AccessModeTemplate based 270 // on the template and the variable type specified. 271 static ObjPtr<Class> GetReturnType(AccessModeTemplate access_mode_template, ObjPtr<Class> varType) 272 REQUIRES_SHARED(Locks::mutator_lock_) { 273 DCHECK(varType != nullptr); 274 switch (access_mode_template) { 275 case AccessModeTemplate::kCompareAndSet: 276 return GetClassRoot(ClassRoot::kPrimitiveBoolean); 277 case AccessModeTemplate::kCompareAndExchange: 278 case AccessModeTemplate::kGet: 279 case AccessModeTemplate::kGetAndUpdate: 280 return varType; 281 case AccessModeTemplate::kSet: 282 return GetClassRoot(ClassRoot::kPrimitiveVoid); 283 } 284 return nullptr; 285 } 286 287 // Method to insert a read barrier for accessors to reference fields. 288 inline void ReadBarrierForVarHandleAccess(ObjPtr<Object> obj, MemberOffset field_offset) 289 REQUIRES_SHARED(Locks::mutator_lock_) { 290 if (kUseReadBarrier) { 291 // We need to ensure that the reference stored in the field is a to-space one before attempting 292 // the CompareAndSet/CompareAndExchange/Exchange operation otherwise it will fail incorrectly 293 // if obj is in the process of being moved. 294 uint8_t* raw_field_addr = reinterpret_cast<uint8_t*>(obj.Ptr()) + field_offset.SizeValue(); 295 auto field_addr = reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_field_addr); 296 // Note that the read barrier load does NOT need to be volatile. 297 static constexpr bool kIsVolatile = false; 298 static constexpr bool kAlwaysUpdateField = true; 299 ReadBarrier::Barrier<mirror::Object, kIsVolatile, kWithReadBarrier, kAlwaysUpdateField>( 300 obj.Ptr(), 301 MemberOffset(field_offset), 302 field_addr); 303 } 304 } 305 306 inline MemberOffset GetMemberOffset(jfieldID field_id) REQUIRES_SHARED(Locks::mutator_lock_) { 307 ArtField* const field = jni::DecodeArtField(field_id); 308 return field->GetOffset(); 309 } 310 311 // 312 // Helper methods for storing results from atomic operations into 313 // JValue instances. 314 // 315 316 inline void StoreResult(uint8_t value, JValue* result) { 317 result->SetZ(value); 318 } 319 320 inline void StoreResult(int8_t value, JValue* result) { 321 result->SetB(value); 322 } 323 324 inline void StoreResult(uint16_t value, JValue* result) { 325 result->SetC(value); 326 } 327 328 inline void StoreResult(int16_t value, JValue* result) { 329 result->SetS(value); 330 } 331 332 inline void StoreResult(int32_t value, JValue* result) { 333 result->SetI(value); 334 } 335 336 inline void StoreResult(int64_t value, JValue* result) { 337 result->SetJ(value); 338 } 339 340 inline void StoreResult(float value, JValue* result) { 341 result->SetF(value); 342 } 343 344 inline void StoreResult(double value, JValue* result) { 345 result->SetD(value); 346 } 347 348 inline void StoreResult(ObjPtr<Object> value, JValue* result) 349 REQUIRES_SHARED(Locks::mutator_lock_) { 350 result->SetL(value); 351 } 352 353 // 354 // Helper class for byte-swapping value that has been stored in a JValue. 355 // 356 357 template <typename T> 358 class JValueByteSwapper final { 359 public: 360 static void ByteSwap(JValue* value); 361 static void MaybeByteSwap(bool byte_swap, JValue* value) { 362 if (byte_swap) { 363 ByteSwap(value); 364 } 365 } 366 }; 367 368 template <> 369 void JValueByteSwapper<uint16_t>::ByteSwap(JValue* value) { 370 value->SetC(BSWAP(value->GetC())); 371 } 372 373 template <> 374 void JValueByteSwapper<int16_t>::ByteSwap(JValue* value) { 375 value->SetS(BSWAP(value->GetS())); 376 } 377 378 template <> 379 void JValueByteSwapper<int32_t>::ByteSwap(JValue* value) { 380 value->SetI(BSWAP(value->GetI())); 381 } 382 383 template <> 384 void JValueByteSwapper<int64_t>::ByteSwap(JValue* value) { 385 value->SetJ(BSWAP(value->GetJ())); 386 } 387 388 // 389 // Accessor implementations, shared across all VarHandle types. 390 // 391 392 template <typename T, std::memory_order MO> 393 class AtomicGetAccessor : public Object::Accessor<T> { 394 public: 395 explicit AtomicGetAccessor(JValue* result) : result_(result) {} 396 397 void Access(T* addr) override { 398 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 399 StoreResult(atom->load(MO), result_); 400 } 401 402 private: 403 JValue* result_; 404 }; 405 406 template <typename T, std::memory_order MO> 407 class AtomicSetAccessor : public Object::Accessor<T> { 408 public: 409 explicit AtomicSetAccessor(T new_value) : new_value_(new_value) {} 410 411 void Access(T* addr) override { 412 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 413 atom->store(new_value_, MO); 414 } 415 416 private: 417 T new_value_; 418 }; 419 420 template <typename T> using GetAccessor = AtomicGetAccessor<T, std::memory_order_relaxed>; 421 422 template <typename T> using SetAccessor = AtomicSetAccessor<T, std::memory_order_relaxed>; 423 424 template <typename T> 425 using GetVolatileAccessor = AtomicGetAccessor<T, std::memory_order_seq_cst>; 426 427 template <typename T> 428 using SetVolatileAccessor = AtomicSetAccessor<T, std::memory_order_seq_cst>; 429 430 template <typename T, std::memory_order MOS, std::memory_order MOF> 431 class AtomicStrongCompareAndSetAccessor : public Object::Accessor<T> { 432 public: 433 AtomicStrongCompareAndSetAccessor(T expected_value, T desired_value, JValue* result) 434 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {} 435 436 void Access(T* addr) override { 437 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 438 bool success = atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF); 439 StoreResult(success ? JNI_TRUE : JNI_FALSE, result_); 440 } 441 442 private: 443 T expected_value_; 444 T desired_value_; 445 JValue* result_; 446 }; 447 448 template<typename T> 449 using CompareAndSetAccessor = 450 AtomicStrongCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>; 451 452 template <typename T, std::memory_order MOS, std::memory_order MOF> 453 class AtomicStrongCompareAndExchangeAccessor : public Object::Accessor<T> { 454 public: 455 AtomicStrongCompareAndExchangeAccessor(T expected_value, T desired_value, JValue* result) 456 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {} 457 458 void Access(T* addr) override { 459 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 460 atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF); 461 StoreResult(expected_value_, result_); 462 } 463 464 private: 465 T expected_value_; 466 T desired_value_; 467 JValue* result_; 468 }; 469 470 template <typename T> 471 using CompareAndExchangeAccessor = 472 AtomicStrongCompareAndExchangeAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>; 473 474 template <typename T, std::memory_order MOS, std::memory_order MOF> 475 class AtomicWeakCompareAndSetAccessor : public Object::Accessor<T> { 476 public: 477 AtomicWeakCompareAndSetAccessor(T expected_value, T desired_value, JValue* result) 478 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {} 479 480 void Access(T* addr) override { 481 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 482 bool success = atom->compare_exchange_weak(expected_value_, desired_value_, MOS, MOF); 483 StoreResult(success ? JNI_TRUE : JNI_FALSE, result_); 484 } 485 486 private: 487 T expected_value_; 488 T desired_value_; 489 JValue* result_; 490 }; 491 492 template <typename T> 493 using WeakCompareAndSetAccessor = 494 AtomicWeakCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>; 495 496 template <typename T, std::memory_order MO> 497 class AtomicGetAndSetAccessor : public Object::Accessor<T> { 498 public: 499 AtomicGetAndSetAccessor(T new_value, JValue* result) : new_value_(new_value), result_(result) {} 500 501 void Access(T* addr) override { 502 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 503 T old_value = atom->exchange(new_value_, MO); 504 StoreResult(old_value, result_); 505 } 506 507 private: 508 T new_value_; 509 JValue* result_; 510 }; 511 512 template <typename T> 513 using GetAndSetAccessor = AtomicGetAndSetAccessor<T, std::memory_order_seq_cst>; 514 515 template <typename T, bool kIsFloat, std::memory_order MO> 516 class AtomicGetAndAddOperator { 517 public: 518 static T Apply(T* addr, T addend) { 519 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 520 return atom->fetch_add(addend, MO); 521 } 522 }; 523 524 template <typename T, std::memory_order MO> 525 class AtomicGetAndAddOperator<T, /* kIsFloat */ true, MO> { 526 public: 527 static T Apply(T* addr, T addend) { 528 // c++11 does not have std::atomic<T>::fetch_and_add for floating 529 // point types, so we effect one with a compare and swap. 530 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 531 T old_value = atom->load(std::memory_order_relaxed); 532 T new_value; 533 do { 534 new_value = old_value + addend; 535 } while (!atom->compare_exchange_weak(old_value, new_value, MO, std::memory_order_relaxed)); 536 return old_value; 537 } 538 }; 539 540 template <typename T, std::memory_order MO> 541 class AtomicGetAndAddAccessor : public Object::Accessor<T> { 542 public: 543 AtomicGetAndAddAccessor(T addend, JValue* result) : addend_(addend), result_(result) {} 544 545 void Access(T* addr) override { 546 constexpr bool kIsFloatingPoint = std::is_floating_point<T>::value; 547 T old_value = AtomicGetAndAddOperator<T, kIsFloatingPoint, MO>::Apply(addr, addend_); 548 StoreResult(old_value, result_); 549 } 550 551 private: 552 T addend_; 553 JValue* result_; 554 }; 555 556 template <typename T> 557 using GetAndAddAccessor = AtomicGetAndAddAccessor<T, std::memory_order_seq_cst>; 558 559 // Accessor specifically for memory views where the caller can specify 560 // the byte-ordering. Addition only works outside of the byte-swapped 561 // memory view because of the direction of carries. 562 template <typename T, std::memory_order MO> 563 class AtomicGetAndAddWithByteSwapAccessor : public Object::Accessor<T> { 564 public: 565 AtomicGetAndAddWithByteSwapAccessor(T value, JValue* result) : value_(value), result_(result) {} 566 567 void Access(T* addr) override { 568 std::atomic<T>* const atom = reinterpret_cast<std::atomic<T>*>(addr); 569 T current_value = atom->load(std::memory_order_relaxed); 570 T sum; 571 do { 572 sum = BSWAP(current_value) + value_; 573 // NB current_value is a pass-by-reference argument in the call to 574 // atomic<T>::compare_exchange_weak(). 575 } while (!atom->compare_exchange_weak(current_value, 576 BSWAP(sum), 577 MO, 578 std::memory_order_relaxed)); 579 StoreResult(BSWAP(current_value), result_); 580 } 581 582 private: 583 T value_; 584 JValue* result_; 585 }; 586 587 template <typename T> 588 using GetAndAddWithByteSwapAccessor = 589 AtomicGetAndAddWithByteSwapAccessor<T, std::memory_order_seq_cst>; 590 591 template <typename T, std::memory_order MO> 592 class AtomicGetAndBitwiseOrAccessor : public Object::Accessor<T> { 593 public: 594 AtomicGetAndBitwiseOrAccessor(T value, JValue* result) : value_(value), result_(result) {} 595 596 void Access(T* addr) override { 597 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 598 T old_value = atom->fetch_or(value_, MO); 599 StoreResult(old_value, result_); 600 } 601 602 private: 603 T value_; 604 JValue* result_; 605 }; 606 607 template <typename T> 608 using GetAndBitwiseOrAccessor = AtomicGetAndBitwiseOrAccessor<T, std::memory_order_seq_cst>; 609 610 template <typename T, std::memory_order MO> 611 class AtomicGetAndBitwiseAndAccessor : public Object::Accessor<T> { 612 public: 613 AtomicGetAndBitwiseAndAccessor(T value, JValue* result) : value_(value), result_(result) {} 614 615 void Access(T* addr) override { 616 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 617 T old_value = atom->fetch_and(value_, MO); 618 StoreResult(old_value, result_); 619 } 620 621 private: 622 T value_; 623 JValue* result_; 624 }; 625 626 template <typename T> 627 using GetAndBitwiseAndAccessor = 628 AtomicGetAndBitwiseAndAccessor<T, std::memory_order_seq_cst>; 629 630 template <typename T, std::memory_order MO> 631 class AtomicGetAndBitwiseXorAccessor : public Object::Accessor<T> { 632 public: 633 AtomicGetAndBitwiseXorAccessor(T value, JValue* result) : value_(value), result_(result) {} 634 635 void Access(T* addr) override { 636 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); 637 T old_value = atom->fetch_xor(value_, MO); 638 StoreResult(old_value, result_); 639 } 640 641 private: 642 T value_; 643 JValue* result_; 644 }; 645 646 template <typename T> 647 using GetAndBitwiseXorAccessor = AtomicGetAndBitwiseXorAccessor<T, std::memory_order_seq_cst>; 648 649 // 650 // Unreachable access modes. 651 // 652 653 NO_RETURN void UnreachableAccessMode(const char* access_mode, const char* type_name) { 654 LOG(FATAL) << "Unreachable access mode :" << access_mode << " for type " << type_name; 655 UNREACHABLE(); 656 } 657 658 #define UNREACHABLE_ACCESS_MODE(ACCESS_MODE, TYPE) \ 659 template<> void ACCESS_MODE ## Accessor<TYPE>::Access(TYPE*) { \ 660 UnreachableAccessMode(#ACCESS_MODE, #TYPE); \ 661 } 662 663 // The boolean primitive type is not numeric (boolean == std::uint8_t). 664 UNREACHABLE_ACCESS_MODE(GetAndAdd, uint8_t) 665 666 // The floating point types do not support bitwise operations. 667 UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, float) 668 UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, float) 669 UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, float) 670 UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, double) 671 UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, double) 672 UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, double) 673 674 // A helper class for object field accesses for floats and 675 // doubles. The object interface deals with Field32 and Field64. The 676 // former is used for both integers and floats, the latter for longs 677 // and doubles. This class provides the necessary coercion. 678 template <typename T, typename U> 679 class TypeAdaptorAccessor : public Object::Accessor<T> { 680 public: 681 explicit TypeAdaptorAccessor(Object::Accessor<U>* inner_accessor) 682 : inner_accessor_(inner_accessor) {} 683 684 void Access(T* addr) override { 685 static_assert(sizeof(T) == sizeof(U), "bad conversion"); 686 inner_accessor_->Access(reinterpret_cast<U*>(addr)); 687 } 688 689 private: 690 Object::Accessor<U>* inner_accessor_; 691 }; 692 693 template <typename T> 694 class FieldAccessViaAccessor { 695 public: 696 using Accessor = Object::Accessor<T>; 697 698 // Apply an Accessor to get a field in an object. 699 static void Get(ObjPtr<Object> obj, 700 MemberOffset field_offset, 701 Accessor* accessor) 702 REQUIRES_SHARED(Locks::mutator_lock_) { 703 obj->GetPrimitiveFieldViaAccessor(field_offset, accessor); 704 } 705 706 // Apply an Accessor to update a field in an object. 707 static void Update(ObjPtr<Object> obj, 708 MemberOffset field_offset, 709 Accessor* accessor) 710 REQUIRES_SHARED(Locks::mutator_lock_); 711 }; 712 713 template <> 714 inline void FieldAccessViaAccessor<float>::Get(ObjPtr<Object> obj, 715 MemberOffset field_offset, 716 Accessor* accessor) 717 REQUIRES_SHARED(Locks::mutator_lock_) { 718 TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor); 719 obj->GetPrimitiveFieldViaAccessor(field_offset, &float_to_int_accessor); 720 } 721 722 template <> 723 inline void FieldAccessViaAccessor<double>::Get(ObjPtr<Object> obj, 724 MemberOffset field_offset, 725 Accessor* accessor) 726 REQUIRES_SHARED(Locks::mutator_lock_) { 727 TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor); 728 obj->GetPrimitiveFieldViaAccessor(field_offset, &double_to_int_accessor); 729 } 730 731 template <> 732 void FieldAccessViaAccessor<uint8_t>::Update(ObjPtr<Object> obj, 733 MemberOffset field_offset, 734 Accessor* accessor) 735 REQUIRES_SHARED(Locks::mutator_lock_) { 736 if (Runtime::Current()->IsActiveTransaction()) { 737 obj->UpdateFieldBooleanViaAccessor<kTransactionActive>(field_offset, accessor); 738 } else { 739 obj->UpdateFieldBooleanViaAccessor<kTransactionInactive>(field_offset, accessor); 740 } 741 } 742 743 template <> 744 void FieldAccessViaAccessor<int8_t>::Update(ObjPtr<Object> obj, 745 MemberOffset field_offset, 746 Accessor* accessor) 747 REQUIRES_SHARED(Locks::mutator_lock_) { 748 if (Runtime::Current()->IsActiveTransaction()) { 749 obj->UpdateFieldByteViaAccessor<kTransactionActive>(field_offset, accessor); 750 } else { 751 obj->UpdateFieldByteViaAccessor<kTransactionInactive>(field_offset, accessor); 752 } 753 } 754 755 template <> 756 void FieldAccessViaAccessor<uint16_t>::Update(ObjPtr<Object> obj, 757 MemberOffset field_offset, 758 Accessor* accessor) 759 REQUIRES_SHARED(Locks::mutator_lock_) { 760 if (Runtime::Current()->IsActiveTransaction()) { 761 obj->UpdateFieldCharViaAccessor<kTransactionActive>(field_offset, accessor); 762 } else { 763 obj->UpdateFieldCharViaAccessor<kTransactionInactive>(field_offset, accessor); 764 } 765 } 766 767 template <> 768 void FieldAccessViaAccessor<int16_t>::Update(ObjPtr<Object> obj, 769 MemberOffset field_offset, 770 Accessor* accessor) 771 REQUIRES_SHARED(Locks::mutator_lock_) { 772 if (Runtime::Current()->IsActiveTransaction()) { 773 obj->UpdateFieldShortViaAccessor<kTransactionActive>(field_offset, accessor); 774 } else { 775 obj->UpdateFieldShortViaAccessor<kTransactionInactive>(field_offset, accessor); 776 } 777 } 778 779 template <> 780 void FieldAccessViaAccessor<int32_t>::Update(ObjPtr<Object> obj, 781 MemberOffset field_offset, 782 Accessor* accessor) 783 REQUIRES_SHARED(Locks::mutator_lock_) { 784 if (Runtime::Current()->IsActiveTransaction()) { 785 obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, accessor); 786 } else { 787 obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, accessor); 788 } 789 } 790 791 template <> 792 void FieldAccessViaAccessor<int64_t>::Update(ObjPtr<Object> obj, 793 MemberOffset field_offset, 794 Accessor* accessor) 795 REQUIRES_SHARED(Locks::mutator_lock_) { 796 if (Runtime::Current()->IsActiveTransaction()) { 797 obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, accessor); 798 } else { 799 obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, accessor); 800 } 801 } 802 803 template <> 804 void FieldAccessViaAccessor<float>::Update(ObjPtr<Object> obj, 805 MemberOffset field_offset, 806 Accessor* accessor) 807 REQUIRES_SHARED(Locks::mutator_lock_) { 808 TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor); 809 if (Runtime::Current()->IsActiveTransaction()) { 810 obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, &float_to_int_accessor); 811 } else { 812 obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, &float_to_int_accessor); 813 } 814 } 815 816 template <> 817 void FieldAccessViaAccessor<double>::Update(ObjPtr<Object> obj, 818 MemberOffset field_offset, 819 Accessor* accessor) 820 REQUIRES_SHARED(Locks::mutator_lock_) { 821 TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor); 822 if (Runtime::Current()->IsActiveTransaction()) { 823 obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, &double_to_int_accessor); 824 } else { 825 obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, &double_to_int_accessor); 826 } 827 } 828 829 // Helper class that gets values from a shadow frame with appropriate type coercion. 830 template <typename T> 831 class ValueGetter { 832 public: 833 static T Get(ShadowFrameGetter* getter) REQUIRES_SHARED(Locks::mutator_lock_) { 834 static_assert(sizeof(T) <= sizeof(uint32_t), "Bad size"); 835 uint32_t raw_value = getter->Get(); 836 return static_cast<T>(raw_value); 837 } 838 }; 839 840 template <> 841 int64_t ValueGetter<int64_t>::Get(ShadowFrameGetter* getter) { 842 return getter->GetLong(); 843 } 844 845 template <> 846 float ValueGetter<float>::Get(ShadowFrameGetter* getter) { 847 uint32_t raw_value = getter->Get(); 848 return *reinterpret_cast<float*>(&raw_value); 849 } 850 851 template <> 852 double ValueGetter<double>::Get(ShadowFrameGetter* getter) { 853 int64_t raw_value = getter->GetLong(); 854 return *reinterpret_cast<double*>(&raw_value); 855 } 856 857 template <> 858 ObjPtr<Object> ValueGetter<ObjPtr<Object>>::Get(ShadowFrameGetter* getter) { 859 return getter->GetReference(); 860 } 861 862 // Class for accessing fields of Object instances 863 template <typename T> 864 class FieldAccessor { 865 public: 866 static bool Dispatch(VarHandle::AccessMode access_mode, 867 ObjPtr<Object> obj, 868 MemberOffset field_offset, 869 ShadowFrameGetter* getter, 870 JValue* result) 871 REQUIRES_SHARED(Locks::mutator_lock_); 872 }; 873 874 // Dispatch implementation for primitive fields. 875 template <typename T> 876 bool FieldAccessor<T>::Dispatch(VarHandle::AccessMode access_mode, 877 ObjPtr<Object> obj, 878 MemberOffset field_offset, 879 ShadowFrameGetter* getter, 880 JValue* result) { 881 switch (access_mode) { 882 case VarHandle::AccessMode::kGet: { 883 GetAccessor<T> accessor(result); 884 FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor); 885 break; 886 } 887 case VarHandle::AccessMode::kSet: { 888 T new_value = ValueGetter<T>::Get(getter); 889 SetAccessor<T> accessor(new_value); 890 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 891 break; 892 } 893 case VarHandle::AccessMode::kGetAcquire: 894 case VarHandle::AccessMode::kGetOpaque: 895 case VarHandle::AccessMode::kGetVolatile: { 896 GetVolatileAccessor<T> accessor(result); 897 FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor); 898 break; 899 } 900 case VarHandle::AccessMode::kSetOpaque: 901 case VarHandle::AccessMode::kSetRelease: 902 case VarHandle::AccessMode::kSetVolatile: { 903 T new_value = ValueGetter<T>::Get(getter); 904 SetVolatileAccessor<T> accessor(new_value); 905 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 906 break; 907 } 908 case VarHandle::AccessMode::kCompareAndSet: { 909 T expected_value = ValueGetter<T>::Get(getter); 910 T desired_value = ValueGetter<T>::Get(getter); 911 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result); 912 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 913 break; 914 } 915 case VarHandle::AccessMode::kCompareAndExchange: 916 case VarHandle::AccessMode::kCompareAndExchangeAcquire: 917 case VarHandle::AccessMode::kCompareAndExchangeRelease: { 918 T expected_value = ValueGetter<T>::Get(getter); 919 T desired_value = ValueGetter<T>::Get(getter); 920 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result); 921 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 922 break; 923 } 924 case VarHandle::AccessMode::kWeakCompareAndSet: 925 case VarHandle::AccessMode::kWeakCompareAndSetAcquire: 926 case VarHandle::AccessMode::kWeakCompareAndSetPlain: 927 case VarHandle::AccessMode::kWeakCompareAndSetRelease: { 928 T expected_value = ValueGetter<T>::Get(getter); 929 T desired_value = ValueGetter<T>::Get(getter); 930 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result); 931 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 932 break; 933 } 934 case VarHandle::AccessMode::kGetAndSet: 935 case VarHandle::AccessMode::kGetAndSetAcquire: 936 case VarHandle::AccessMode::kGetAndSetRelease: { 937 T new_value = ValueGetter<T>::Get(getter); 938 GetAndSetAccessor<T> accessor(new_value, result); 939 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 940 break; 941 } 942 case VarHandle::AccessMode::kGetAndAdd: 943 case VarHandle::AccessMode::kGetAndAddAcquire: 944 case VarHandle::AccessMode::kGetAndAddRelease: { 945 T value = ValueGetter<T>::Get(getter); 946 GetAndAddAccessor<T> accessor(value, result); 947 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 948 break; 949 } 950 case VarHandle::AccessMode::kGetAndBitwiseOr: 951 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: 952 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { 953 T value = ValueGetter<T>::Get(getter); 954 GetAndBitwiseOrAccessor<T> accessor(value, result); 955 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 956 break; 957 } 958 case VarHandle::AccessMode::kGetAndBitwiseAnd: 959 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: 960 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { 961 T value = ValueGetter<T>::Get(getter); 962 GetAndBitwiseAndAccessor<T> accessor(value, result); 963 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 964 break; 965 } 966 case VarHandle::AccessMode::kGetAndBitwiseXor: 967 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: 968 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { 969 T value = ValueGetter<T>::Get(getter); 970 GetAndBitwiseXorAccessor<T> accessor(value, result); 971 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); 972 break; 973 } 974 } 975 return true; 976 } 977 978 // Dispatch implementation for reference fields. 979 template <> 980 bool FieldAccessor<ObjPtr<Object>>::Dispatch(VarHandle::AccessMode access_mode, 981 ObjPtr<Object> obj, 982 MemberOffset field_offset, 983 ShadowFrameGetter* getter, 984 JValue* result) 985 REQUIRES_SHARED(Locks::mutator_lock_) { 986 // To keep things simple, use the minimum strongest existing 987 // field accessor for Object fields. This may be the most 988 // straightforward strategy in general for the interpreter. 989 switch (access_mode) { 990 case VarHandle::AccessMode::kGet: { 991 StoreResult(obj->GetFieldObject<Object>(field_offset), result); 992 break; 993 } 994 case VarHandle::AccessMode::kSet: { 995 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter); 996 if (Runtime::Current()->IsActiveTransaction()) { 997 obj->SetFieldObject<kTransactionActive>(field_offset, new_value); 998 } else { 999 obj->SetFieldObject<kTransactionInactive>(field_offset, new_value); 1000 } 1001 break; 1002 } 1003 case VarHandle::AccessMode::kGetAcquire: 1004 case VarHandle::AccessMode::kGetOpaque: 1005 case VarHandle::AccessMode::kGetVolatile: { 1006 StoreResult(obj->GetFieldObjectVolatile<Object>(field_offset), result); 1007 break; 1008 } 1009 case VarHandle::AccessMode::kSetOpaque: 1010 case VarHandle::AccessMode::kSetRelease: 1011 case VarHandle::AccessMode::kSetVolatile: { 1012 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1013 if (Runtime::Current()->IsActiveTransaction()) { 1014 obj->SetFieldObjectVolatile<kTransactionActive>(field_offset, new_value); 1015 } else { 1016 obj->SetFieldObjectVolatile<kTransactionInactive>(field_offset, new_value); 1017 } 1018 break; 1019 } 1020 case VarHandle::AccessMode::kCompareAndSet: { 1021 ReadBarrierForVarHandleAccess(obj, field_offset); 1022 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1023 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1024 bool cas_result; 1025 if (Runtime::Current()->IsActiveTransaction()) { 1026 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset, 1027 expected_value, 1028 desired_value, 1029 CASMode::kStrong, 1030 std::memory_order_seq_cst); 1031 } else { 1032 cas_result = obj->CasFieldObject<kTransactionInactive>(field_offset, 1033 expected_value, 1034 desired_value, 1035 CASMode::kStrong, 1036 std::memory_order_seq_cst); 1037 } 1038 StoreResult(static_cast<uint8_t>(cas_result), result); 1039 break; 1040 } 1041 case VarHandle::AccessMode::kWeakCompareAndSet: 1042 case VarHandle::AccessMode::kWeakCompareAndSetAcquire: 1043 case VarHandle::AccessMode::kWeakCompareAndSetPlain: 1044 case VarHandle::AccessMode::kWeakCompareAndSetRelease: { 1045 ReadBarrierForVarHandleAccess(obj, field_offset); 1046 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1047 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1048 bool cas_result; 1049 if (Runtime::Current()->IsActiveTransaction()) { 1050 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset, 1051 expected_value, 1052 desired_value, 1053 CASMode::kWeak, 1054 std::memory_order_seq_cst); 1055 } else { 1056 cas_result = obj->CasFieldObject<kTransactionInactive>( 1057 field_offset, 1058 expected_value, 1059 desired_value, 1060 CASMode::kWeak, 1061 std::memory_order_seq_cst); 1062 } 1063 StoreResult(static_cast<uint8_t>(cas_result), result); 1064 break; 1065 } 1066 case VarHandle::AccessMode::kCompareAndExchange: 1067 case VarHandle::AccessMode::kCompareAndExchangeAcquire: 1068 case VarHandle::AccessMode::kCompareAndExchangeRelease: { 1069 ReadBarrierForVarHandleAccess(obj, field_offset); 1070 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1071 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1072 ObjPtr<Object> witness_value; 1073 if (Runtime::Current()->IsActiveTransaction()) { 1074 witness_value = obj->CompareAndExchangeFieldObject<kTransactionActive>(field_offset, 1075 expected_value, 1076 desired_value); 1077 } else { 1078 witness_value = obj->CompareAndExchangeFieldObject<kTransactionInactive>(field_offset, 1079 expected_value, 1080 desired_value); 1081 } 1082 StoreResult(witness_value, result); 1083 break; 1084 } 1085 case VarHandle::AccessMode::kGetAndSet: 1086 case VarHandle::AccessMode::kGetAndSetAcquire: 1087 case VarHandle::AccessMode::kGetAndSetRelease: { 1088 ReadBarrierForVarHandleAccess(obj, field_offset); 1089 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter); 1090 ObjPtr<Object> old_value; 1091 if (Runtime::Current()->IsActiveTransaction()) { 1092 old_value = obj->ExchangeFieldObject<kTransactionActive>(field_offset, new_value); 1093 } else { 1094 old_value = obj->ExchangeFieldObject<kTransactionInactive>(field_offset, new_value); 1095 } 1096 StoreResult(old_value, result); 1097 break; 1098 } 1099 case VarHandle::AccessMode::kGetAndAdd: 1100 case VarHandle::AccessMode::kGetAndAddAcquire: 1101 case VarHandle::AccessMode::kGetAndAddRelease: 1102 case VarHandle::AccessMode::kGetAndBitwiseOr: 1103 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: 1104 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: 1105 case VarHandle::AccessMode::kGetAndBitwiseAnd: 1106 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: 1107 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: 1108 case VarHandle::AccessMode::kGetAndBitwiseXor: 1109 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: 1110 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { 1111 size_t index = static_cast<size_t>(access_mode); 1112 const char* access_mode_name = kAccessorToAccessMode[index].method_name; 1113 UnreachableAccessMode(access_mode_name, "Object"); 1114 } 1115 } 1116 return true; 1117 } 1118 1119 // Class for accessing primitive array elements. 1120 template <typename T> 1121 class PrimitiveArrayElementAccessor { 1122 public: 1123 static T* GetElementAddress(ObjPtr<Array> target_array, int target_element) 1124 REQUIRES_SHARED(Locks::mutator_lock_) { 1125 auto primitive_array = ObjPtr<PrimitiveArray<T>>::DownCast(target_array); 1126 DCHECK(primitive_array->CheckIsValidIndex(target_element)); 1127 return &primitive_array->GetData()[target_element]; 1128 } 1129 1130 static bool Dispatch(VarHandle::AccessMode access_mode, 1131 ObjPtr<Array> target_array, 1132 int target_element, 1133 ShadowFrameGetter* getter, 1134 JValue* result) 1135 REQUIRES_SHARED(Locks::mutator_lock_) { 1136 T* element_address = GetElementAddress(target_array, target_element); 1137 switch (access_mode) { 1138 case VarHandle::AccessMode::kGet: { 1139 GetAccessor<T> accessor(result); 1140 accessor.Access(element_address); 1141 break; 1142 } 1143 case VarHandle::AccessMode::kSet: { 1144 T new_value = ValueGetter<T>::Get(getter); 1145 SetAccessor<T> accessor(new_value); 1146 accessor.Access(element_address); 1147 break; 1148 } 1149 case VarHandle::AccessMode::kGetAcquire: 1150 case VarHandle::AccessMode::kGetOpaque: 1151 case VarHandle::AccessMode::kGetVolatile: { 1152 GetVolatileAccessor<T> accessor(result); 1153 accessor.Access(element_address); 1154 break; 1155 } 1156 case VarHandle::AccessMode::kSetOpaque: 1157 case VarHandle::AccessMode::kSetRelease: 1158 case VarHandle::AccessMode::kSetVolatile: { 1159 T new_value = ValueGetter<T>::Get(getter); 1160 SetVolatileAccessor<T> accessor(new_value); 1161 accessor.Access(element_address); 1162 break; 1163 } 1164 case VarHandle::AccessMode::kCompareAndSet: { 1165 T expected_value = ValueGetter<T>::Get(getter); 1166 T desired_value = ValueGetter<T>::Get(getter); 1167 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result); 1168 accessor.Access(element_address); 1169 break; 1170 } 1171 case VarHandle::AccessMode::kCompareAndExchange: 1172 case VarHandle::AccessMode::kCompareAndExchangeAcquire: 1173 case VarHandle::AccessMode::kCompareAndExchangeRelease: { 1174 T expected_value = ValueGetter<T>::Get(getter); 1175 T desired_value = ValueGetter<T>::Get(getter); 1176 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result); 1177 accessor.Access(element_address); 1178 break; 1179 } 1180 case VarHandle::AccessMode::kWeakCompareAndSet: 1181 case VarHandle::AccessMode::kWeakCompareAndSetAcquire: 1182 case VarHandle::AccessMode::kWeakCompareAndSetPlain: 1183 case VarHandle::AccessMode::kWeakCompareAndSetRelease: { 1184 T expected_value = ValueGetter<T>::Get(getter); 1185 T desired_value = ValueGetter<T>::Get(getter); 1186 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result); 1187 accessor.Access(element_address); 1188 break; 1189 } 1190 case VarHandle::AccessMode::kGetAndSet: 1191 case VarHandle::AccessMode::kGetAndSetAcquire: 1192 case VarHandle::AccessMode::kGetAndSetRelease: { 1193 T new_value = ValueGetter<T>::Get(getter); 1194 GetAndSetAccessor<T> accessor(new_value, result); 1195 accessor.Access(element_address); 1196 break; 1197 } 1198 case VarHandle::AccessMode::kGetAndAdd: 1199 case VarHandle::AccessMode::kGetAndAddAcquire: 1200 case VarHandle::AccessMode::kGetAndAddRelease: { 1201 T value = ValueGetter<T>::Get(getter); 1202 GetAndAddAccessor<T> accessor(value, result); 1203 accessor.Access(element_address); 1204 break; 1205 } 1206 case VarHandle::AccessMode::kGetAndBitwiseOr: 1207 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: 1208 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { 1209 T value = ValueGetter<T>::Get(getter); 1210 GetAndBitwiseOrAccessor<T> accessor(value, result); 1211 accessor.Access(element_address); 1212 break; 1213 } 1214 case VarHandle::AccessMode::kGetAndBitwiseAnd: 1215 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: 1216 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { 1217 T value = ValueGetter<T>::Get(getter); 1218 GetAndBitwiseAndAccessor<T> accessor(value, result); 1219 accessor.Access(element_address); 1220 break; 1221 } 1222 case VarHandle::AccessMode::kGetAndBitwiseXor: 1223 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: 1224 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { 1225 T value = ValueGetter<T>::Get(getter); 1226 GetAndBitwiseXorAccessor<T> accessor(value, result); 1227 accessor.Access(element_address); 1228 break; 1229 } 1230 } 1231 return true; 1232 } 1233 }; 1234 1235 // Class for accessing primitive array elements. 1236 template <typename T> 1237 class ByteArrayViewAccessor { 1238 public: 1239 static inline bool IsAccessAligned(int8_t* data, int data_index) { 1240 static_assert(IsPowerOfTwo(sizeof(T)), "unexpected size"); 1241 static_assert(std::is_arithmetic<T>::value, "unexpected type"); 1242 uintptr_t alignment_mask = sizeof(T) - 1; 1243 uintptr_t address = reinterpret_cast<uintptr_t>(data + data_index); 1244 return (address & alignment_mask) == 0; 1245 } 1246 1247 static inline void MaybeByteSwap(bool byte_swap, T* const value) { 1248 if (byte_swap) { 1249 *value = BSWAP(*value); 1250 } 1251 } 1252 1253 static bool Dispatch(const VarHandle::AccessMode access_mode, 1254 int8_t* const data, 1255 const int data_index, 1256 const bool byte_swap, 1257 ShadowFrameGetter* const getter, 1258 JValue* const result) 1259 REQUIRES_SHARED(Locks::mutator_lock_) { 1260 const bool is_aligned = IsAccessAligned(data, data_index); 1261 if (!is_aligned) { 1262 switch (access_mode) { 1263 case VarHandle::AccessMode::kGet: { 1264 T value; 1265 memcpy(&value, data + data_index, sizeof(T)); 1266 MaybeByteSwap(byte_swap, &value); 1267 StoreResult(value, result); 1268 return true; 1269 } 1270 case VarHandle::AccessMode::kSet: { 1271 T new_value = ValueGetter<T>::Get(getter); 1272 MaybeByteSwap(byte_swap, &new_value); 1273 memcpy(data + data_index, &new_value, sizeof(T)); 1274 return true; 1275 } 1276 default: 1277 // No other access modes support unaligned access. 1278 ThrowIllegalStateException("Unaligned access not supported"); 1279 return false; 1280 } 1281 } 1282 1283 T* const element_address = reinterpret_cast<T*>(data + data_index); 1284 CHECK(IsAccessAligned(reinterpret_cast<int8_t*>(element_address), 0)); 1285 switch (access_mode) { 1286 case VarHandle::AccessMode::kGet: { 1287 GetAccessor<T> accessor(result); 1288 accessor.Access(element_address); 1289 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1290 break; 1291 } 1292 case VarHandle::AccessMode::kSet: { 1293 T new_value = ValueGetter<T>::Get(getter); 1294 MaybeByteSwap(byte_swap, &new_value); 1295 SetAccessor<T> accessor(new_value); 1296 accessor.Access(element_address); 1297 break; 1298 } 1299 case VarHandle::AccessMode::kGetAcquire: 1300 case VarHandle::AccessMode::kGetOpaque: 1301 case VarHandle::AccessMode::kGetVolatile: { 1302 GetVolatileAccessor<T> accessor(result); 1303 accessor.Access(element_address); 1304 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1305 break; 1306 } 1307 case VarHandle::AccessMode::kSetOpaque: 1308 case VarHandle::AccessMode::kSetRelease: 1309 case VarHandle::AccessMode::kSetVolatile: { 1310 T new_value = ValueGetter<T>::Get(getter); 1311 MaybeByteSwap(byte_swap, &new_value); 1312 SetVolatileAccessor<T> accessor(new_value); 1313 accessor.Access(element_address); 1314 break; 1315 } 1316 case VarHandle::AccessMode::kCompareAndSet: { 1317 T expected_value = ValueGetter<T>::Get(getter); 1318 T desired_value = ValueGetter<T>::Get(getter); 1319 MaybeByteSwap(byte_swap, &expected_value); 1320 MaybeByteSwap(byte_swap, &desired_value); 1321 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result); 1322 accessor.Access(element_address); 1323 break; 1324 } 1325 case VarHandle::AccessMode::kCompareAndExchange: 1326 case VarHandle::AccessMode::kCompareAndExchangeAcquire: 1327 case VarHandle::AccessMode::kCompareAndExchangeRelease: { 1328 T expected_value = ValueGetter<T>::Get(getter); 1329 T desired_value = ValueGetter<T>::Get(getter); 1330 MaybeByteSwap(byte_swap, &expected_value); 1331 MaybeByteSwap(byte_swap, &desired_value); 1332 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result); 1333 accessor.Access(element_address); 1334 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1335 break; 1336 } 1337 case VarHandle::AccessMode::kWeakCompareAndSet: 1338 case VarHandle::AccessMode::kWeakCompareAndSetAcquire: 1339 case VarHandle::AccessMode::kWeakCompareAndSetPlain: 1340 case VarHandle::AccessMode::kWeakCompareAndSetRelease: { 1341 T expected_value = ValueGetter<T>::Get(getter); 1342 T desired_value = ValueGetter<T>::Get(getter); 1343 MaybeByteSwap(byte_swap, &expected_value); 1344 MaybeByteSwap(byte_swap, &desired_value); 1345 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result); 1346 accessor.Access(element_address); 1347 break; 1348 } 1349 case VarHandle::AccessMode::kGetAndSet: 1350 case VarHandle::AccessMode::kGetAndSetAcquire: 1351 case VarHandle::AccessMode::kGetAndSetRelease: { 1352 T new_value = ValueGetter<T>::Get(getter); 1353 MaybeByteSwap(byte_swap, &new_value); 1354 GetAndSetAccessor<T> accessor(new_value, result); 1355 accessor.Access(element_address); 1356 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1357 break; 1358 } 1359 case VarHandle::AccessMode::kGetAndAdd: 1360 case VarHandle::AccessMode::kGetAndAddAcquire: 1361 case VarHandle::AccessMode::kGetAndAddRelease: { 1362 T value = ValueGetter<T>::Get(getter); 1363 if (byte_swap) { 1364 GetAndAddWithByteSwapAccessor<T> accessor(value, result); 1365 accessor.Access(element_address); 1366 } else { 1367 GetAndAddAccessor<T> accessor(value, result); 1368 accessor.Access(element_address); 1369 } 1370 break; 1371 } 1372 case VarHandle::AccessMode::kGetAndBitwiseOr: 1373 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: 1374 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { 1375 T value = ValueGetter<T>::Get(getter); 1376 MaybeByteSwap(byte_swap, &value); 1377 GetAndBitwiseOrAccessor<T> accessor(value, result); 1378 accessor.Access(element_address); 1379 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1380 break; 1381 } 1382 case VarHandle::AccessMode::kGetAndBitwiseAnd: 1383 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: 1384 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { 1385 T value = ValueGetter<T>::Get(getter); 1386 MaybeByteSwap(byte_swap, &value); 1387 GetAndBitwiseAndAccessor<T> accessor(value, result); 1388 accessor.Access(element_address); 1389 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1390 break; 1391 } 1392 case VarHandle::AccessMode::kGetAndBitwiseXor: 1393 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: 1394 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { 1395 T value = ValueGetter<T>::Get(getter); 1396 MaybeByteSwap(byte_swap, &value); 1397 GetAndBitwiseXorAccessor<T> accessor(value, result); 1398 accessor.Access(element_address); 1399 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); 1400 break; 1401 } 1402 } 1403 return true; 1404 } 1405 }; 1406 1407 } // namespace 1408 1409 ObjPtr<Class> VarHandle::GetVarType() { 1410 return GetFieldObject<Class>(VarTypeOffset()); 1411 } 1412 1413 ObjPtr<Class> VarHandle::GetCoordinateType0() { 1414 return GetFieldObject<Class>(CoordinateType0Offset()); 1415 } 1416 1417 ObjPtr<Class> VarHandle::GetCoordinateType1() { 1418 return GetFieldObject<Class>(CoordinateType1Offset()); 1419 } 1420 1421 int32_t VarHandle::GetAccessModesBitMask() { 1422 return GetField32(AccessModesBitMaskOffset()); 1423 } 1424 1425 VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode access_mode, 1426 ObjPtr<MethodType> method_type) { 1427 MatchKind match = MatchKind::kExact; 1428 1429 ObjPtr<VarHandle> vh = this; 1430 ObjPtr<Class> var_type = vh->GetVarType(); 1431 ObjPtr<Class> mt_rtype = method_type->GetRType(); 1432 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); 1433 1434 // Check return type first. If the return type of the method 1435 // of the VarHandle is immaterial. 1436 if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) { 1437 ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type); 1438 if (vh_rtype != mt_rtype) { 1439 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) { 1440 return MatchKind::kNone; 1441 } 1442 match = MatchKind::kWithConversions; 1443 } 1444 } 1445 1446 // Check the number of parameters matches. 1447 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters]; 1448 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes, 1449 access_mode_template, 1450 var_type, 1451 GetCoordinateType0(), 1452 GetCoordinateType1()); 1453 if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) { 1454 return MatchKind::kNone; 1455 } 1456 1457 // Check the parameter types are compatible. 1458 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes(); 1459 for (int32_t i = 0; i < vh_ptypes_count; ++i) { 1460 if (mt_ptypes->Get(i) == vh_ptypes[i]) { 1461 continue; 1462 } 1463 if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) { 1464 return MatchKind::kNone; 1465 } 1466 match = MatchKind::kWithConversions; 1467 } 1468 return match; 1469 } 1470 1471 bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode, 1472 ObjPtr<MethodType> method_type) { 1473 StackHandleScope<3> hs(Thread::Current()); 1474 Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType())); 1475 Handle<VarHandle> vh(hs.NewHandle(this)); 1476 Handle<Class> var_type(hs.NewHandle(vh->GetVarType())); 1477 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); 1478 1479 // Check return type first. 1480 if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) { 1481 // The result of the operation will be discarded. The return type 1482 // of the VarHandle is immaterial. 1483 } else { 1484 ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get())); 1485 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) { 1486 return false; 1487 } 1488 } 1489 1490 // Check the number of parameters matches (ignoring the VarHandle parameter). 1491 static const int32_t kVarHandleParameters = 1; 1492 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters]; 1493 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes, 1494 access_mode_template, 1495 var_type.Get(), 1496 GetCoordinateType0(), 1497 GetCoordinateType1()); 1498 if (vh_ptypes_count != method_type->GetPTypes()->GetLength() - kVarHandleParameters) { 1499 return false; 1500 } 1501 1502 // Check the parameter types are compatible (ignoring the VarHandle parameter). 1503 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes(); 1504 for (int32_t i = 0; i < vh_ptypes_count; ++i) { 1505 if (!IsParameterTypeConvertible(mt_ptypes->Get(i + kVarHandleParameters), vh_ptypes[i])) { 1506 return false; 1507 } 1508 } 1509 return true; 1510 } 1511 1512 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, 1513 ObjPtr<VarHandle> var_handle, 1514 AccessMode access_mode) { 1515 // This is a static method as the var_handle might be moved by the GC during it's execution. 1516 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); 1517 1518 StackHandleScope<3> hs(self); 1519 Handle<VarHandle> vh = hs.NewHandle(var_handle); 1520 Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType())); 1521 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, 1522 vh->GetCoordinateType0(), 1523 vh->GetCoordinateType1()); 1524 ObjPtr<Class> array_of_class = GetClassRoot<ObjectArray<Class>>(); 1525 Handle<ObjectArray<Class>> ptypes = 1526 hs.NewHandle(ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count)); 1527 if (ptypes == nullptr) { 1528 return nullptr; 1529 } 1530 1531 ObjPtr<Class> ptypes_array[VarHandle::kMaxAccessorParameters]; 1532 BuildParameterArray(ptypes_array, 1533 access_mode_template, 1534 vh->GetVarType(), 1535 vh->GetCoordinateType0(), 1536 vh->GetCoordinateType1()); 1537 for (int32_t i = 0; i < ptypes_count; ++i) { 1538 ptypes->Set(i, ptypes_array[i]); 1539 } 1540 return MethodType::Create(self, rtype, ptypes); 1541 } 1542 1543 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) { 1544 return GetMethodTypeForAccessMode(self, this, access_mode); 1545 } 1546 1547 std::string VarHandle::PrettyDescriptorForAccessMode(AccessMode access_mode) { 1548 // Effect MethodType::PrettyDescriptor() without first creating a method type first. 1549 std::ostringstream oss; 1550 oss << '('; 1551 1552 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); 1553 ObjPtr<Class> var_type = GetVarType(); 1554 ObjPtr<Class> ctypes[2] = { GetCoordinateType0(), GetCoordinateType1() }; 1555 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, ctypes[0], ctypes[1]); 1556 int32_t ptypes_done = 0; 1557 for (ObjPtr<Class> ctype : ctypes) { 1558 if (!ctype.IsNull()) { 1559 if (ptypes_done != 0) { 1560 oss << ", "; 1561 } 1562 oss << ctype->PrettyDescriptor();; 1563 ptypes_done++; 1564 } 1565 } 1566 while (ptypes_done != ptypes_count) { 1567 if (ptypes_done != 0) { 1568 oss << ", "; 1569 } 1570 oss << var_type->PrettyDescriptor(); 1571 ptypes_done++; 1572 } 1573 ObjPtr<Class> rtype = GetReturnType(access_mode_template, var_type); 1574 oss << ')' << rtype->PrettyDescriptor(); 1575 return oss.str(); 1576 } 1577 1578 bool VarHandle::Access(AccessMode access_mode, 1579 ShadowFrame* shadow_frame, 1580 const InstructionOperands* const operands, 1581 JValue* result) { 1582 ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots(); 1583 ObjPtr<Class> klass = GetClass(); 1584 if (klass == GetClassRoot<FieldVarHandle>(class_roots)) { 1585 auto vh = reinterpret_cast<FieldVarHandle*>(this); 1586 return vh->Access(access_mode, shadow_frame, operands, result); 1587 } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) { 1588 auto vh = reinterpret_cast<ArrayElementVarHandle*>(this); 1589 return vh->Access(access_mode, shadow_frame, operands, result); 1590 } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) { 1591 auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this); 1592 return vh->Access(access_mode, shadow_frame, operands, result); 1593 } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) { 1594 auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this); 1595 return vh->Access(access_mode, shadow_frame, operands, result); 1596 } else { 1597 LOG(FATAL) << "Unknown varhandle kind"; 1598 UNREACHABLE(); 1599 } 1600 } 1601 1602 const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) { 1603 AccessMode access_mode; 1604 if (!GetAccessModeByMethodName(accessor_name, &access_mode)) { 1605 return nullptr; 1606 } 1607 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); 1608 switch (access_mode_template) { 1609 case AccessModeTemplate::kGet: 1610 case AccessModeTemplate::kCompareAndExchange: 1611 case AccessModeTemplate::kGetAndUpdate: 1612 return "Ljava/lang/Object;"; 1613 case AccessModeTemplate::kCompareAndSet: 1614 return "Z"; 1615 case AccessModeTemplate::kSet: 1616 return "V"; 1617 } 1618 } 1619 1620 VarHandle::AccessMode VarHandle::GetAccessModeByIntrinsic(Intrinsics intrinsic) { 1621 #define VAR_HANDLE_ACCESS_MODE(V) \ 1622 V(CompareAndExchange) \ 1623 V(CompareAndExchangeAcquire) \ 1624 V(CompareAndExchangeRelease) \ 1625 V(CompareAndSet) \ 1626 V(Get) \ 1627 V(GetAcquire) \ 1628 V(GetAndAdd) \ 1629 V(GetAndAddAcquire) \ 1630 V(GetAndAddRelease) \ 1631 V(GetAndBitwiseAnd) \ 1632 V(GetAndBitwiseAndAcquire) \ 1633 V(GetAndBitwiseAndRelease) \ 1634 V(GetAndBitwiseOr) \ 1635 V(GetAndBitwiseOrAcquire) \ 1636 V(GetAndBitwiseOrRelease) \ 1637 V(GetAndBitwiseXor) \ 1638 V(GetAndBitwiseXorAcquire) \ 1639 V(GetAndBitwiseXorRelease) \ 1640 V(GetAndSet) \ 1641 V(GetAndSetAcquire) \ 1642 V(GetAndSetRelease) \ 1643 V(GetOpaque) \ 1644 V(GetVolatile) \ 1645 V(Set) \ 1646 V(SetOpaque) \ 1647 V(SetRelease) \ 1648 V(SetVolatile) \ 1649 V(WeakCompareAndSet) \ 1650 V(WeakCompareAndSetAcquire) \ 1651 V(WeakCompareAndSetPlain) \ 1652 V(WeakCompareAndSetRelease) 1653 switch (intrinsic) { 1654 #define INTRINSIC_CASE(Name) \ 1655 case Intrinsics::kVarHandle ## Name: \ 1656 return VarHandle::AccessMode::k ## Name; 1657 VAR_HANDLE_ACCESS_MODE(INTRINSIC_CASE) 1658 #undef INTRINSIC_CASE 1659 #undef VAR_HANDLE_ACCESS_MODE 1660 default: 1661 break; 1662 } 1663 LOG(FATAL) << "Unknown VarHandle instrinsic: " << static_cast<int>(intrinsic); 1664 UNREACHABLE(); 1665 } 1666 1667 bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode) { 1668 if (method_name == nullptr) { 1669 return false; 1670 } 1671 VarHandleAccessorToAccessModeEntry target = { method_name, /*dummy*/VarHandle::AccessMode::kGet }; 1672 auto last = std::cend(kAccessorToAccessMode); 1673 auto it = std::lower_bound(std::cbegin(kAccessorToAccessMode), 1674 last, 1675 target, 1676 VarHandleAccessorToAccessModeEntry::CompareName); 1677 if (it == last || strcmp(it->method_name, method_name) != 0) { 1678 return false; 1679 } 1680 *access_mode = it->access_mode; 1681 return true; 1682 } 1683 1684 ArtField* FieldVarHandle::GetField() { 1685 return reinterpret_cast64<ArtField*>(GetField64(ArtFieldOffset())); 1686 } 1687 1688 bool FieldVarHandle::Access(AccessMode access_mode, 1689 ShadowFrame* shadow_frame, 1690 const InstructionOperands* const operands, 1691 JValue* result) { 1692 ShadowFrameGetter getter(*shadow_frame, operands); 1693 ArtField* field = GetField(); 1694 ObjPtr<Object> obj; 1695 if (field->IsStatic()) { 1696 DCHECK_LE(operands->GetNumberOfOperands(), 1697 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u)); 1698 obj = field->GetDeclaringClass(); 1699 } else { 1700 DCHECK_GE(operands->GetNumberOfOperands(), 1u); 1701 DCHECK_LE(operands->GetNumberOfOperands(), 1702 1u + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u)); 1703 obj = getter.GetReference(); 1704 if (obj.IsNull()) { 1705 ThrowNullPointerExceptionForCoordinate(); 1706 return false; 1707 } 1708 } 1709 DCHECK(!obj.IsNull()); 1710 1711 const MemberOffset offset = field->GetOffset(); 1712 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); 1713 switch (primitive_type) { 1714 case Primitive::Type::kPrimNot: 1715 return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, obj, offset, &getter, result); 1716 case Primitive::kPrimBoolean: 1717 return FieldAccessor<uint8_t>::Dispatch(access_mode, obj, offset, &getter, result); 1718 case Primitive::kPrimByte: 1719 return FieldAccessor<int8_t>::Dispatch(access_mode, obj, offset, &getter, result); 1720 case Primitive::kPrimChar: 1721 return FieldAccessor<uint16_t>::Dispatch(access_mode, obj, offset, &getter, result); 1722 case Primitive::kPrimShort: 1723 return FieldAccessor<int16_t>::Dispatch(access_mode, obj, offset, &getter, result); 1724 case Primitive::kPrimInt: 1725 return FieldAccessor<int32_t>::Dispatch(access_mode, obj, offset, &getter, result); 1726 case Primitive::kPrimFloat: 1727 return FieldAccessor<float>::Dispatch(access_mode, obj, offset, &getter, result); 1728 case Primitive::kPrimLong: 1729 return FieldAccessor<int64_t>::Dispatch(access_mode, obj, offset, &getter, result); 1730 case Primitive::kPrimDouble: 1731 return FieldAccessor<double>::Dispatch(access_mode, obj, offset, &getter, result); 1732 case Primitive::kPrimVoid: 1733 break; 1734 } 1735 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; 1736 UNREACHABLE(); 1737 } 1738 1739 bool ArrayElementVarHandle::Access(AccessMode access_mode, 1740 ShadowFrame* shadow_frame, 1741 const InstructionOperands* const operands, 1742 JValue* result) { 1743 ShadowFrameGetter getter(*shadow_frame, operands); 1744 1745 // The target array is the first co-ordinate type preceeding var type arguments. 1746 ObjPtr<Object> raw_array(getter.GetReference()); 1747 if (raw_array == nullptr) { 1748 ThrowNullPointerExceptionForCoordinate(); 1749 return false; 1750 } 1751 1752 ObjPtr<Array> target_array(raw_array->AsArray()); 1753 1754 // The target array element is the second co-ordinate type preceeding var type arguments. 1755 const int target_element = getter.Get(); 1756 if (!target_array->CheckIsValidIndex(target_element)) { 1757 DCHECK(Thread::Current()->IsExceptionPending()); 1758 return false; 1759 } 1760 1761 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); 1762 switch (primitive_type) { 1763 case Primitive::Type::kPrimNot: { 1764 MemberOffset target_element_offset = 1765 target_array->AsObjectArray<Object>()->OffsetOfElement(target_element); 1766 return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, 1767 target_array, 1768 target_element_offset, 1769 &getter, 1770 result); 1771 } 1772 case Primitive::Type::kPrimBoolean: 1773 return PrimitiveArrayElementAccessor<uint8_t>::Dispatch(access_mode, 1774 target_array, 1775 target_element, 1776 &getter, 1777 result); 1778 case Primitive::Type::kPrimByte: 1779 return PrimitiveArrayElementAccessor<int8_t>::Dispatch(access_mode, 1780 target_array, 1781 target_element, 1782 &getter, 1783 result); 1784 case Primitive::Type::kPrimChar: 1785 return PrimitiveArrayElementAccessor<uint16_t>::Dispatch(access_mode, 1786 target_array, 1787 target_element, 1788 &getter, 1789 result); 1790 case Primitive::Type::kPrimShort: 1791 return PrimitiveArrayElementAccessor<int16_t>::Dispatch(access_mode, 1792 target_array, 1793 target_element, 1794 &getter, 1795 result); 1796 case Primitive::Type::kPrimInt: 1797 return PrimitiveArrayElementAccessor<int32_t>::Dispatch(access_mode, 1798 target_array, 1799 target_element, 1800 &getter, 1801 result); 1802 case Primitive::Type::kPrimLong: 1803 return PrimitiveArrayElementAccessor<int64_t>::Dispatch(access_mode, 1804 target_array, 1805 target_element, 1806 &getter, 1807 result); 1808 case Primitive::Type::kPrimFloat: 1809 return PrimitiveArrayElementAccessor<float>::Dispatch(access_mode, 1810 target_array, 1811 target_element, 1812 &getter, 1813 result); 1814 case Primitive::Type::kPrimDouble: 1815 return PrimitiveArrayElementAccessor<double>::Dispatch(access_mode, 1816 target_array, 1817 target_element, 1818 &getter, 1819 result); 1820 case Primitive::Type::kPrimVoid: 1821 break; 1822 } 1823 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; 1824 UNREACHABLE(); 1825 } 1826 1827 bool ByteArrayViewVarHandle::GetNativeByteOrder() { 1828 return GetFieldBoolean(NativeByteOrderOffset()); 1829 } 1830 1831 bool ByteArrayViewVarHandle::Access(AccessMode access_mode, 1832 ShadowFrame* shadow_frame, 1833 const InstructionOperands* const operands, 1834 JValue* result) { 1835 ShadowFrameGetter getter(*shadow_frame, operands); 1836 1837 // The byte array is the first co-ordinate type preceeding var type arguments. 1838 ObjPtr<Object> raw_byte_array(getter.GetReference()); 1839 if (raw_byte_array == nullptr) { 1840 ThrowNullPointerExceptionForCoordinate(); 1841 return false; 1842 } 1843 1844 ObjPtr<ByteArray> byte_array(raw_byte_array->AsByteArray()); 1845 1846 // The offset in the byte array element is the second co-ordinate type. 1847 const int32_t data_offset = getter.Get(); 1848 1849 // Bounds check requested access. 1850 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); 1851 if (!CheckElementIndex(primitive_type, data_offset, byte_array->GetLength())) { 1852 return false; 1853 } 1854 1855 int8_t* const data = byte_array->GetData(); 1856 bool byte_swap = !GetNativeByteOrder(); 1857 switch (primitive_type) { 1858 case Primitive::Type::kPrimNot: 1859 case Primitive::kPrimBoolean: 1860 case Primitive::kPrimByte: 1861 case Primitive::kPrimVoid: 1862 // These are not supported for byte array views and not instantiable. 1863 break; 1864 case Primitive::kPrimChar: 1865 return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode, 1866 data, 1867 data_offset, 1868 byte_swap, 1869 &getter, 1870 result); 1871 case Primitive::kPrimShort: 1872 return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode, 1873 data, 1874 data_offset, 1875 byte_swap, 1876 &getter, 1877 result); 1878 case Primitive::kPrimInt: 1879 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, 1880 data, 1881 data_offset, 1882 byte_swap, 1883 &getter, 1884 result); 1885 case Primitive::kPrimFloat: 1886 // Treated as a bitwise representation. See javadoc comments for 1887 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). 1888 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, 1889 data, 1890 data_offset, 1891 byte_swap, 1892 &getter, 1893 result); 1894 case Primitive::kPrimLong: 1895 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, 1896 data, 1897 data_offset, 1898 byte_swap, 1899 &getter, 1900 result); 1901 case Primitive::kPrimDouble: 1902 // Treated as a bitwise representation. See javadoc comments for 1903 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). 1904 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, 1905 data, 1906 data_offset, 1907 byte_swap, 1908 &getter, 1909 result); 1910 } 1911 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; 1912 UNREACHABLE(); 1913 } 1914 1915 bool ByteBufferViewVarHandle::GetNativeByteOrder() { 1916 return GetFieldBoolean(NativeByteOrderOffset()); 1917 } 1918 1919 bool ByteBufferViewVarHandle::Access(AccessMode access_mode, 1920 ShadowFrame* shadow_frame, 1921 const InstructionOperands* const operands, 1922 JValue* result) { 1923 ShadowFrameGetter getter(*shadow_frame, operands); 1924 1925 // The byte buffer is the first co-ordinate argument preceeding var type arguments. 1926 ObjPtr<Object> byte_buffer(getter.GetReference()); 1927 if (byte_buffer == nullptr) { 1928 ThrowNullPointerExceptionForCoordinate(); 1929 return false; 1930 } 1931 1932 // The byte index for access is the second co-ordinate 1933 // argument. This is relative to the offset field of the ByteBuffer. 1934 const int32_t byte_index = getter.Get(); 1935 1936 // Check access_mode is compatible with ByteBuffer's read-only property. 1937 bool is_read_only = byte_buffer->GetFieldBoolean( 1938 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_isReadOnly)); 1939 if (is_read_only && !IsReadOnlyAccessMode(access_mode)) { 1940 ThrowReadOnlyBufferException(); 1941 return false; 1942 } 1943 1944 // The native_address is only set for ByteBuffer instances backed by native memory. 1945 const int64_t native_address = 1946 byte_buffer->GetField64(GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_address)); 1947 1948 // Determine offset and limit for accesses. 1949 int32_t byte_buffer_offset; 1950 if (native_address == 0L) { 1951 // Accessing a heap allocated byte buffer. 1952 byte_buffer_offset = byte_buffer->GetField32( 1953 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_offset)); 1954 } else { 1955 // Accessing direct memory. 1956 byte_buffer_offset = 0; 1957 } 1958 const int32_t byte_buffer_limit = byte_buffer->GetField32( 1959 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_limit)); 1960 1961 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); 1962 if (!CheckElementIndex(primitive_type, byte_index, byte_buffer_offset, byte_buffer_limit)) { 1963 return false; 1964 } 1965 const int32_t checked_offset32 = byte_buffer_offset + byte_index; 1966 1967 int8_t* data; 1968 if (native_address == 0) { 1969 ObjPtr<ByteArray> heap_byte_array = byte_buffer->GetFieldObject<ByteArray>( 1970 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_hb)); 1971 data = heap_byte_array->GetData(); 1972 } else { 1973 data = reinterpret_cast<int8_t*>(static_cast<uint32_t>(native_address)); 1974 } 1975 1976 bool byte_swap = !GetNativeByteOrder(); 1977 switch (primitive_type) { 1978 case Primitive::kPrimChar: 1979 return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode, 1980 data, 1981 checked_offset32, 1982 byte_swap, 1983 &getter, 1984 result); 1985 case Primitive::kPrimShort: 1986 return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode, 1987 data, 1988 checked_offset32, 1989 byte_swap, 1990 &getter, 1991 result); 1992 case Primitive::kPrimInt: 1993 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, 1994 data, 1995 checked_offset32, 1996 byte_swap, 1997 &getter, 1998 result); 1999 case Primitive::kPrimFloat: 2000 // Treated as a bitwise representation. See javadoc comments for 2001 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). 2002 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, 2003 data, 2004 checked_offset32, 2005 byte_swap, 2006 &getter, 2007 result); 2008 case Primitive::kPrimLong: 2009 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, 2010 data, 2011 checked_offset32, 2012 byte_swap, 2013 &getter, 2014 result); 2015 case Primitive::kPrimDouble: 2016 // Treated as a bitwise representation. See javadoc comments for 2017 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). 2018 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, 2019 data, 2020 checked_offset32, 2021 byte_swap, 2022 &getter, 2023 result); 2024 case Primitive::Type::kPrimNot: 2025 case Primitive::kPrimBoolean: 2026 case Primitive::kPrimByte: 2027 case Primitive::kPrimVoid: 2028 // These are not supported for byte array views and not instantiable. 2029 break; 2030 } 2031 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; 2032 UNREACHABLE(); 2033 } 2034 2035 } // namespace mirror 2036 } // namespace art 2037