HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Android 10
|
10.0.0_r6
下载
查看原文件
收藏
根目录
art
runtime
mirror
var_handle.cc
/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "var_handle.h" #include "array-inl.h" #include "art_field-inl.h" #include "base/casts.h" #include "class-inl.h" #include "class_linker.h" #include "class_root.h" #include "intrinsics_enum.h" #include "jni/jni_internal.h" #include "jvalue-inl.h" #include "method_handles-inl.h" #include "method_type-inl.h" #include "object_array-alloc-inl.h" #include "obj_ptr-inl.h" #include "well_known_classes.h" namespace art { namespace mirror { static constexpr bool kTransactionActive = true; static constexpr bool kTransactionInactive = !kTransactionActive; namespace { struct VarHandleAccessorToAccessModeEntry { const char* method_name; VarHandle::AccessMode access_mode; // Binary predicate function for finding access_mode by // method_name. The access_mode field is ignored. static bool CompareName(const VarHandleAccessorToAccessModeEntry& lhs, const VarHandleAccessorToAccessModeEntry& rhs) { return strcmp(lhs.method_name, rhs.method_name) < 0; } }; // Map of VarHandle accessor method names to access mode values. The list is alpha-sorted to support // binary search. For the usage scenario - lookups in the verifier - a linear scan would likely // suffice since we expect VarHandles to be a lesser encountered class. We could use a std::hashmap // here and this would be easier to maintain if new values are added here. However, this entails // CPU cycles initializing the structure on every execution and uses O(N) more memory for // intermediate nodes and makes that memory dirty. Compile-time magic using constexpr is possible // here, but that's a tax when this code is recompiled. const VarHandleAccessorToAccessModeEntry kAccessorToAccessMode[VarHandle::kNumberOfAccessModes] = { { "compareAndExchange", VarHandle::AccessMode::kCompareAndExchange }, { "compareAndExchangeAcquire", VarHandle::AccessMode::kCompareAndExchangeAcquire }, { "compareAndExchangeRelease", VarHandle::AccessMode::kCompareAndExchangeRelease }, { "compareAndSet", VarHandle::AccessMode::kCompareAndSet }, { "get", VarHandle::AccessMode::kGet }, { "getAcquire", VarHandle::AccessMode::kGetAcquire }, { "getAndAdd", VarHandle::AccessMode::kGetAndAdd }, { "getAndAddAcquire", VarHandle::AccessMode::kGetAndAddAcquire }, { "getAndAddRelease", VarHandle::AccessMode::kGetAndAddRelease }, { "getAndBitwiseAnd", VarHandle::AccessMode::kGetAndBitwiseAnd }, { "getAndBitwiseAndAcquire", VarHandle::AccessMode::kGetAndBitwiseAndAcquire }, { "getAndBitwiseAndRelease", VarHandle::AccessMode::kGetAndBitwiseAndRelease }, { "getAndBitwiseOr", VarHandle::AccessMode::kGetAndBitwiseOr }, { "getAndBitwiseOrAcquire", VarHandle::AccessMode::kGetAndBitwiseOrAcquire }, { "getAndBitwiseOrRelease", VarHandle::AccessMode::kGetAndBitwiseOrRelease }, { "getAndBitwiseXor", VarHandle::AccessMode::kGetAndBitwiseXor }, { "getAndBitwiseXorAcquire", VarHandle::AccessMode::kGetAndBitwiseXorAcquire }, { "getAndBitwiseXorRelease", VarHandle::AccessMode::kGetAndBitwiseXorRelease }, { "getAndSet", VarHandle::AccessMode::kGetAndSet }, { "getAndSetAcquire", VarHandle::AccessMode::kGetAndSetAcquire }, { "getAndSetRelease", VarHandle::AccessMode::kGetAndSetRelease }, { "getOpaque", VarHandle::AccessMode::kGetOpaque }, { "getVolatile", VarHandle::AccessMode::kGetVolatile }, { "set", VarHandle::AccessMode::kSet }, { "setOpaque", VarHandle::AccessMode::kSetOpaque }, { "setRelease", VarHandle::AccessMode::kSetRelease }, { "setVolatile", VarHandle::AccessMode::kSetVolatile }, { "weakCompareAndSet", VarHandle::AccessMode::kWeakCompareAndSet }, { "weakCompareAndSetAcquire", VarHandle::AccessMode::kWeakCompareAndSetAcquire }, { "weakCompareAndSetPlain", VarHandle::AccessMode::kWeakCompareAndSetPlain }, { "weakCompareAndSetRelease", VarHandle::AccessMode::kWeakCompareAndSetRelease }, }; // Enumeration for describing the parameter and return types of an AccessMode. enum class AccessModeTemplate : uint32_t { kGet, // T Op(C0..CN) kSet, // void Op(C0..CN, T) kCompareAndSet, // boolean Op(C0..CN, T, T) kCompareAndExchange, // T Op(C0..CN, T, T) kGetAndUpdate, // T Op(C0..CN, T) }; // Look up the AccessModeTemplate for a given VarHandle // AccessMode. This simplifies finding the correct signature for a // VarHandle accessor method. AccessModeTemplate GetAccessModeTemplate(VarHandle::AccessMode access_mode) { switch (access_mode) { case VarHandle::AccessMode::kGet: return AccessModeTemplate::kGet; case VarHandle::AccessMode::kSet: return AccessModeTemplate::kSet; case VarHandle::AccessMode::kGetVolatile: return AccessModeTemplate::kGet; case VarHandle::AccessMode::kSetVolatile: return AccessModeTemplate::kSet; case VarHandle::AccessMode::kGetAcquire: return AccessModeTemplate::kGet; case VarHandle::AccessMode::kSetRelease: return AccessModeTemplate::kSet; case VarHandle::AccessMode::kGetOpaque: return AccessModeTemplate::kGet; case VarHandle::AccessMode::kSetOpaque: return AccessModeTemplate::kSet; case VarHandle::AccessMode::kCompareAndSet: return AccessModeTemplate::kCompareAndSet; case VarHandle::AccessMode::kCompareAndExchange: return AccessModeTemplate::kCompareAndExchange; case VarHandle::AccessMode::kCompareAndExchangeAcquire: return AccessModeTemplate::kCompareAndExchange; case VarHandle::AccessMode::kCompareAndExchangeRelease: return AccessModeTemplate::kCompareAndExchange; case VarHandle::AccessMode::kWeakCompareAndSetPlain: return AccessModeTemplate::kCompareAndSet; case VarHandle::AccessMode::kWeakCompareAndSet: return AccessModeTemplate::kCompareAndSet; case VarHandle::AccessMode::kWeakCompareAndSetAcquire: return AccessModeTemplate::kCompareAndSet; case VarHandle::AccessMode::kWeakCompareAndSetRelease: return AccessModeTemplate::kCompareAndSet; case VarHandle::AccessMode::kGetAndSet: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndSetAcquire: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndSetRelease: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndAdd: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndAddAcquire: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndAddRelease: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseOr: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseOrRelease: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseAnd: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseAndRelease: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseXor: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseXorRelease: return AccessModeTemplate::kGetAndUpdate; case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: return AccessModeTemplate::kGetAndUpdate; } } int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) { switch (access_mode_template) { case AccessModeTemplate::kGet: return 0; case AccessModeTemplate::kSet: case AccessModeTemplate::kGetAndUpdate: return 1; case AccessModeTemplate::kCompareAndSet: case AccessModeTemplate::kCompareAndExchange: return 2; } UNREACHABLE(); } // Returns the number of parameters associated with an // AccessModeTemplate and the supplied coordinate types. int32_t GetNumberOfParameters(AccessModeTemplate access_mode_template, ObjPtr
coordinateType0, ObjPtr
coordinateType1) { int32_t count = 0; if (!coordinateType0.IsNull()) { count++; if (!coordinateType1.IsNull()) { count++; } } return count + GetNumberOfVarTypeParameters(access_mode_template); } void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) { ThrowNullPointerException("Attempt to access memory on a null object"); } bool CheckElementIndex(Primitive::Type type, int32_t relative_index, int32_t start, int32_t limit) REQUIRES_SHARED(Locks::mutator_lock_) { int64_t index = start + relative_index; int64_t max_index = limit - Primitive::ComponentSize(type); if (index < start || index > max_index) { ThrowIndexOutOfBoundsException(index, limit - start); return false; } return true; } bool CheckElementIndex(Primitive::Type type, int32_t index, int32_t range_limit) REQUIRES_SHARED(Locks::mutator_lock_) { return CheckElementIndex(type, index, 0, range_limit); } // Returns true if access_mode only entails a memory read. False if // access_mode may write to memory. bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) { AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); return access_mode_template == AccessModeTemplate::kGet; } // Writes the parameter types associated with the AccessModeTemplate // into an array. The parameter types are derived from the specified // variable type and coordinate types. Returns the number of // parameters written. int32_t BuildParameterArray(ObjPtr
(¶meters)[VarHandle::kMaxAccessorParameters], AccessModeTemplate access_mode_template, ObjPtr
varType, ObjPtr
coordinateType0, ObjPtr
coordinateType1) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(varType != nullptr); int32_t index = 0; if (!coordinateType0.IsNull()) { parameters[index++] = coordinateType0; if (!coordinateType1.IsNull()) { parameters[index++] = coordinateType1; } } else { DCHECK(coordinateType1.IsNull()); } switch (access_mode_template) { case AccessModeTemplate::kCompareAndExchange: case AccessModeTemplate::kCompareAndSet: parameters[index++] = varType; parameters[index++] = varType; return index; case AccessModeTemplate::kGet: return index; case AccessModeTemplate::kGetAndUpdate: case AccessModeTemplate::kSet: parameters[index++] = varType; return index; } return -1; } // Returns the return type associated with an AccessModeTemplate based // on the template and the variable type specified. static ObjPtr
GetReturnType(AccessModeTemplate access_mode_template, ObjPtr
varType) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(varType != nullptr); switch (access_mode_template) { case AccessModeTemplate::kCompareAndSet: return GetClassRoot(ClassRoot::kPrimitiveBoolean); case AccessModeTemplate::kCompareAndExchange: case AccessModeTemplate::kGet: case AccessModeTemplate::kGetAndUpdate: return varType; case AccessModeTemplate::kSet: return GetClassRoot(ClassRoot::kPrimitiveVoid); } return nullptr; } // Method to insert a read barrier for accessors to reference fields. inline void ReadBarrierForVarHandleAccess(ObjPtr
obj, MemberOffset field_offset) REQUIRES_SHARED(Locks::mutator_lock_) { if (kUseReadBarrier) { // We need to ensure that the reference stored in the field is a to-space one before attempting // the CompareAndSet/CompareAndExchange/Exchange operation otherwise it will fail incorrectly // if obj is in the process of being moved. uint8_t* raw_field_addr = reinterpret_cast
(obj.Ptr()) + field_offset.SizeValue(); auto field_addr = reinterpret_cast
*>(raw_field_addr); // Note that the read barrier load does NOT need to be volatile. static constexpr bool kIsVolatile = false; static constexpr bool kAlwaysUpdateField = true; ReadBarrier::Barrier
( obj.Ptr(), MemberOffset(field_offset), field_addr); } } inline MemberOffset GetMemberOffset(jfieldID field_id) REQUIRES_SHARED(Locks::mutator_lock_) { ArtField* const field = jni::DecodeArtField(field_id); return field->GetOffset(); } // // Helper methods for storing results from atomic operations into // JValue instances. // inline void StoreResult(uint8_t value, JValue* result) { result->SetZ(value); } inline void StoreResult(int8_t value, JValue* result) { result->SetB(value); } inline void StoreResult(uint16_t value, JValue* result) { result->SetC(value); } inline void StoreResult(int16_t value, JValue* result) { result->SetS(value); } inline void StoreResult(int32_t value, JValue* result) { result->SetI(value); } inline void StoreResult(int64_t value, JValue* result) { result->SetJ(value); } inline void StoreResult(float value, JValue* result) { result->SetF(value); } inline void StoreResult(double value, JValue* result) { result->SetD(value); } inline void StoreResult(ObjPtr
value, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { result->SetL(value); } // // Helper class for byte-swapping value that has been stored in a JValue. // template
class JValueByteSwapper final { public: static void ByteSwap(JValue* value); static void MaybeByteSwap(bool byte_swap, JValue* value) { if (byte_swap) { ByteSwap(value); } } }; template <> void JValueByteSwapper
::ByteSwap(JValue* value) { value->SetC(BSWAP(value->GetC())); } template <> void JValueByteSwapper
::ByteSwap(JValue* value) { value->SetS(BSWAP(value->GetS())); } template <> void JValueByteSwapper
::ByteSwap(JValue* value) { value->SetI(BSWAP(value->GetI())); } template <> void JValueByteSwapper
::ByteSwap(JValue* value) { value->SetJ(BSWAP(value->GetJ())); } // // Accessor implementations, shared across all VarHandle types. // template
class AtomicGetAccessor : public Object::Accessor
{ public: explicit AtomicGetAccessor(JValue* result) : result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); StoreResult(atom->load(MO), result_); } private: JValue* result_; }; template
class AtomicSetAccessor : public Object::Accessor
{ public: explicit AtomicSetAccessor(T new_value) : new_value_(new_value) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); atom->store(new_value_, MO); } private: T new_value_; }; template
using GetAccessor = AtomicGetAccessor
; template
using SetAccessor = AtomicSetAccessor
; template
using GetVolatileAccessor = AtomicGetAccessor
; template
using SetVolatileAccessor = AtomicSetAccessor
; template
class AtomicStrongCompareAndSetAccessor : public Object::Accessor
{ public: AtomicStrongCompareAndSetAccessor(T expected_value, T desired_value, JValue* result) : expected_value_(expected_value), desired_value_(desired_value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); bool success = atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF); StoreResult(success ? JNI_TRUE : JNI_FALSE, result_); } private: T expected_value_; T desired_value_; JValue* result_; }; template
using CompareAndSetAccessor = AtomicStrongCompareAndSetAccessor
; template
class AtomicStrongCompareAndExchangeAccessor : public Object::Accessor
{ public: AtomicStrongCompareAndExchangeAccessor(T expected_value, T desired_value, JValue* result) : expected_value_(expected_value), desired_value_(desired_value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF); StoreResult(expected_value_, result_); } private: T expected_value_; T desired_value_; JValue* result_; }; template
using CompareAndExchangeAccessor = AtomicStrongCompareAndExchangeAccessor
; template
class AtomicWeakCompareAndSetAccessor : public Object::Accessor
{ public: AtomicWeakCompareAndSetAccessor(T expected_value, T desired_value, JValue* result) : expected_value_(expected_value), desired_value_(desired_value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); bool success = atom->compare_exchange_weak(expected_value_, desired_value_, MOS, MOF); StoreResult(success ? JNI_TRUE : JNI_FALSE, result_); } private: T expected_value_; T desired_value_; JValue* result_; }; template
using WeakCompareAndSetAccessor = AtomicWeakCompareAndSetAccessor
; template
class AtomicGetAndSetAccessor : public Object::Accessor
{ public: AtomicGetAndSetAccessor(T new_value, JValue* result) : new_value_(new_value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); T old_value = atom->exchange(new_value_, MO); StoreResult(old_value, result_); } private: T new_value_; JValue* result_; }; template
using GetAndSetAccessor = AtomicGetAndSetAccessor
; template
class AtomicGetAndAddOperator { public: static T Apply(T* addr, T addend) { std::atomic
* atom = reinterpret_cast
*>(addr); return atom->fetch_add(addend, MO); } }; template
class AtomicGetAndAddOperator
{ public: static T Apply(T* addr, T addend) { // c++11 does not have std::atomic
::fetch_and_add for floating // point types, so we effect one with a compare and swap. std::atomic
* atom = reinterpret_cast
*>(addr); T old_value = atom->load(std::memory_order_relaxed); T new_value; do { new_value = old_value + addend; } while (!atom->compare_exchange_weak(old_value, new_value, MO, std::memory_order_relaxed)); return old_value; } }; template
class AtomicGetAndAddAccessor : public Object::Accessor
{ public: AtomicGetAndAddAccessor(T addend, JValue* result) : addend_(addend), result_(result) {} void Access(T* addr) override { constexpr bool kIsFloatingPoint = std::is_floating_point
::value; T old_value = AtomicGetAndAddOperator
::Apply(addr, addend_); StoreResult(old_value, result_); } private: T addend_; JValue* result_; }; template
using GetAndAddAccessor = AtomicGetAndAddAccessor
; // Accessor specifically for memory views where the caller can specify // the byte-ordering. Addition only works outside of the byte-swapped // memory view because of the direction of carries. template
class AtomicGetAndAddWithByteSwapAccessor : public Object::Accessor
{ public: AtomicGetAndAddWithByteSwapAccessor(T value, JValue* result) : value_(value), result_(result) {} void Access(T* addr) override { std::atomic
* const atom = reinterpret_cast
*>(addr); T current_value = atom->load(std::memory_order_relaxed); T sum; do { sum = BSWAP(current_value) + value_; // NB current_value is a pass-by-reference argument in the call to // atomic
::compare_exchange_weak(). } while (!atom->compare_exchange_weak(current_value, BSWAP(sum), MO, std::memory_order_relaxed)); StoreResult(BSWAP(current_value), result_); } private: T value_; JValue* result_; }; template
using GetAndAddWithByteSwapAccessor = AtomicGetAndAddWithByteSwapAccessor
; template
class AtomicGetAndBitwiseOrAccessor : public Object::Accessor
{ public: AtomicGetAndBitwiseOrAccessor(T value, JValue* result) : value_(value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); T old_value = atom->fetch_or(value_, MO); StoreResult(old_value, result_); } private: T value_; JValue* result_; }; template
using GetAndBitwiseOrAccessor = AtomicGetAndBitwiseOrAccessor
; template
class AtomicGetAndBitwiseAndAccessor : public Object::Accessor
{ public: AtomicGetAndBitwiseAndAccessor(T value, JValue* result) : value_(value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); T old_value = atom->fetch_and(value_, MO); StoreResult(old_value, result_); } private: T value_; JValue* result_; }; template
using GetAndBitwiseAndAccessor = AtomicGetAndBitwiseAndAccessor
; template
class AtomicGetAndBitwiseXorAccessor : public Object::Accessor
{ public: AtomicGetAndBitwiseXorAccessor(T value, JValue* result) : value_(value), result_(result) {} void Access(T* addr) override { std::atomic
* atom = reinterpret_cast
*>(addr); T old_value = atom->fetch_xor(value_, MO); StoreResult(old_value, result_); } private: T value_; JValue* result_; }; template
using GetAndBitwiseXorAccessor = AtomicGetAndBitwiseXorAccessor
; // // Unreachable access modes. // NO_RETURN void UnreachableAccessMode(const char* access_mode, const char* type_name) { LOG(FATAL) << "Unreachable access mode :" << access_mode << " for type " << type_name; UNREACHABLE(); } #define UNREACHABLE_ACCESS_MODE(ACCESS_MODE, TYPE) \ template<> void ACCESS_MODE ## Accessor
::Access(TYPE*) { \ UnreachableAccessMode(#ACCESS_MODE, #TYPE); \ } // The boolean primitive type is not numeric (boolean == std::uint8_t). UNREACHABLE_ACCESS_MODE(GetAndAdd, uint8_t) // The floating point types do not support bitwise operations. UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, float) UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, float) UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, float) UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, double) UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, double) UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, double) // A helper class for object field accesses for floats and // doubles. The object interface deals with Field32 and Field64. The // former is used for both integers and floats, the latter for longs // and doubles. This class provides the necessary coercion. template
class TypeAdaptorAccessor : public Object::Accessor
{ public: explicit TypeAdaptorAccessor(Object::Accessor
* inner_accessor) : inner_accessor_(inner_accessor) {} void Access(T* addr) override { static_assert(sizeof(T) == sizeof(U), "bad conversion"); inner_accessor_->Access(reinterpret_cast
(addr)); } private: Object::Accessor
* inner_accessor_; }; template
class FieldAccessViaAccessor { public: using Accessor = Object::Accessor
; // Apply an Accessor to get a field in an object. static void Get(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { obj->GetPrimitiveFieldViaAccessor(field_offset, accessor); } // Apply an Accessor to update a field in an object. static void Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_); }; template <> inline void FieldAccessViaAccessor
::Get(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { TypeAdaptorAccessor
float_to_int_accessor(accessor); obj->GetPrimitiveFieldViaAccessor(field_offset, &float_to_int_accessor); } template <> inline void FieldAccessViaAccessor
::Get(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { TypeAdaptorAccessor
double_to_int_accessor(accessor); obj->GetPrimitiveFieldViaAccessor(field_offset, &double_to_int_accessor); } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateFieldBooleanViaAccessor
(field_offset, accessor); } else { obj->UpdateFieldBooleanViaAccessor
(field_offset, accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateFieldByteViaAccessor
(field_offset, accessor); } else { obj->UpdateFieldByteViaAccessor
(field_offset, accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateFieldCharViaAccessor
(field_offset, accessor); } else { obj->UpdateFieldCharViaAccessor
(field_offset, accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateFieldShortViaAccessor
(field_offset, accessor); } else { obj->UpdateFieldShortViaAccessor
(field_offset, accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateField32ViaAccessor
(field_offset, accessor); } else { obj->UpdateField32ViaAccessor
(field_offset, accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateField64ViaAccessor
(field_offset, accessor); } else { obj->UpdateField64ViaAccessor
(field_offset, accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { TypeAdaptorAccessor
float_to_int_accessor(accessor); if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateField32ViaAccessor
(field_offset, &float_to_int_accessor); } else { obj->UpdateField32ViaAccessor
(field_offset, &float_to_int_accessor); } } template <> void FieldAccessViaAccessor
::Update(ObjPtr
obj, MemberOffset field_offset, Accessor* accessor) REQUIRES_SHARED(Locks::mutator_lock_) { TypeAdaptorAccessor
double_to_int_accessor(accessor); if (Runtime::Current()->IsActiveTransaction()) { obj->UpdateField64ViaAccessor
(field_offset, &double_to_int_accessor); } else { obj->UpdateField64ViaAccessor
(field_offset, &double_to_int_accessor); } } // Helper class that gets values from a shadow frame with appropriate type coercion. template
class ValueGetter { public: static T Get(ShadowFrameGetter* getter) REQUIRES_SHARED(Locks::mutator_lock_) { static_assert(sizeof(T) <= sizeof(uint32_t), "Bad size"); uint32_t raw_value = getter->Get(); return static_cast
(raw_value); } }; template <> int64_t ValueGetter
::Get(ShadowFrameGetter* getter) { return getter->GetLong(); } template <> float ValueGetter
::Get(ShadowFrameGetter* getter) { uint32_t raw_value = getter->Get(); return *reinterpret_cast
(&raw_value); } template <> double ValueGetter
::Get(ShadowFrameGetter* getter) { int64_t raw_value = getter->GetLong(); return *reinterpret_cast
(&raw_value); } template <> ObjPtr
ValueGetter
>::Get(ShadowFrameGetter* getter) { return getter->GetReference(); } // Class for accessing fields of Object instances template
class FieldAccessor { public: static bool Dispatch(VarHandle::AccessMode access_mode, ObjPtr
obj, MemberOffset field_offset, ShadowFrameGetter* getter, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_); }; // Dispatch implementation for primitive fields. template
bool FieldAccessor
::Dispatch(VarHandle::AccessMode access_mode, ObjPtr
obj, MemberOffset field_offset, ShadowFrameGetter* getter, JValue* result) { switch (access_mode) { case VarHandle::AccessMode::kGet: { GetAccessor
accessor(result); FieldAccessViaAccessor
::Get(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kSet: { T new_value = ValueGetter
::Get(getter); SetAccessor
accessor(new_value); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kGetAcquire: case VarHandle::AccessMode::kGetOpaque: case VarHandle::AccessMode::kGetVolatile: { GetVolatileAccessor
accessor(result); FieldAccessViaAccessor
::Get(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kSetOpaque: case VarHandle::AccessMode::kSetRelease: case VarHandle::AccessMode::kSetVolatile: { T new_value = ValueGetter
::Get(getter); SetVolatileAccessor
accessor(new_value); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kCompareAndSet: { T expected_value = ValueGetter
::Get(getter); T desired_value = ValueGetter
::Get(getter); CompareAndSetAccessor
accessor(expected_value, desired_value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kCompareAndExchange: case VarHandle::AccessMode::kCompareAndExchangeAcquire: case VarHandle::AccessMode::kCompareAndExchangeRelease: { T expected_value = ValueGetter
::Get(getter); T desired_value = ValueGetter
::Get(getter); CompareAndExchangeAccessor
accessor(expected_value, desired_value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kWeakCompareAndSet: case VarHandle::AccessMode::kWeakCompareAndSetAcquire: case VarHandle::AccessMode::kWeakCompareAndSetPlain: case VarHandle::AccessMode::kWeakCompareAndSetRelease: { T expected_value = ValueGetter
::Get(getter); T desired_value = ValueGetter
::Get(getter); WeakCompareAndSetAccessor
accessor(expected_value, desired_value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kGetAndSet: case VarHandle::AccessMode::kGetAndSetAcquire: case VarHandle::AccessMode::kGetAndSetRelease: { T new_value = ValueGetter
::Get(getter); GetAndSetAccessor
accessor(new_value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kGetAndAdd: case VarHandle::AccessMode::kGetAndAddAcquire: case VarHandle::AccessMode::kGetAndAddRelease: { T value = ValueGetter
::Get(getter); GetAndAddAccessor
accessor(value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kGetAndBitwiseOr: case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { T value = ValueGetter
::Get(getter); GetAndBitwiseOrAccessor
accessor(value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kGetAndBitwiseAnd: case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { T value = ValueGetter
::Get(getter); GetAndBitwiseAndAccessor
accessor(value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } case VarHandle::AccessMode::kGetAndBitwiseXor: case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { T value = ValueGetter
::Get(getter); GetAndBitwiseXorAccessor
accessor(value, result); FieldAccessViaAccessor
::Update(obj, field_offset, &accessor); break; } } return true; } // Dispatch implementation for reference fields. template <> bool FieldAccessor
>::Dispatch(VarHandle::AccessMode access_mode, ObjPtr
obj, MemberOffset field_offset, ShadowFrameGetter* getter, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { // To keep things simple, use the minimum strongest existing // field accessor for Object fields. This may be the most // straightforward strategy in general for the interpreter. switch (access_mode) { case VarHandle::AccessMode::kGet: { StoreResult(obj->GetFieldObject
(field_offset), result); break; } case VarHandle::AccessMode::kSet: { ObjPtr
new_value = ValueGetter
>::Get(getter); if (Runtime::Current()->IsActiveTransaction()) { obj->SetFieldObject
(field_offset, new_value); } else { obj->SetFieldObject
(field_offset, new_value); } break; } case VarHandle::AccessMode::kGetAcquire: case VarHandle::AccessMode::kGetOpaque: case VarHandle::AccessMode::kGetVolatile: { StoreResult(obj->GetFieldObjectVolatile
(field_offset), result); break; } case VarHandle::AccessMode::kSetOpaque: case VarHandle::AccessMode::kSetRelease: case VarHandle::AccessMode::kSetVolatile: { ObjPtr
new_value = ValueGetter
>::Get(getter); if (Runtime::Current()->IsActiveTransaction()) { obj->SetFieldObjectVolatile
(field_offset, new_value); } else { obj->SetFieldObjectVolatile
(field_offset, new_value); } break; } case VarHandle::AccessMode::kCompareAndSet: { ReadBarrierForVarHandleAccess(obj, field_offset); ObjPtr
expected_value = ValueGetter
>::Get(getter); ObjPtr
desired_value = ValueGetter
>::Get(getter); bool cas_result; if (Runtime::Current()->IsActiveTransaction()) { cas_result = obj->CasFieldObject
(field_offset, expected_value, desired_value, CASMode::kStrong, std::memory_order_seq_cst); } else { cas_result = obj->CasFieldObject
(field_offset, expected_value, desired_value, CASMode::kStrong, std::memory_order_seq_cst); } StoreResult(static_cast
(cas_result), result); break; } case VarHandle::AccessMode::kWeakCompareAndSet: case VarHandle::AccessMode::kWeakCompareAndSetAcquire: case VarHandle::AccessMode::kWeakCompareAndSetPlain: case VarHandle::AccessMode::kWeakCompareAndSetRelease: { ReadBarrierForVarHandleAccess(obj, field_offset); ObjPtr
expected_value = ValueGetter
>::Get(getter); ObjPtr
desired_value = ValueGetter
>::Get(getter); bool cas_result; if (Runtime::Current()->IsActiveTransaction()) { cas_result = obj->CasFieldObject
(field_offset, expected_value, desired_value, CASMode::kWeak, std::memory_order_seq_cst); } else { cas_result = obj->CasFieldObject
( field_offset, expected_value, desired_value, CASMode::kWeak, std::memory_order_seq_cst); } StoreResult(static_cast
(cas_result), result); break; } case VarHandle::AccessMode::kCompareAndExchange: case VarHandle::AccessMode::kCompareAndExchangeAcquire: case VarHandle::AccessMode::kCompareAndExchangeRelease: { ReadBarrierForVarHandleAccess(obj, field_offset); ObjPtr
expected_value = ValueGetter
>::Get(getter); ObjPtr
desired_value = ValueGetter
>::Get(getter); ObjPtr
witness_value; if (Runtime::Current()->IsActiveTransaction()) { witness_value = obj->CompareAndExchangeFieldObject
(field_offset, expected_value, desired_value); } else { witness_value = obj->CompareAndExchangeFieldObject
(field_offset, expected_value, desired_value); } StoreResult(witness_value, result); break; } case VarHandle::AccessMode::kGetAndSet: case VarHandle::AccessMode::kGetAndSetAcquire: case VarHandle::AccessMode::kGetAndSetRelease: { ReadBarrierForVarHandleAccess(obj, field_offset); ObjPtr
new_value = ValueGetter
>::Get(getter); ObjPtr
old_value; if (Runtime::Current()->IsActiveTransaction()) { old_value = obj->ExchangeFieldObject
(field_offset, new_value); } else { old_value = obj->ExchangeFieldObject
(field_offset, new_value); } StoreResult(old_value, result); break; } case VarHandle::AccessMode::kGetAndAdd: case VarHandle::AccessMode::kGetAndAddAcquire: case VarHandle::AccessMode::kGetAndAddRelease: case VarHandle::AccessMode::kGetAndBitwiseOr: case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: case VarHandle::AccessMode::kGetAndBitwiseOrRelease: case VarHandle::AccessMode::kGetAndBitwiseAnd: case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: case VarHandle::AccessMode::kGetAndBitwiseAndRelease: case VarHandle::AccessMode::kGetAndBitwiseXor: case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { size_t index = static_cast
(access_mode); const char* access_mode_name = kAccessorToAccessMode[index].method_name; UnreachableAccessMode(access_mode_name, "Object"); } } return true; } // Class for accessing primitive array elements. template
class PrimitiveArrayElementAccessor { public: static T* GetElementAddress(ObjPtr
target_array, int target_element) REQUIRES_SHARED(Locks::mutator_lock_) { auto primitive_array = ObjPtr
>::DownCast(target_array); DCHECK(primitive_array->CheckIsValidIndex(target_element)); return &primitive_array->GetData()[target_element]; } static bool Dispatch(VarHandle::AccessMode access_mode, ObjPtr
target_array, int target_element, ShadowFrameGetter* getter, JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { T* element_address = GetElementAddress(target_array, target_element); switch (access_mode) { case VarHandle::AccessMode::kGet: { GetAccessor
accessor(result); accessor.Access(element_address); break; } case VarHandle::AccessMode::kSet: { T new_value = ValueGetter
::Get(getter); SetAccessor
accessor(new_value); accessor.Access(element_address); break; } case VarHandle::AccessMode::kGetAcquire: case VarHandle::AccessMode::kGetOpaque: case VarHandle::AccessMode::kGetVolatile: { GetVolatileAccessor
accessor(result); accessor.Access(element_address); break; } case VarHandle::AccessMode::kSetOpaque: case VarHandle::AccessMode::kSetRelease: case VarHandle::AccessMode::kSetVolatile: { T new_value = ValueGetter
::Get(getter); SetVolatileAccessor
accessor(new_value); accessor.Access(element_address); break; } case VarHandle::AccessMode::kCompareAndSet: { T expected_value = ValueGetter
::Get(getter); T desired_value = ValueGetter
::Get(getter); CompareAndSetAccessor
accessor(expected_value, desired_value, result); accessor.Access(element_address); break; } case VarHandle::AccessMode::kCompareAndExchange: case VarHandle::AccessMode::kCompareAndExchangeAcquire: case VarHandle::AccessMode::kCompareAndExchangeRelease: { T expected_value = ValueGetter
::Get(getter); T desired_value = ValueGetter
::Get(getter); CompareAndExchangeAccessor
accessor(expected_value, desired_value, result); accessor.Access(element_address); break; } case VarHandle::AccessMode::kWeakCompareAndSet: case VarHandle::AccessMode::kWeakCompareAndSetAcquire: case VarHandle::AccessMode::kWeakCompareAndSetPlain: case VarHandle::AccessMode::kWeakCompareAndSetRelease: { T expected_value = ValueGetter