diff options
author | 2020-09-02 16:41:13 +0100 | |
---|---|---|
committer | 2020-09-02 19:39:22 +0000 | |
commit | d111cd22792c1cda507e343e46762842956a2c9b (patch) | |
tree | e9c7c49446dd3e92e30d39baa98038193f943f60 | |
parent | b78bfeea4526a286ab7cf4874759be8e0d1daeba (diff) |
Expose VarHandle::AccessModeTemplate and helpers for compiler
Bug: 65872996
Test: art/test/run_test.sh --host 712
Test: art_runtime_tests
Change-Id: I3c19fe8bb1f4be4275c9c0c51ecf8b57ab1b7e96
-rw-r--r-- | runtime/mirror/var_handle.cc | 216 | ||||
-rw-r--r-- | runtime/mirror/var_handle.h | 24 | ||||
-rw-r--r-- | runtime/mirror/var_handle_test.cc | 59 |
3 files changed, 189 insertions, 110 deletions
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc index 202134a1dc..7970c621d7 100644 --- a/runtime/mirror/var_handle.cc +++ b/runtime/mirror/var_handle.cc @@ -92,102 +92,9 @@ const VarHandleAccessorToAccessModeEntry kAccessorToAccessMode[VarHandle::kNumbe { "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, +int32_t GetNumberOfParameters(VarHandle::AccessModeTemplate access_mode_template, ObjPtr<Class> coordinateType0, ObjPtr<Class> coordinateType1) { int32_t count = 0; @@ -197,7 +104,7 @@ int32_t GetNumberOfParameters(AccessModeTemplate access_mode_template, count++; } } - return count + GetNumberOfVarTypeParameters(access_mode_template); + return count + VarHandle::GetNumberOfVarTypeParameters(access_mode_template); } void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) { @@ -225,8 +132,7 @@ bool CheckElementIndex(Primitive::Type type, int32_t index, int32_t 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; + return VarHandle::GetAccessModeTemplate(access_mode) == VarHandle::AccessModeTemplate::kGet; } // Writes the parameter types associated with the AccessModeTemplate @@ -234,7 +140,7 @@ bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) { // variable type and coordinate types. Returns the number of // parameters written. int32_t BuildParameterArray(ObjPtr<Class> (¶meters)[VarHandle::kMaxAccessorParameters], - AccessModeTemplate access_mode_template, + VarHandle::AccessModeTemplate access_mode_template, ObjPtr<Class> varType, ObjPtr<Class> coordinateType0, ObjPtr<Class> coordinateType1) @@ -251,34 +157,35 @@ int32_t BuildParameterArray(ObjPtr<Class> (¶meters)[VarHandle::kMaxAccessorP } switch (access_mode_template) { - case AccessModeTemplate::kCompareAndExchange: - case AccessModeTemplate::kCompareAndSet: + case VarHandle::AccessModeTemplate::kCompareAndExchange: + case VarHandle::AccessModeTemplate::kCompareAndSet: parameters[index++] = varType; parameters[index++] = varType; return index; - case AccessModeTemplate::kGet: + case VarHandle::AccessModeTemplate::kGet: return index; - case AccessModeTemplate::kGetAndUpdate: - case AccessModeTemplate::kSet: + case VarHandle::AccessModeTemplate::kGetAndUpdate: + case VarHandle::AccessModeTemplate::kSet: parameters[index++] = varType; return index; } return -1; } -// Returns the return type associated with an AccessModeTemplate based +// Returns the return type associated with an VarHandle::AccessModeTemplate based // on the template and the variable type specified. -static ObjPtr<Class> GetReturnType(AccessModeTemplate access_mode_template, ObjPtr<Class> varType) +static ObjPtr<Class> GetReturnType(VarHandle::AccessModeTemplate access_mode_template, + ObjPtr<Class> varType) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(varType != nullptr); switch (access_mode_template) { - case AccessModeTemplate::kCompareAndSet: + case VarHandle::AccessModeTemplate::kCompareAndSet: return GetClassRoot(ClassRoot::kPrimitiveBoolean); - case AccessModeTemplate::kCompareAndExchange: - case AccessModeTemplate::kGet: - case AccessModeTemplate::kGetAndUpdate: + case VarHandle::AccessModeTemplate::kCompareAndExchange: + case VarHandle::AccessModeTemplate::kGet: + case VarHandle::AccessModeTemplate::kGetAndUpdate: return varType; - case AccessModeTemplate::kSet: + case VarHandle::AccessModeTemplate::kSet: return GetClassRoot(ClassRoot::kPrimitiveVoid); } return nullptr; @@ -1647,6 +1554,95 @@ bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* a return true; } +// Look up the AccessModeTemplate for a given VarHandle +// AccessMode. This simplifies finding the correct signature for a +// VarHandle accessor method. +VarHandle::AccessModeTemplate VarHandle::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; + } +} + +VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplateByIntrinsic(Intrinsics ordinal) { + AccessMode access_mode = GetAccessModeByIntrinsic(ordinal); + return GetAccessModeTemplate(access_mode); +} + +int32_t VarHandle::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(); +} + ArtField* FieldVarHandle::GetField() { return reinterpret_cast64<ArtField*>(GetField64(ArtFieldOffset())); } diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h index 83cf2e1111..c1dcb94eab 100644 --- a/runtime/mirror/var_handle.h +++ b/runtime/mirror/var_handle.h @@ -57,6 +57,12 @@ class MANAGED VarHandle : public Object { // method can take. static constexpr size_t kMaxVarTypeParameters = 2; + // The minimum number of CoordinateType parameters a VarHandle acessor method may take. + static constexpr size_t kMinCoordinateTypes = 0; + + // The maximum number of CoordinateType parameters a VarHandle acessor method may take. + static constexpr size_t kMaxCoordinateTypes = 2; + // Enumeration of the possible access modes. This mirrors the enum // in java.lang.invoke.VarHandle. enum class AccessMode : uint32_t { @@ -95,6 +101,15 @@ class MANAGED VarHandle : public Object { }; constexpr static size_t kNumberOfAccessModes = static_cast<size_t>(AccessMode::kLast) + 1u; + // 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) + }; + // Returns true if the AccessMode specified is a supported operation. bool IsAccessModeSupported(AccessMode accessMode) REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessModesBitMask() & (1u << static_cast<uint32_t>(accessMode))) != 0; @@ -143,6 +158,15 @@ class MANAGED VarHandle : public Object { // VarHandle access method, such as "setOpaque". Returns false otherwise. static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode); + // Returns the AccessModeTemplate for a given mode. + static AccessModeTemplate GetAccessModeTemplate(AccessMode access_mode); + + // Returns the AccessModeTemplate corresponding to a VarHandle accessor intrinsic. + static AccessModeTemplate GetAccessModeTemplateByIntrinsic(Intrinsics ordinal); + + // Returns the number of VarType parameters for an access mode template. + static int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template); + static MemberOffset VarTypeOffset() { return MemberOffset(OFFSETOF_MEMBER(VarHandle, var_type_)); } diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc index bb67a4adb4..5e763ddf92 100644 --- a/runtime/mirror/var_handle_test.cc +++ b/runtime/mirror/var_handle_test.cc @@ -417,6 +417,65 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) { } } +TEST_F(VarHandleTest, AccessModeTemplate) { + EXPECT_EQ(VarHandle::AccessModeTemplate::kGet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGet)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSet)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetVolatile)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSetVolatile)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAcquire)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSetRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetOpaque)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kSetOpaque)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndSet)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndExchange, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndExchange)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndExchange, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndExchangeAcquire)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndExchange, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kCompareAndExchangeRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSetPlain)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSet)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSetAcquire)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kCompareAndSet, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kWeakCompareAndSetRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndSet)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndSetAcquire)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndSetRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseOr)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseOrRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseOrAcquire)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseAnd)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseAndRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseAndAcquire)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseXor)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseXorRelease)); + EXPECT_EQ(VarHandle::AccessModeTemplate::kGetAndUpdate, + VarHandle::GetAccessModeTemplate(VarHandle::AccessMode::kGetAndBitwiseXorAcquire)); +} + TEST_F(VarHandleTest, StaticFieldVarHandle) { Thread * const self = Thread::Current(); ScopedObjectAccess soa(self); |