/*
* 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 <string>
#include <vector>
#include "art_field-inl.h"
#include "class-alloc-inl.h"
#include "class-inl.h"
#include "class_linker-inl.h"
#include "class_loader.h"
#include "class_root-inl.h"
#include "common_runtime_test.h"
#include "handle_scope-inl.h"
#include "jvalue-inl.h"
#include "method_type.h"
#include "object_array-alloc-inl.h"
#include "object_array-inl.h"
#include "reflection.h"
#include "scoped_thread_state_change-inl.h"
namespace art HIDDEN {
namespace mirror {
// Tests for mirror::VarHandle and it's descendents.
class VarHandleTest : public CommonRuntimeTest {
public :
VarHandleTest() {
use_boot_image_ = true ; // Make the Runtime creation cheaper.
}
static ObjPtr<FieldVarHandle> CreateFieldVarHandle(Thread* const self,
ArtField* art_field,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
StackHandleScope<4 > hs(self);
Handle<FieldVarHandle> fvh = hs.NewHandle(
ObjPtr<FieldVarHandle>::DownCast(GetClassRoot<FieldVarHandle>()->AllocObject(self)));
Handle<Class > var_type = hs.NewHandle(art_field->ResolveType());
if (art_field->IsStatic()) {
InitializeVarHandle(fvh.Get(), var_type, access_modes_bit_mask);
} else {
Handle<Class > declaring_type = hs.NewHandle(art_field->GetDeclaringClass());
InitializeVarHandle(fvh.Get(),
var_type,
declaring_type,
access_modes_bit_mask);
}
uintptr_t opaque_field = reinterpret_cast <uintptr_t>(art_field);
fvh->SetField64<false >(FieldVarHandle::ArtFieldOffset(), opaque_field);
return fvh.Get();
}
static ObjPtr<ArrayElementVarHandle> CreateArrayElementVarHandle(Thread* const self,
Handle<Class > array_class,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
StackHandleScope<3 > hs(self);
Handle<ArrayElementVarHandle> vh = hs.NewHandle(
ObjPtr<ArrayElementVarHandle>::DownCast(
GetClassRoot<ArrayElementVarHandle>()->AllocObject(self)));
// Initialize super class fields
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<Class > var_type = hs.NewHandle(array_class->GetComponentType());
Handle<Class > index_type = hs.NewHandle(class_linker->FindPrimitiveClass('I' ));
InitializeVarHandle(vh.Get(), var_type, array_class, index_type, access_modes_bit_mask);
return vh.Get();
}
static ObjPtr<ByteArrayViewVarHandle> CreateByteArrayViewVarHandle(
Thread* const self,
Handle<Class > view_array_class,
bool native_byte_order,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
StackHandleScope<4 > hs(self);
Handle<ByteArrayViewVarHandle> bvh = hs.NewHandle(
ObjPtr<ByteArrayViewVarHandle>::DownCast(
GetClassRoot<ByteArrayViewVarHandle>()->AllocObject(self)));
// Initialize super class fields
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<Class > var_type = hs.NewHandle(view_array_class->GetComponentType());
Handle<Class > index_type = hs.NewHandle(class_linker->FindPrimitiveClass('I' ));
Handle<Class > byte_array_class(hs.NewHandle(GetClassRoot<mirror::ByteArray>()));
InitializeVarHandle(bvh.Get(), var_type, byte_array_class, index_type, access_modes_bit_mask);
bvh->SetFieldBoolean<false >(ByteArrayViewVarHandle::NativeByteOrderOffset(), native_byte_order);
return bvh.Get();
}
static ObjPtr<ByteBufferViewVarHandle> CreateByteBufferViewVarHandle(
Thread* const self,
Handle<Class > view_array_class,
bool native_byte_order,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
StackHandleScope<5 > hs(self);
Handle<ByteBufferViewVarHandle> bvh = hs.NewHandle(
ObjPtr<ByteBufferViewVarHandle>::DownCast(
GetClassRoot<ByteArrayViewVarHandle>()->AllocObject(self)));
// Initialize super class fields
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Handle<Class > var_type = hs.NewHandle(view_array_class->GetComponentType());
Handle<Class > index_type = hs.NewHandle(class_linker->FindPrimitiveClass('I' ));
Handle<Class > byte_buffer_class = hs.NewHandle(
class_linker->FindSystemClass(self, "Ljava/nio/ByteBuffer;" ));
InitializeVarHandle(bvh.Get(), var_type, byte_buffer_class, index_type, access_modes_bit_mask);
bvh->SetFieldBoolean<false >(ByteBufferViewVarHandle::NativeByteOrderOffset(),
native_byte_order);
return bvh.Get();
}
static int32_t AccessModesBitMask(VarHandle::AccessMode mode) {
return 1 << static_cast <int32_t>(mode);
}
template <typename ... Args>
static int32_t AccessModesBitMask(VarHandle::AccessMode first, Args... args) {
return AccessModesBitMask(first) | AccessModesBitMask(args...);
}
ObjPtr<MethodType> MethodTypeOf(const std::string& method_descriptor);
template <typename VH>
bool AccessModeExactMatch(Handle<VH> vh,
VarHandle::AccessMode access_mode,
const char * descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
template <typename VH>
bool AccessModeWithConversionsMatch(Handle<VH> vh,
VarHandle::AccessMode access_mode,
const char * descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
template <typename VH>
bool AccessModeNoMatch(Handle<VH> vh,
VarHandle::AccessMode access_mode,
const char * descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
private :
static void InitializeVarHandle(ObjPtr<VarHandle> vh,
Handle<Class > var_type,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) {
vh->SetFieldObject<false >(VarHandle::VarTypeOffset(), var_type.Get());
vh->SetField32<false >(VarHandle::AccessModesBitMaskOffset(), access_modes_bit_mask);
}
static void InitializeVarHandle(ObjPtr<VarHandle> vh,
Handle<Class > var_type,
Handle<Class > coordinate_type0,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) {
InitializeVarHandle(vh, var_type, access_modes_bit_mask);
vh->SetFieldObject<false >(VarHandle::CoordinateType0Offset(), coordinate_type0.Get());
}
static void InitializeVarHandle(ObjPtr<VarHandle> vh,
Handle<Class > var_type,
Handle<Class > coordinate_type0,
Handle<Class > coordinate_type1,
int32_t access_modes_bit_mask)
REQUIRES_SHARED(Locks::mutator_lock_) {
InitializeVarHandle(vh, var_type, access_modes_bit_mask);
vh->SetFieldObject<false >(VarHandle::CoordinateType0Offset(), coordinate_type0.Get());
vh->SetFieldObject<false >(VarHandle::CoordinateType1Offset(), coordinate_type1.Get());
}
};
// Convenience method for constructing MethodType instances from
// well-formed method descriptors.
ObjPtr<MethodType> VarHandleTest::MethodTypeOf(const std::string& method_descriptor) {
std::vector<std::string> descriptors;
auto it = method_descriptor.cbegin();
if (*it++ != '(' ) {
LOG(FATAL) << "Bad descriptor: " << method_descriptor;
}
bool returnValueSeen = false ;
const char * prefix = "" ;
for (; it != method_descriptor.cend() && !returnValueSeen; ++it) {
switch (*it) {
case ')' :
descriptors.push_back(std::string(++it, method_descriptor.cend()));
returnValueSeen = true ;
break ;
case '[' :
prefix = "[" ;
break ;
case 'Z' :
case 'B' :
case 'C' :
case 'S' :
case 'I' :
case 'J' :
case 'F' :
case 'D' :
descriptors.push_back(prefix + std::string(it, it + 1 ));
prefix = "" ;
break ;
case 'L' : {
auto last = it + 1 ;
while (*last != ';' ) {
++last;
}
descriptors.push_back(prefix + std::string(it, last + 1 ));
prefix = "" ;
it = last;
break ;
}
default :
LOG(FATAL) << "Bad descriptor: " << method_descriptor;
}
}
Thread* const self = Thread::Current();
ScopedObjectAccess soa(self);
StackHandleScope<3 > hs(self);
int ptypes_count = static_cast <int >(descriptors.size()) - 1 ;
ObjPtr<mirror::Class > array_of_class = GetClassRoot<mirror::ObjectArray<mirror::Class >>();
Handle<ObjectArray<Class >> ptypes = hs.NewHandle(
ObjectArray<Class >::Alloc(Thread::Current(), array_of_class, ptypes_count));
Handle<mirror::ClassLoader> boot_class_loader = hs.NewHandle<mirror::ClassLoader>(nullptr);
for (int i = 0 ; i < ptypes_count; ++i) {
ptypes->Set(i, FindClass(descriptors[i].c_str(), boot_class_loader));
}
Handle<Class > rtype = hs.NewHandle(FindClass(descriptors.back().c_str(), boot_class_loader));
return MethodType::Create(self, rtype, ptypes);
}
static bool AccessModeMatch(ObjPtr<VarHandle> vh,
VarHandle::AccessMode access_mode,
ObjPtr<MethodType> method_type,
VarHandle::MatchKind expected_match)
REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetMethodTypeMatchForAccessMode(access_mode, method_type) == expected_match;
}
template <typename VH>
bool VarHandleTest::AccessModeExactMatch(Handle<VH> vh,
VarHandle::AccessMode access_mode,
const char * descriptor) {
ObjPtr<MethodType> method_type = MethodTypeOf(descriptor);
return AccessModeMatch(vh.Get(),
access_mode,
method_type,
VarHandle::MatchKind::kExact);
}
template <typename VH>
bool VarHandleTest::AccessModeWithConversionsMatch(Handle<VH> vh,
VarHandle::AccessMode access_mode,
const char * descriptor) {
ObjPtr<MethodType> method_type = MethodTypeOf(descriptor);
return AccessModeMatch(vh.Get(),
access_mode,
method_type,
VarHandle::MatchKind::kWithConversions);
}
template <typename VH>
bool VarHandleTest::AccessModeNoMatch(Handle<VH> vh,
VarHandle::AccessMode access_mode,
const char * descriptor) {
ObjPtr<MethodType> method_type = MethodTypeOf(descriptor);
return AccessModeMatch(vh.Get(),
access_mode,
method_type,
VarHandle::MatchKind::kNone);
}
TEST_F(VarHandleTest, InstanceFieldVarHandle) {
Thread * const self = Thread::Current();
ScopedObjectAccess soa(self);
ObjPtr<Object> i = BoxPrimitive(Primitive::kPrimInt, JValue::FromPrimitive<int32_t>(37 ));
ArtField* value = i->GetClass()->FindDeclaredInstanceField("value" , "I" );
int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kGet,
VarHandle::AccessMode::kGetAndSet,
VarHandle::AccessMode::kGetAndBitwiseXor);
StackHandleScope<6 > hs(self);
Handle<mirror::FieldVarHandle> fvh(hs.NewHandle(CreateFieldVarHandle(self, value, mask)));
EXPECT_FALSE(fvh.IsNull());
EXPECT_EQ(value, fvh->GetArtField());
// Check access modes
EXPECT_TRUE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetVolatile));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSetVolatile));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSetRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetOpaque));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSetOpaque));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchange));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetPlain));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetRelease));
EXPECT_TRUE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAdd));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOr));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAnd));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndAcquire));
EXPECT_TRUE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXor));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorAcquire));
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;)I" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;)V" ));
EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;)D" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)Z" ));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;I)V" ));
EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;S)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)Z" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)V" ));
EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;II)Ljava/lang/Boolean;" ));
EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;IB)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;II)I" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)I" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;II)V" ));
EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;II)J" ));
EXPECT_TRUE(AccessModeWithConversionsMatch(fvh, access_mode, "(Ljava/lang/Integer;BS)F" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(IIII)V" ));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;I)I" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(Ljava/lang/Integer;I)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Ljava/lang/Integer;I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)S" ));
}
// Check synthesized method types match expected forms.
{
Handle<MethodType> get = hs.NewHandle(MethodTypeOf("(Ljava/lang/Integer;)I" ));
Handle<MethodType> set = hs.NewHandle(MethodTypeOf("(Ljava/lang/Integer;I)V" ));
Handle<MethodType> compareAndSet = hs.NewHandle(MethodTypeOf("(Ljava/lang/Integer;II)Z" ));
Handle<MethodType> compareAndExchange = hs.NewHandle(MethodTypeOf("(Ljava/lang/Integer;II)I" ));
Handle<MethodType> getAndUpdate = hs.NewHandle(MethodTypeOf("(Ljava/lang/Integer;I)I" ));
auto test_mode = [=](VarHandle::AccessMode access_mode, Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) {
return fvh->GetMethodTypeForAccessMode(self, access_mode)->IsExactMatch(method_type.Get());
};
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGet, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSet, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetVolatile, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetVolatile, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAcquire, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetRelease, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetOpaque, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetOpaque, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchange, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeAcquire, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeRelease, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetPlain, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetAcquire, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetRelease, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSet, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAdd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOr, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAnd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXor, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorAcquire, getAndUpdate));
}
}
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);
ObjPtr<Object> i = BoxPrimitive(Primitive::kPrimInt, JValue::FromPrimitive<int32_t>(37 ));
ArtField* value = i->GetClass()->FindDeclaredStaticField("MIN_VALUE" , "I" );
int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kSet,
VarHandle::AccessMode::kGetOpaque,
VarHandle::AccessMode::kGetAndBitwiseAndRelease);
StackHandleScope<6 > hs(self);
Handle<mirror::FieldVarHandle> fvh(hs.NewHandle(CreateFieldVarHandle(self, value, mask)));
EXPECT_FALSE(fvh.IsNull());
EXPECT_EQ(value, fvh->GetArtField());
// Check access modes
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGet));
EXPECT_TRUE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetVolatile));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSetVolatile));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSetRelease));
EXPECT_TRUE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetOpaque));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kSetOpaque));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchange));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetPlain));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSet));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAdd));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOr));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAnd));
EXPECT_TRUE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndAcquire));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXor));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorRelease));
EXPECT_FALSE(fvh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorAcquire));
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "()I" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "()V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)Z" ));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(I)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(F)V" ));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(II)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)Ljava/lang/String;" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "()Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(II)I" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(II)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(ID)I" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)S" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(IIJ)V" ));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(I)I" ));
EXPECT_TRUE(AccessModeExactMatch(fvh, access_mode, "(I)V" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(fvh, access_mode, "(II)V" ));
}
// Check synthesized method types match expected forms.
{
Handle<MethodType> get = hs.NewHandle(MethodTypeOf("()I" ));
Handle<MethodType> set = hs.NewHandle(MethodTypeOf("(I)V" ));
Handle<MethodType> compareAndSet = hs.NewHandle(MethodTypeOf("(II)Z" ));
Handle<MethodType> compareAndExchange = hs.NewHandle(MethodTypeOf("(II)I" ));
Handle<MethodType> getAndUpdate = hs.NewHandle(MethodTypeOf("(I)I" ));
auto test_mode = [=](VarHandle::AccessMode access_mode, Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) {
return fvh->GetMethodTypeForAccessMode(self, access_mode)->IsExactMatch(method_type.Get());
};
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGet, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSet, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetVolatile, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetVolatile, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAcquire, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetRelease, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetOpaque, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetOpaque, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchange, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeAcquire, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeRelease, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetPlain, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetAcquire, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetRelease, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSet, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAdd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOr, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAnd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXor, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorAcquire, getAndUpdate));
}
}
TEST_F(VarHandleTest, ArrayElementVarHandle) {
Thread * const self = Thread::Current();
ScopedObjectAccess soa(self);
StackHandleScope<7 > hs(self);
int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kGet,
VarHandle::AccessMode::kSet,
VarHandle::AccessMode::kGetVolatile,
VarHandle::AccessMode::kSetVolatile,
VarHandle::AccessMode::kGetAcquire,
VarHandle::AccessMode::kSetRelease,
VarHandle::AccessMode::kGetOpaque,
VarHandle::AccessMode::kSetOpaque,
VarHandle::AccessMode::kCompareAndSet,
VarHandle::AccessMode::kCompareAndExchange,
VarHandle::AccessMode::kCompareAndExchangeAcquire,
VarHandle::AccessMode::kCompareAndExchangeRelease,
VarHandle::AccessMode::kWeakCompareAndSetPlain,
VarHandle::AccessMode::kWeakCompareAndSet,
VarHandle::AccessMode::kWeakCompareAndSetAcquire,
VarHandle::AccessMode::kWeakCompareAndSetRelease,
VarHandle::AccessMode::kGetAndSet,
VarHandle::AccessMode::kGetAndSetAcquire,
VarHandle::AccessMode::kGetAndSetRelease,
VarHandle::AccessMode::kGetAndAdd,
VarHandle::AccessMode::kGetAndAddAcquire,
VarHandle::AccessMode::kGetAndAddRelease,
VarHandle::AccessMode::kGetAndBitwiseOr,
VarHandle::AccessMode::kGetAndBitwiseOrRelease,
VarHandle::AccessMode::kGetAndBitwiseOrAcquire,
VarHandle::AccessMode::kGetAndBitwiseAnd,
VarHandle::AccessMode::kGetAndBitwiseAndRelease,
VarHandle::AccessMode::kGetAndBitwiseAndAcquire,
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorRelease,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
Handle<mirror::Class > string_array_class = hs.NewHandle(
GetClassRoot<mirror::ObjectArray<mirror::String>>());
Handle<mirror::ArrayElementVarHandle> vh(
hs.NewHandle(CreateArrayElementVarHandle(self, string_array_class, mask)));
EXPECT_FALSE(vh.IsNull());
// Check access modes
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetVolatile));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetVolatile));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetOpaque));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetOpaque));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchange));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetPlain));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAdd));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOr));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAnd));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXor));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorAcquire));
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;I)Ljava/lang/String;" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;I)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;Ljava/lang/String;)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)Z" ));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;I)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;III)I" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;II)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(III)V" ));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([Ljava/lang/String;ILjava/lang/String;)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(II)V" ));
}
// Check synthesized method types match expected forms.
{
Handle<MethodType> get = hs.NewHandle(MethodTypeOf("([Ljava/lang/String;I)Ljava/lang/String;" ));
Handle<MethodType> set =
hs.NewHandle(MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;)V" ));
Handle<MethodType> compareAndSet =
hs.NewHandle(MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Z" ));
Handle<MethodType> compareAndExchange = hs.NewHandle(MethodTypeOf(
"([Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;" ));
Handle<MethodType> getAndUpdate =
hs.NewHandle(MethodTypeOf("([Ljava/lang/String;ILjava/lang/String;)Ljava/lang/String;" ));
auto test_mode = [=](VarHandle::AccessMode access_mode, Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetMethodTypeForAccessMode(self, access_mode)->IsExactMatch(method_type.Get());
};
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGet, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSet, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetVolatile, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetVolatile, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAcquire, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetRelease, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetOpaque, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetOpaque, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchange, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeAcquire, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeRelease, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetPlain, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetAcquire, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetRelease, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSet, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAdd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOr, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAnd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXor, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorAcquire, getAndUpdate));
}
}
TEST_F(VarHandleTest, ByteArrayViewVarHandle) {
Thread * const self = Thread::Current();
ScopedObjectAccess soa(self);
StackHandleScope<7 > hs(self);
int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kGet,
VarHandle::AccessMode::kGetVolatile,
VarHandle::AccessMode::kGetAcquire,
VarHandle::AccessMode::kGetOpaque,
VarHandle::AccessMode::kCompareAndSet,
VarHandle::AccessMode::kCompareAndExchangeAcquire,
VarHandle::AccessMode::kWeakCompareAndSetPlain,
VarHandle::AccessMode::kWeakCompareAndSetAcquire,
VarHandle::AccessMode::kGetAndSet,
VarHandle::AccessMode::kGetAndSetRelease,
VarHandle::AccessMode::kGetAndAddAcquire,
VarHandle::AccessMode::kGetAndBitwiseOr,
VarHandle::AccessMode::kGetAndBitwiseOrAcquire,
VarHandle::AccessMode::kGetAndBitwiseAndRelease,
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
Handle<Class > char_array_class(hs.NewHandle(GetClassRoot<mirror::CharArray>()));
const bool native_byte_order = true ;
Handle<mirror::ByteArrayViewVarHandle> vh(
hs.NewHandle(CreateByteArrayViewVarHandle(self, char_array_class, native_byte_order, mask)));
EXPECT_FALSE(vh.IsNull());
EXPECT_EQ(native_byte_order, vh->GetNativeByteOrder());
// Check access modes
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGet));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetVolatile));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetVolatile));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetOpaque));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetOpaque));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndSet));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchange));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetPlain));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSet));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetRelease));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAdd));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOr));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAnd));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndRelease));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXor));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorAcquire));
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BI)C" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BI)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BC)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)Z" ));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BIC)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BI)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BI)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BICC)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BIII)I" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BI)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BICC)C" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BICC)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BII)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(III)V" ));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BIC)C" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "([BIC)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "([BIC)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(II)V" ));
}
// Check synthesized method types match expected forms.
{
Handle<MethodType> get = hs.NewHandle(MethodTypeOf("([BI)C" ));
Handle<MethodType> set = hs.NewHandle(MethodTypeOf("([BIC)V" ));
Handle<MethodType> compareAndSet = hs.NewHandle(MethodTypeOf("([BICC)Z" ));
Handle<MethodType> compareAndExchange = hs.NewHandle(MethodTypeOf("([BICC)C" ));
Handle<MethodType> getAndUpdate = hs.NewHandle(MethodTypeOf("([BIC)C" ));
auto test_mode = [=](VarHandle::AccessMode access_mode, Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetMethodTypeForAccessMode(self, access_mode)->IsExactMatch(method_type.Get());
};
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGet, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSet, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetVolatile, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetVolatile, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAcquire, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetRelease, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetOpaque, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetOpaque, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchange, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeAcquire, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeRelease, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetPlain, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetAcquire, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetRelease, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSet, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAdd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOr, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAnd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXor, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorAcquire, getAndUpdate));
}
}
TEST_F(VarHandleTest, ByteBufferViewVarHandle) {
Thread * const self = Thread::Current();
ScopedObjectAccess soa(self);
StackHandleScope<7 > hs(self);
int32_t mask = AccessModesBitMask(VarHandle::AccessMode::kGet,
VarHandle::AccessMode::kGetVolatile,
VarHandle::AccessMode::kGetAcquire,
VarHandle::AccessMode::kGetOpaque,
VarHandle::AccessMode::kCompareAndSet,
VarHandle::AccessMode::kCompareAndExchangeAcquire,
VarHandle::AccessMode::kWeakCompareAndSetPlain,
VarHandle::AccessMode::kWeakCompareAndSetAcquire,
VarHandle::AccessMode::kGetAndSet,
VarHandle::AccessMode::kGetAndSetRelease,
VarHandle::AccessMode::kGetAndAddAcquire,
VarHandle::AccessMode::kGetAndBitwiseOr,
VarHandle::AccessMode::kGetAndBitwiseOrAcquire,
VarHandle::AccessMode::kGetAndBitwiseAndRelease,
VarHandle::AccessMode::kGetAndBitwiseXor,
VarHandle::AccessMode::kGetAndBitwiseXorAcquire);
Handle<Class > double_array_class(hs.NewHandle(GetClassRoot<mirror::DoubleArray>()));
const bool native_byte_order = false ;
Handle<mirror::ByteBufferViewVarHandle> vh(hs.NewHandle(
CreateByteBufferViewVarHandle(self, double_array_class, native_byte_order, mask)));
EXPECT_FALSE(vh.IsNull());
EXPECT_EQ(native_byte_order, vh->GetNativeByteOrder());
// Check access modes
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGet));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetVolatile));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetVolatile));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetOpaque));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kSetOpaque));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndSet));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchange));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kCompareAndExchangeRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetPlain));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSet));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kWeakCompareAndSetRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSet));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndSetRelease));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAdd));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndAddRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOr));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseOrAcquire));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAnd));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndRelease));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseAndAcquire));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXor));
EXPECT_FALSE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorRelease));
EXPECT_TRUE(vh->IsAccessModeSupported(VarHandle::AccessMode::kGetAndBitwiseXorAcquire));
// Check compatibility - "Get" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)D" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;D)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)Z" ));
}
// Check compatibility - "Set" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kSet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndSet" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndSet;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDD)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDI)D" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;I)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Z)V" ));
}
// Check compatibility - "CompareAndExchange" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kCompareAndExchange;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDD)D" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;IDD)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;II)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(III)V" ));
}
// Check compatibility - "GetAndUpdate" pattern
{
const VarHandle::AccessMode access_mode = VarHandle::AccessMode::kGetAndAdd;
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)D" ));
EXPECT_TRUE(AccessModeExactMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)V" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(Ljava/nio/ByteBuffer;ID)Z" ));
EXPECT_TRUE(AccessModeNoMatch(vh, access_mode, "(II)V" ));
}
// Check synthesized method types match expected forms.
{
Handle<MethodType> get = hs.NewHandle(MethodTypeOf("(Ljava/nio/ByteBuffer;I)D" ));
Handle<MethodType> set = hs.NewHandle(MethodTypeOf("(Ljava/nio/ByteBuffer;ID)V" ));
Handle<MethodType> compareAndSet = hs.NewHandle(MethodTypeOf("(Ljava/nio/ByteBuffer;IDD)Z" ));
Handle<MethodType> compareAndExchange =
hs.NewHandle(MethodTypeOf("(Ljava/nio/ByteBuffer;IDD)D" ));
Handle<MethodType> getAndUpdate = hs.NewHandle(MethodTypeOf("(Ljava/nio/ByteBuffer;ID)D" ));
auto test_mode = [=](VarHandle::AccessMode access_mode, Handle<MethodType> method_type)
REQUIRES_SHARED(Locks::mutator_lock_) {
return vh->GetMethodTypeForAccessMode(self, access_mode)->IsExactMatch(method_type.Get());
};
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGet, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSet, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetVolatile, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetVolatile, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAcquire, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetRelease, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetOpaque, get));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kSetOpaque, set));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchange, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeAcquire, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kCompareAndExchangeRelease, compareAndExchange));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetPlain, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSet, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetAcquire, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kWeakCompareAndSetRelease, compareAndSet));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSet, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndSetRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAdd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndAddRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOr, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseOrAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAnd, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseAndAcquire, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXor, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorRelease, getAndUpdate));
EXPECT_TRUE(test_mode(VarHandle::AccessMode::kGetAndBitwiseXorAcquire, getAndUpdate));
}
}
TEST_F(VarHandleTest, GetMethodTypeForAccessMode) {
VarHandle::AccessMode access_mode;
// Invalid access mode names
EXPECT_FALSE(VarHandle::GetAccessModeByMethodName(nullptr, &access_mode));
EXPECT_FALSE(VarHandle::GetAccessModeByMethodName("" , &access_mode));
EXPECT_FALSE(VarHandle::GetAccessModeByMethodName("CompareAndExchange" , &access_mode));
EXPECT_FALSE(VarHandle::GetAccessModeByMethodName("compareAndExchangX" , &access_mode));
// Valid access mode names
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("compareAndExchange" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kCompareAndExchange, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("compareAndExchangeAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kCompareAndExchangeAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("compareAndExchangeRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kCompareAndExchangeRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("compareAndSet" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kCompareAndSet, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("get" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGet, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndAdd" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndAdd, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndAddAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndAddAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndAddRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndAddRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseAnd" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseAnd, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseAndAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseAndAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseAndRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseAndRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseOr" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseOr, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseOrAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseOrAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseOrRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseOrRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseXor" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseXor, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseXorAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseXorAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndBitwiseXorRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndBitwiseXorRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndSet" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndSet, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndSetAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndSetAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getAndSetRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetAndSetRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getOpaque" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetOpaque, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("getVolatile" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kGetVolatile, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("set" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kSet, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("setOpaque" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kSetOpaque, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("setRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kSetRelease, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("setVolatile" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kSetVolatile, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("weakCompareAndSet" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kWeakCompareAndSet, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("weakCompareAndSetAcquire" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kWeakCompareAndSetAcquire, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("weakCompareAndSetPlain" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kWeakCompareAndSetPlain, access_mode);
EXPECT_TRUE(VarHandle::GetAccessModeByMethodName("weakCompareAndSetRelease" , &access_mode));
EXPECT_EQ(VarHandle::AccessMode::kWeakCompareAndSetRelease, access_mode);
}
} // namespace mirror
} // namespace art
Messung V0.5 in Prozent C=93 H=95 G=93
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland