diff options
author | 2017-12-08 11:36:19 +0000 | |
---|---|---|
committer | 2018-02-06 12:51:42 +0000 | |
commit | becc83b59ff703c02198f832dbc3216a0ab8a022 (patch) | |
tree | 38a3061481f01e2dcdc955bd9e9ddb60e0fd5a6f | |
parent | 1e5b3f39ff1776fd8b7d8d7d372347a08d98781b (diff) |
ART: Interpreter support for VarHandle accessors
Add support for invoking VarHandle accessors in the interpreter and
forces code with VarHandles accessor invocations to use the interpreter.
Bug: 65872996
Test: art/test/run-test --host 712
Change-Id: I9ee3ad6aef6a3bc73d90cec0a8e023e5db42b7a2
29 files changed, 9377 insertions, 307 deletions
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc index 19e7f7686d..f7ff15fbfd 100644 --- a/runtime/common_throws.cc +++ b/runtime/common_throws.cc @@ -53,6 +53,11 @@ static void AddReferrerLocation(std::ostream& os, ObjPtr<mirror::Class> referrer } } +static void ThrowException(const char* exception_descriptor) REQUIRES_SHARED(Locks::mutator_lock_) { + Thread* self = Thread::Current(); + self->ThrowNewException(exception_descriptor, nullptr); +} + static void ThrowException(const char* exception_descriptor, ObjPtr<mirror::Class> referrer, const char* fmt, @@ -243,6 +248,11 @@ void ThrowIllegalArgumentException(const char* msg) { ThrowException("Ljava/lang/IllegalArgumentException;", nullptr, msg); } +// IllegalStateException + +void ThrowIllegalStateException(const char* msg) { + ThrowException("Ljava/lang/IllegalStateException;", nullptr, msg); +} // IncompatibleClassChangeError @@ -314,6 +324,13 @@ void ThrowIncompatibleClassChangeErrorForMethodConflict(ArtMethod* method) { ArtMethod::PrettyMethod(method).c_str()).c_str()); } +// IndexOutOfBoundsException + +void ThrowIndexOutOfBoundsException(int index, int length) { + ThrowException("Ljava/lang/IndexOutOfBoundsException;", nullptr, + StringPrintf("length=%d; index=%d", length, index).c_str()); +} + // InternalError void ThrowInternalError(const char* fmt, ...) { @@ -719,6 +736,12 @@ void ThrowNullPointerException(const char* msg) { ThrowException("Ljava/lang/NullPointerException;", nullptr, msg); } +// ReadOnlyBufferException + +void ThrowReadOnlyBufferException() { + Thread::Current()->ThrowNewException("Ljava/nio/ReadOnlyBufferException;", nullptr); +} + // RuntimeException void ThrowRuntimeException(const char* fmt, ...) { @@ -842,6 +865,12 @@ void ThrowStringIndexOutOfBoundsException(int index, int length) { StringPrintf("length=%d; index=%d", length, index).c_str()); } +// UnsupportedOperationException + +void ThrowUnsupportedOperationException() { + ThrowException("Ljava/lang/UnsupportedOperationException;"); +} + // VerifyError void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) { @@ -853,13 +882,13 @@ void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) { // WrongMethodTypeException -void ThrowWrongMethodTypeException(mirror::MethodType* callee_type, - mirror::MethodType* callsite_type) { +void ThrowWrongMethodTypeException(mirror::MethodType* expected_type, + mirror::MethodType* actual_type) { ThrowException("Ljava/lang/invoke/WrongMethodTypeException;", nullptr, StringPrintf("Expected %s but was %s", - callee_type->PrettyDescriptor().c_str(), - callsite_type->PrettyDescriptor().c_str()).c_str()); + expected_type->PrettyDescriptor().c_str(), + actual_type->PrettyDescriptor().c_str()).c_str()); } } // namespace art diff --git a/runtime/common_throws.h b/runtime/common_throws.h index 3512b2b5bf..e9baa4fef0 100644 --- a/runtime/common_throws.h +++ b/runtime/common_throws.h @@ -120,6 +120,11 @@ void ThrowIllegalAccessException(const char* msg) void ThrowIllegalArgumentException(const char* msg) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +// IllegalAccessException + +void ThrowIllegalStateException(const char* msg) + REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + // IncompatibleClassChangeError void ThrowIncompatibleClassChangeError(InvokeType expected_type, @@ -151,6 +156,11 @@ void ThrowIncompatibleClassChangeError(ObjPtr<mirror::Class> referrer, const cha void ThrowIncompatibleClassChangeErrorForMethodConflict(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +// IndexOutOfBoundsException + +void ThrowIndexOutOfBoundsException(int index, int length) + REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + // InternalError void ThrowInternalError(const char* fmt, ...) @@ -223,6 +233,10 @@ void ThrowNullPointerExceptionFromDexPC(bool check_address = false, uintptr_t ad void ThrowNullPointerException(const char* msg) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +// ReadOnlyBufferException + +void ThrowReadOnlyBufferException() REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + // RuntimeException void ThrowRuntimeException(const char* fmt, ...) @@ -244,6 +258,10 @@ void ThrowStackOverflowError(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) void ThrowStringIndexOutOfBoundsException(int index, int length) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; +// UnsupportedOperationException + +void ThrowUnsupportedOperationException() REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; + // VerifyError void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) @@ -251,6 +269,7 @@ void ThrowVerifyError(ObjPtr<mirror::Class> referrer, const char* fmt, ...) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; // WrongMethodTypeException + void ThrowWrongMethodTypeException(mirror::MethodType* callee_type, mirror::MethodType* callsite_type) REQUIRES_SHARED(Locks::mutator_lock_) COLD_ATTR; diff --git a/runtime/dex/dex_instruction.cc b/runtime/dex/dex_instruction.cc index b84791ffae..886218129e 100644 --- a/runtime/dex/dex_instruction.cc +++ b/runtime/dex/dex_instruction.cc @@ -558,4 +558,11 @@ uint32_t VarArgsInstructionOperands::GetOperand(size_t operand_index) const { return operands_[operand_index]; } +uint32_t NoReceiverInstructionOperands::GetOperand(size_t operand_index) const { + DCHECK_LT(GetNumberOfOperands(), inner_->GetNumberOfOperands()); + // The receiver is the first operand and since we're skipping it, we need to + // add 1 to the operand_index. + return inner_->GetOperand(operand_index + 1); +} + } // namespace art diff --git a/runtime/dex/dex_instruction.h b/runtime/dex/dex_instruction.h index 8b1a5ce670..de14ed3c41 100644 --- a/runtime/dex/dex_instruction.h +++ b/runtime/dex/dex_instruction.h @@ -701,7 +701,7 @@ class InstructionOperands { size_t GetNumberOfOperands() const { return num_operands_; } private: - size_t num_operands_; + const size_t num_operands_; DISALLOW_IMPLICIT_CONSTRUCTORS(InstructionOperands); }; @@ -737,6 +737,21 @@ class VarArgsInstructionOperands FINAL : public InstructionOperands { DISALLOW_IMPLICIT_CONSTRUCTORS(VarArgsInstructionOperands); }; +// Class for accessing operands without the receiver by wrapping an +// existing InstructionOperands instance. +class NoReceiverInstructionOperands FINAL : public InstructionOperands { + public: + explicit NoReceiverInstructionOperands(InstructionOperands* inner) + : InstructionOperands(inner->GetNumberOfOperands() - 1), inner_(inner) {} + ~NoReceiverInstructionOperands() {} + uint32_t GetOperand(size_t operand_index) const OVERRIDE; + + private: + const InstructionOperands* const inner_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(NoReceiverInstructionOperands); +}; + } // namespace art #endif // ART_RUNTIME_DEX_DEX_INSTRUCTION_H_ diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 12b8c38bbb..91b2d0e1e3 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -31,6 +31,7 @@ #include "mirror/class.h" #include "mirror/emulated_stack_frame.h" #include "mirror/method_handle_impl-inl.h" +#include "mirror/var_handle.h" #include "reflection-inl.h" #include "reflection.h" #include "stack.h" @@ -723,263 +724,149 @@ bool DoMethodHandleInvoke(Thread* self, } } -static bool UnimplementedSignaturePolymorphicMethod(Thread* self ATTRIBUTE_UNUSED, - ShadowFrame& shadow_frame ATTRIBUTE_UNUSED, - const Instruction* inst ATTRIBUTE_UNUSED, - uint16_t inst_data ATTRIBUTE_UNUSED, - JValue* result ATTRIBUTE_UNUSED) +static bool DoVarHandleInvokeChecked(Thread* self, + Handle<mirror::VarHandle> var_handle, + Handle<mirror::MethodType> callsite_type, + mirror::VarHandle::AccessMode access_mode, + ShadowFrame& shadow_frame, + InstructionOperands* operands, + JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - UNIMPLEMENTED(FATAL) << "TODO(oth): b/65872996"; - return false; -} - -bool DoVarHandleCompareAndExchange(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleCompareAndExchangeAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleCompareAndExchangeRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleCompareAndSet(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGet(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndAdd(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndAddAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndAddRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseAnd(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseAndAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseAndRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseOr(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseOrAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseOrRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseXor(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseXorAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndBitwiseXorRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndSet(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndSetAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetAndSetRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetOpaque(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} - -bool DoVarHandleGetVolatile(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); + // TODO(oth): GetMethodTypeForAccessMode() allocates a MethodType() + // which is only required if we need to convert argument and/or + // return types. + StackHandleScope<1> hs(self); + Handle<mirror::MethodType> accessor_type(hs.NewHandle( + var_handle->GetMethodTypeForAccessMode(self, access_mode))); + const size_t num_vregs = accessor_type->NumberOfVRegs(); + const int num_params = accessor_type->GetPTypes()->GetLength(); + ShadowFrameAllocaUniquePtr accessor_frame = + CREATE_SHADOW_FRAME(num_vregs, nullptr, shadow_frame.GetMethod(), shadow_frame.GetDexPC()); + ShadowFrameGetter getter(shadow_frame, operands); + static const uint32_t kFirstDestinationReg = 0; + ShadowFrameSetter setter(accessor_frame.get(), kFirstDestinationReg); + if (!PerformConversions(self, callsite_type, accessor_type, &getter, &setter, num_params)) { + return false; + } + RangeInstructionOperands accessor_operands(kFirstDestinationReg, + kFirstDestinationReg + num_vregs); + if (!var_handle->Access(access_mode, accessor_frame.get(), &accessor_operands, result)) { + return false; + } + return ConvertReturnValue(callsite_type, accessor_type, result); } -bool DoVarHandleSet(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} +static bool DoVarHandleInvokeCommon(Thread* self, + ShadowFrame& shadow_frame, + const Instruction* inst, + uint16_t inst_data, + JValue* result, + mirror::VarHandle::AccessMode access_mode) + REQUIRES_SHARED(Locks::mutator_lock_) { + // Make sure to check for async exceptions + if (UNLIKELY(self->ObserveAsyncException())) { + return false; + } -bool DoVarHandleSetOpaque(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} + bool is_var_args = inst->HasVarArgs(); + const uint32_t vRegC = is_var_args ? inst->VRegC_45cc() : inst->VRegC_4rcc(); + ObjPtr<mirror::Object> receiver(shadow_frame.GetVRegReference(vRegC)); + if (receiver.IsNull()) { + ThrowNullPointerExceptionFromDexPC(); + return false; + } -bool DoVarHandleSetRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} + StackHandleScope<2> hs(self); + Handle<mirror::VarHandle> var_handle(hs.NewHandle(down_cast<mirror::VarHandle*>(receiver.Ptr()))); + if (!var_handle->IsAccessModeSupported(access_mode)) { + ThrowUnsupportedOperationException(); + return false; + } -bool DoVarHandleSetVolatile(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} + const uint32_t vRegH = is_var_args ? inst->VRegH_45cc() : inst->VRegH_4rcc(); + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + Handle<mirror::MethodType> callsite_type(hs.NewHandle( + class_linker->ResolveMethodType(self, vRegH, shadow_frame.GetMethod()))); + // This implies we couldn't resolve one or more types in this VarHandle. + if (UNLIKELY(callsite_type == nullptr)) { + CHECK(self->IsExceptionPending()); + return false; + } -bool DoVarHandleWeakCompareAndSet(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} + if (!var_handle->IsMethodTypeCompatible(access_mode, callsite_type.Get())) { + ThrowWrongMethodTypeException(var_handle->GetMethodTypeForAccessMode(self, access_mode), + callsite_type.Get()); + return false; + } -bool DoVarHandleWeakCompareAndSetAcquire(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); + if (is_var_args) { + uint32_t args[Instruction::kMaxVarArgRegs]; + inst->GetVarArgs(args, inst_data); + VarArgsInstructionOperands all_operands(args, inst->VRegA_45cc()); + NoReceiverInstructionOperands operands(&all_operands); + return DoVarHandleInvokeChecked(self, + var_handle, + callsite_type, + access_mode, + shadow_frame, + &operands, + result); + } else { + RangeInstructionOperands all_operands(inst->VRegC_4rcc(), inst->VRegA_4rcc()); + NoReceiverInstructionOperands operands(&all_operands); + return DoVarHandleInvokeChecked(self, + var_handle, + callsite_type, + access_mode, + shadow_frame, + &operands, + result); + } } -bool DoVarHandleWeakCompareAndSetPlain(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); +#define DO_VAR_HANDLE_ACCESSOR(_access_mode) \ +bool DoVarHandle ## _access_mode(Thread* self, \ + ShadowFrame& shadow_frame, \ + const Instruction* inst, \ + uint16_t inst_data, \ + JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { \ + const auto access_mode = mirror::VarHandle::AccessMode::k ## _access_mode; \ + return DoVarHandleInvokeCommon(self, shadow_frame, inst, inst_data, result, access_mode); \ } -bool DoVarHandleWeakCompareAndSetRelease(Thread* self, - ShadowFrame& shadow_frame, - const Instruction* inst, - uint16_t inst_data, - JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { - return UnimplementedSignaturePolymorphicMethod(self, shadow_frame, inst, inst_data, result); -} +DO_VAR_HANDLE_ACCESSOR(CompareAndExchange) +DO_VAR_HANDLE_ACCESSOR(CompareAndExchangeAcquire) +DO_VAR_HANDLE_ACCESSOR(CompareAndExchangeRelease) +DO_VAR_HANDLE_ACCESSOR(CompareAndSet) +DO_VAR_HANDLE_ACCESSOR(Get) +DO_VAR_HANDLE_ACCESSOR(GetAcquire) +DO_VAR_HANDLE_ACCESSOR(GetAndAdd) +DO_VAR_HANDLE_ACCESSOR(GetAndAddAcquire) +DO_VAR_HANDLE_ACCESSOR(GetAndAddRelease) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseAnd) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseAndAcquire) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseAndRelease) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseOr) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseOrAcquire) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseOrRelease) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseXor) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseXorAcquire) +DO_VAR_HANDLE_ACCESSOR(GetAndBitwiseXorRelease) +DO_VAR_HANDLE_ACCESSOR(GetAndSet) +DO_VAR_HANDLE_ACCESSOR(GetAndSetAcquire) +DO_VAR_HANDLE_ACCESSOR(GetAndSetRelease) +DO_VAR_HANDLE_ACCESSOR(GetOpaque) +DO_VAR_HANDLE_ACCESSOR(GetVolatile) +DO_VAR_HANDLE_ACCESSOR(Set) +DO_VAR_HANDLE_ACCESSOR(SetOpaque) +DO_VAR_HANDLE_ACCESSOR(SetRelease) +DO_VAR_HANDLE_ACCESSOR(SetVolatile) +DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSet) +DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSetAcquire) +DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSetPlain) +DO_VAR_HANDLE_ACCESSOR(WeakCompareAndSetRelease) + +#undef DO_VAR_HANDLE_ACCESSOR template<bool is_range> bool DoInvokePolymorphic(Thread* self, diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc index 2701ec66a4..9b21e1d9bf 100644 --- a/runtime/method_handles.cc +++ b/runtime/method_handles.cc @@ -346,7 +346,7 @@ inline bool ConvertAndCopyArgumentsFromCallerFrame( return false; } - ShadowFrameGetter getter(operands, caller_frame); + ShadowFrameGetter getter(caller_frame, operands); ShadowFrameSetter setter(callee_frame, first_dest_reg); return PerformConversions<ShadowFrameGetter, ShadowFrameSetter>(self, callsite_type, diff --git a/runtime/method_handles.h b/runtime/method_handles.h index 6ffd1a81fc..3b1bf2ee66 100644 --- a/runtime/method_handles.h +++ b/runtime/method_handles.h @@ -130,8 +130,10 @@ bool PerformConversions(Thread* self, // arguments while performing standard argument conversions. class ShadowFrameGetter { public: - ShadowFrameGetter(const InstructionOperands* const operands, const ShadowFrame& shadow_frame) - : operands_(operands), operand_index_(0), shadow_frame_(shadow_frame) {} + ShadowFrameGetter(const ShadowFrame& shadow_frame, + const InstructionOperands* const operands, + size_t operand_index = 0u) + : shadow_frame_(shadow_frame), operands_(operands), operand_index_(operand_index) {} ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) { return shadow_frame_.GetVReg(Next()); @@ -151,26 +153,24 @@ class ShadowFrameGetter { operand_index_ += 1; return next; } + uint32_t NextLong() { const uint32_t next = operands_->GetOperand(operand_index_); operand_index_ += 2; return next; } - const InstructionOperands* const operands_; - size_t operand_index_; // the next register operand to read from frame const ShadowFrame& shadow_frame_; + const InstructionOperands* const operands_; // the set of register operands to read + size_t operand_index_; // the next register operand to read from frame }; // A convenience class that allows values to be written to a given shadow frame, // starting at location |first_dst_reg|. class ShadowFrameSetter { public: - ShadowFrameSetter(ShadowFrame* shadow_frame, - size_t first_dst_reg) : - shadow_frame_(shadow_frame), - arg_index_(first_dst_reg) { - } + ShadowFrameSetter(ShadowFrame* shadow_frame, size_t first_dst_reg) + : shadow_frame_(shadow_frame), arg_index_(first_dst_reg) {} ALWAYS_INLINE void Set(uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) { shadow_frame_->SetVReg(arg_index_++, value); diff --git a/runtime/mirror/emulated_stack_frame.cc b/runtime/mirror/emulated_stack_frame.cc index 5757992167..5f00c6e9c7 100644 --- a/runtime/mirror/emulated_stack_frame.cc +++ b/runtime/mirror/emulated_stack_frame.cc @@ -183,7 +183,7 @@ mirror::EmulatedStackFrame* EmulatedStackFrame::CreateFromShadowFrameAndArgs( } // Step 4 : Perform argument conversions (if required). - ShadowFrameGetter getter(operands, caller_frame); + ShadowFrameGetter getter(caller_frame, operands); EmulatedStackFrameAccessor setter(references, stack_frame, stack_frame->GetLength()); if (!PerformConversions<ShadowFrameGetter, EmulatedStackFrameAccessor>( self, caller_type, callee_type, &getter, &setter, num_method_params)) { diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index 6e2a07c9e0..6c1cb73282 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -935,6 +935,195 @@ inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier( return success; } +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset, + ObjPtr<Object> old_value, + ObjPtr<Object> new_value) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + if (kVerifyFlags & kVerifyWrites) { + VerifyObject(new_value); + } + if (kVerifyFlags & kVerifyReads) { + VerifyObject(old_value); + } + uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); + uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); + bool success = atomic_addr->CompareAndExchangeStrongSequentiallyConsistent(&old_ref, new_ref); + ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref)); + if (kIsDebugBuild) { + // Ensure caller has done read barrier on the reference field so it's in the to-space. + ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr()); + } + if (kTransactionActive && success) { + Runtime::Current()->RecordWriteFieldReference(this, field_offset, witness_value, true); + } + if (kVerifyFlags & kVerifyReads) { + VerifyObject(witness_value); + } + return witness_value; +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset, + ObjPtr<Object> new_value) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + if (kVerifyFlags & kVerifyWrites) { + VerifyObject(new_value); + } + uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); + uint32_t old_ref = atomic_addr->ExchangeSequentiallyConsistent(new_ref); + ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref)); + if (kIsDebugBuild) { + // Ensure caller has done read barrier on the reference field so it's in the to-space. + ReadBarrier::AssertToSpaceInvariant(old_value.Ptr()); + } + if (kTransactionActive) { + Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); + } + if (kVerifyFlags & kVerifyReads) { + VerifyObject(old_value); + } + return old_value; +} + +template<typename T, VerifyObjectFlags kVerifyFlags> +inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) { + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + T* addr = reinterpret_cast<T*>(raw_addr); + accessor->Access(addr); +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset, + Accessor<uint8_t>* accessor) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kTransactionActive) { + static const bool kIsVolatile = true; + uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset); + Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, old_value, kIsVolatile); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + uint8_t* addr = raw_addr; + accessor->Access(addr); +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset, + Accessor<int8_t>* accessor) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kTransactionActive) { + static const bool kIsVolatile = true; + int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset); + Runtime::Current()->RecordWriteFieldByte(this, field_offset, old_value, kIsVolatile); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + int8_t* addr = reinterpret_cast<int8_t*>(raw_addr); + accessor->Access(addr); +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset, + Accessor<uint16_t>* accessor) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kTransactionActive) { + static const bool kIsVolatile = true; + uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset); + Runtime::Current()->RecordWriteFieldChar(this, field_offset, old_value, kIsVolatile); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr); + accessor->Access(addr); +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset, + Accessor<int16_t>* accessor) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kTransactionActive) { + static const bool kIsVolatile = true; + int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset); + Runtime::Current()->RecordWriteFieldShort(this, field_offset, old_value, kIsVolatile); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + int16_t* addr = reinterpret_cast<int16_t*>(raw_addr); + accessor->Access(addr); +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset, + Accessor<int32_t>* accessor) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kTransactionActive) { + static const bool kIsVolatile = true; + int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset); + Runtime::Current()->RecordWriteField32(this, field_offset, old_value, kIsVolatile); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + int32_t* addr = reinterpret_cast<int32_t*>(raw_addr); + accessor->Access(addr); +} + +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset, + Accessor<int64_t>* accessor) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kTransactionActive) { + static const bool kIsVolatile = true; + int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset); + Runtime::Current()->RecordWriteField64(this, field_offset, old_value, kIsVolatile); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); + accessor->Access(addr); +} + template<bool kIsStatic, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index 25b86a527d..816ac69b29 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -347,6 +347,21 @@ class MANAGED LOCKABLE Object { ObjPtr<Object> old_value, ObjPtr<Object> new_value) REQUIRES_SHARED(Locks::mutator_lock_); + + template<bool kTransactionActive, + bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + ObjPtr<Object> CompareAndExchangeFieldObject(MemberOffset field_offset, + ObjPtr<Object> old_value, + ObjPtr<Object> new_value) + REQUIRES_SHARED(Locks::mutator_lock_); + + template<bool kTransactionActive, + bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + ObjPtr<Object> ExchangeFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) + REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, bool kCheckTransaction = true, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> @@ -592,6 +607,52 @@ class MANAGED LOCKABLE Object { field_offset, reinterpret_cast64<int64_t>(new_value)); } } + + // Base class for accessors used to describe accesses performed by VarHandle methods. + template <typename T> + class Accessor { + public: + virtual ~Accessor() { + static_assert(std::is_arithmetic<T>::value, "unsupported type"); + } + virtual void Access(T* field_address) = 0; + }; + + // Getter method that exposes the raw address of a primitive value-type field to an Accessor + // instance. This are used by VarHandle accessor methods to read fields with a wider range of + // memory orderings than usually required. + template<typename T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Update methods that expose the raw address of a primitive value-type to an Accessor instance + // that will attempt to update the field. These are used by VarHandle accessor methods to + // atomically update fields with a wider range of memory orderings than usually required. + template<bool kTransactionActive, bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void UpdateFieldBooleanViaAccessor(MemberOffset field_offset, Accessor<uint8_t>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void UpdateFieldByteViaAccessor(MemberOffset field_offset, Accessor<int8_t>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void UpdateFieldCharViaAccessor(MemberOffset field_offset, Accessor<uint16_t>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void UpdateFieldShortViaAccessor(MemberOffset field_offset, Accessor<int16_t>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void UpdateField32ViaAccessor(MemberOffset field_offset, Accessor<int32_t>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + void UpdateField64ViaAccessor(MemberOffset field_offset, Accessor<int64_t>* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); + // TODO fix thread safety analysis broken by the use of template. This should be // REQUIRES_SHARED(Locks::mutator_lock_). template <bool kVisitNativeRoots = true, diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc index 3f4a28ce9d..85d06f03fe 100644 --- a/runtime/mirror/var_handle.cc +++ b/runtime/mirror/var_handle.cc @@ -16,14 +16,23 @@ #include "var_handle.h" +#include "array-inl.h" +#include "art_field-inl.h" #include "class-inl.h" #include "class_linker.h" #include "gc_root-inl.h" +#include "jni_internal.h" +#include "jvalue-inl.h" +#include "method_handles.h" #include "method_type.h" +#include "well_known_classes.h" namespace art { namespace mirror { +static constexpr bool kTransactionActive = true; +static constexpr bool kTransactionInactive = !kTransactionActive; + namespace { struct VarHandleAccessorToAccessModeEntry { @@ -158,32 +167,64 @@ AccessModeTemplate GetAccessModeTemplate(VarHandle::AccessMode access_mode) { } } -// Returns the number of parameters associated with an -// AccessModeTemplate and the supplied coordinate types. -int32_t GetParameterCount(AccessModeTemplate access_mode_template, - ObjPtr<Class> coordinateType0, - ObjPtr<Class> coordinateType1) { - int32_t index = 0; - if (!coordinateType0.IsNull()) { - index++; - if (!coordinateType1.IsNull()) { - index++; - } - } - +int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) { switch (access_mode_template) { case AccessModeTemplate::kGet: - return index; + return 0; case AccessModeTemplate::kSet: case AccessModeTemplate::kGetAndUpdate: - return index + 1; + return 1; case AccessModeTemplate::kCompareAndSet: case AccessModeTemplate::kCompareAndExchange: - return index + 2; + 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<Class> coordinateType0, + ObjPtr<Class> 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 @@ -248,6 +289,1123 @@ ObjectArray<Class>* NewArrayOfClasses(Thread* self, int count) return ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, count); } +// Method to insert a read barrier for accessors to reference fields. +inline void ReadBarrierForVarHandleAccess(ObjPtr<Object> 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<uint8_t*>(obj.Ptr()) + field_offset.SizeValue(); + auto field_addr = reinterpret_cast<mirror::HeapReference<mirror::Object>*>(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<mirror::Object, kIsVolatile, kWithReadBarrier, kAlwaysUpdateField>( + 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<Object> 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 <typename T> +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<uint16_t>::ByteSwap(JValue* value) { + value->SetC(BSWAP(value->GetC())); +} + +template <> +void JValueByteSwapper<int16_t>::ByteSwap(JValue* value) { + value->SetS(BSWAP(value->GetS())); +} + +template <> +void JValueByteSwapper<int32_t>::ByteSwap(JValue* value) { + value->SetI(BSWAP(value->GetI())); +} + +template <> +void JValueByteSwapper<int64_t>::ByteSwap(JValue* value) { + value->SetJ(BSWAP(value->GetJ())); +} + +// +// Accessor implementations, shared across all VarHandle types. +// + +template <typename T, std::memory_order MO> +class AtomicGetAccessor : public Object::Accessor<T> { + public: + explicit AtomicGetAccessor(JValue* result) : result_(result) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + StoreResult(atom->load(MO), result_); + } + + private: + JValue* result_; +}; + +template <typename T, std::memory_order MO> +class AtomicSetAccessor : public Object::Accessor<T> { + public: + explicit AtomicSetAccessor(T new_value) : new_value_(new_value) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + atom->store(new_value_, MO); + } + + private: + T new_value_; +}; + +template <typename T> using GetAccessor = AtomicGetAccessor<T, std::memory_order_relaxed>; + +template <typename T> using SetAccessor = AtomicSetAccessor<T, std::memory_order_relaxed>; + +template <typename T> +using GetVolatileAccessor = AtomicGetAccessor<T, std::memory_order_seq_cst>; + +template <typename T> +using SetVolatileAccessor = AtomicSetAccessor<T, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MOS, std::memory_order MOF> +class AtomicStrongCompareAndSetAccessor : public Object::Accessor<T> { + 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<T>* atom = reinterpret_cast<std::atomic<T>*>(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<typename T> +using CompareAndSetAccessor = + AtomicStrongCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MOS, std::memory_order MOF> +class AtomicStrongCompareAndExchangeAccessor : public Object::Accessor<T> { + 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<T>* atom = reinterpret_cast<std::atomic<T>*>(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 <typename T> +using CompareAndExchangeAccessor = + AtomicStrongCompareAndExchangeAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MOS, std::memory_order MOF> +class AtomicWeakCompareAndSetAccessor : public Object::Accessor<T> { + 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<T>* atom = reinterpret_cast<std::atomic<T>*>(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 <typename T> +using WeakCompareAndSetAccessor = + AtomicWeakCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MO> +class AtomicGetAndSetAccessor : public Object::Accessor<T> { + public: + AtomicGetAndSetAccessor(T new_value, JValue* result) : new_value_(new_value), result_(result) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + T old_value = atom->exchange(new_value_, MO); + StoreResult(old_value, result_); + } + + private: + T new_value_; + JValue* result_; +}; + +template <typename T> +using GetAndSetAccessor = AtomicGetAndSetAccessor<T, std::memory_order_seq_cst>; + +template <typename T, bool kIsFloat, std::memory_order MO> +class AtomicGetAndAddOperator { + public: + static T Apply(T* addr, T addend) { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + return atom->fetch_add(addend, MO); + } +}; + +template <typename T, std::memory_order MO> +class AtomicGetAndAddOperator<T, /* kIsFloat */ true, MO> { + public: + static T Apply(T* addr, T addend) { + // c++11 does not have std::atomic<T>::fetch_and_add for floating + // point types, so we effect one with a compare and swap. + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(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 <typename T, std::memory_order MO> +class AtomicGetAndAddAccessor : public Object::Accessor<T> { + public: + AtomicGetAndAddAccessor(T addend, JValue* result) : addend_(addend), result_(result) {} + + void Access(T* addr) OVERRIDE { + constexpr bool kIsFloatingPoint = std::is_floating_point<T>::value; + T old_value = AtomicGetAndAddOperator<T, kIsFloatingPoint, MO>::Apply(addr, addend_); + StoreResult(old_value, result_); + } + + private: + T addend_; + JValue* result_; +}; + +template <typename T> +using GetAndAddAccessor = AtomicGetAndAddAccessor<T, std::memory_order_seq_cst>; + +// 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 <typename T, std::memory_order MO> +class AtomicGetAndAddWithByteSwapAccessor : public Object::Accessor<T> { + public: + AtomicGetAndAddWithByteSwapAccessor(T value, JValue* result) : value_(value), result_(result) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* const atom = reinterpret_cast<std::atomic<T>*>(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<T>::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 <typename T> +using GetAndAddWithByteSwapAccessor = + AtomicGetAndAddWithByteSwapAccessor<T, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MO> +class AtomicGetAndBitwiseOrAccessor : public Object::Accessor<T> { + public: + AtomicGetAndBitwiseOrAccessor(T value, JValue* result) : value_(value), result_(result) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + T old_value = atom->fetch_or(value_, MO); + StoreResult(old_value, result_); + } + + private: + T value_; + JValue* result_; +}; + +template <typename T> +using GetAndBitwiseOrAccessor = AtomicGetAndBitwiseOrAccessor<T, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MO> +class AtomicGetAndBitwiseAndAccessor : public Object::Accessor<T> { + public: + AtomicGetAndBitwiseAndAccessor(T value, JValue* result) : value_(value), result_(result) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + T old_value = atom->fetch_and(value_, MO); + StoreResult(old_value, result_); + } + + private: + T value_; + JValue* result_; +}; + +template <typename T> +using GetAndBitwiseAndAccessor = + AtomicGetAndBitwiseAndAccessor<T, std::memory_order_seq_cst>; + +template <typename T, std::memory_order MO> +class AtomicGetAndBitwiseXorAccessor : public Object::Accessor<T> { + public: + AtomicGetAndBitwiseXorAccessor(T value, JValue* result) : value_(value), result_(result) {} + + void Access(T* addr) OVERRIDE { + std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr); + T old_value = atom->fetch_xor(value_, MO); + StoreResult(old_value, result_); + } + + private: + T value_; + JValue* result_; +}; + +template <typename T> +using GetAndBitwiseXorAccessor = AtomicGetAndBitwiseXorAccessor<T, std::memory_order_seq_cst>; + +// +// 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<TYPE>::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 <typename T, typename U> +class TypeAdaptorAccessor : public Object::Accessor<T> { + public: + explicit TypeAdaptorAccessor(Object::Accessor<U>* inner_accessor) + : inner_accessor_(inner_accessor) {} + + void Access(T* addr) OVERRIDE { + static_assert(sizeof(T) == sizeof(U), "bad conversion"); + inner_accessor_->Access(reinterpret_cast<U*>(addr)); + } + + private: + Object::Accessor<U>* inner_accessor_; +}; + +template <typename T> +class FieldAccessViaAccessor { + public: + typedef Object::Accessor<T> Accessor; + + // Apply an Accessor to get a field in an object. + static void Get(ObjPtr<Object> 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<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_); +}; + +template <> +inline void FieldAccessViaAccessor<float>::Get(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor); + obj->GetPrimitiveFieldViaAccessor(field_offset, &float_to_int_accessor); +} + +template <> +inline void FieldAccessViaAccessor<double>::Get(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor); + obj->GetPrimitiveFieldViaAccessor(field_offset, &double_to_int_accessor); +} + +template <> +void FieldAccessViaAccessor<uint8_t>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateFieldBooleanViaAccessor<kTransactionActive>(field_offset, accessor); + } else { + obj->UpdateFieldBooleanViaAccessor<kTransactionInactive>(field_offset, accessor); + } +} + +template <> +void FieldAccessViaAccessor<int8_t>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateFieldByteViaAccessor<kTransactionActive>(field_offset, accessor); + } else { + obj->UpdateFieldByteViaAccessor<kTransactionInactive>(field_offset, accessor); + } +} + +template <> +void FieldAccessViaAccessor<uint16_t>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateFieldCharViaAccessor<kTransactionActive>(field_offset, accessor); + } else { + obj->UpdateFieldCharViaAccessor<kTransactionInactive>(field_offset, accessor); + } +} + +template <> +void FieldAccessViaAccessor<int16_t>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateFieldShortViaAccessor<kTransactionActive>(field_offset, accessor); + } else { + obj->UpdateFieldShortViaAccessor<kTransactionInactive>(field_offset, accessor); + } +} + +template <> +void FieldAccessViaAccessor<int32_t>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, accessor); + } else { + obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, accessor); + } +} + +template <> +void FieldAccessViaAccessor<int64_t>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, accessor); + } else { + obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, accessor); + } +} + +template <> +void FieldAccessViaAccessor<float>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor); + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, &float_to_int_accessor); + } else { + obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, &float_to_int_accessor); + } +} + +template <> +void FieldAccessViaAccessor<double>::Update(ObjPtr<Object> obj, + MemberOffset field_offset, + Accessor* accessor) + REQUIRES_SHARED(Locks::mutator_lock_) { + TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor); + if (Runtime::Current()->IsActiveTransaction()) { + obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, &double_to_int_accessor); + } else { + obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, &double_to_int_accessor); + } +} + +// Helper class that gets values from a shadow frame with appropriate type coercion. +template <typename T> +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<T>(raw_value); + } +}; + +template <> +int64_t ValueGetter<int64_t>::Get(ShadowFrameGetter* getter) { + return getter->GetLong(); +} + +template <> +float ValueGetter<float>::Get(ShadowFrameGetter* getter) { + uint32_t raw_value = getter->Get(); + return *reinterpret_cast<float*>(&raw_value); +} + +template <> +double ValueGetter<double>::Get(ShadowFrameGetter* getter) { + int64_t raw_value = getter->GetLong(); + return *reinterpret_cast<double*>(&raw_value); +} + +template <> +ObjPtr<Object> ValueGetter<ObjPtr<Object>>::Get(ShadowFrameGetter* getter) { + return getter->GetReference(); +} + +// Class for accessing fields of Object instances +template <typename T> +class FieldAccessor { + public: + static bool Dispatch(VarHandle::AccessMode access_mode, + ObjPtr<Object> obj, + MemberOffset field_offset, + ShadowFrameGetter* getter, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); +}; + +// Dispatch implementation for primitive fields. +template <typename T> +bool FieldAccessor<T>::Dispatch(VarHandle::AccessMode access_mode, + ObjPtr<Object> obj, + MemberOffset field_offset, + ShadowFrameGetter* getter, + JValue* result) { + switch (access_mode) { + case VarHandle::AccessMode::kGet: { + GetAccessor<T> accessor(result); + FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kSet: { + T new_value = ValueGetter<T>::Get(getter); + SetAccessor<T> accessor(new_value); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kGetAcquire: + case VarHandle::AccessMode::kGetOpaque: + case VarHandle::AccessMode::kGetVolatile: { + GetVolatileAccessor<T> accessor(result); + FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kSetOpaque: + case VarHandle::AccessMode::kSetRelease: + case VarHandle::AccessMode::kSetVolatile: { + T new_value = ValueGetter<T>::Get(getter); + SetVolatileAccessor<T> accessor(new_value); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kCompareAndSet: { + T expected_value = ValueGetter<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + CompareAndSetAccessor<T> accessor(expected_value, desired_value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kCompareAndExchange: + case VarHandle::AccessMode::kCompareAndExchangeAcquire: + case VarHandle::AccessMode::kCompareAndExchangeRelease: { + T expected_value = ValueGetter<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result); + FieldAccessViaAccessor<T>::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<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kGetAndSet: + case VarHandle::AccessMode::kGetAndSetAcquire: + case VarHandle::AccessMode::kGetAndSetRelease: { + T new_value = ValueGetter<T>::Get(getter); + GetAndSetAccessor<T> accessor(new_value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kGetAndAdd: + case VarHandle::AccessMode::kGetAndAddAcquire: + case VarHandle::AccessMode::kGetAndAddRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndAddAccessor<T> accessor(value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseOr: + case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: + case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndBitwiseOrAccessor<T> accessor(value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseAnd: + case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: + case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndBitwiseAndAccessor<T> accessor(value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseXor: + case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: + case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndBitwiseXorAccessor<T> accessor(value, result); + FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor); + break; + } + } + return true; +} + +// Dispatch implementation for reference fields. +template <> +bool FieldAccessor<ObjPtr<Object>>::Dispatch(VarHandle::AccessMode access_mode, + ObjPtr<Object> 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<Object>(field_offset), result); + break; + } + case VarHandle::AccessMode::kSet: { + ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter); + if (Runtime::Current()->IsActiveTransaction()) { + obj->SetFieldObject<kTransactionActive>(field_offset, new_value); + } else { + obj->SetFieldObject<kTransactionInactive>(field_offset, new_value); + } + break; + } + case VarHandle::AccessMode::kGetAcquire: + case VarHandle::AccessMode::kGetOpaque: + case VarHandle::AccessMode::kGetVolatile: { + StoreResult(obj->GetFieldObjectVolatile<Object>(field_offset), result); + break; + } + case VarHandle::AccessMode::kSetOpaque: + case VarHandle::AccessMode::kSetRelease: + case VarHandle::AccessMode::kSetVolatile: { + ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter); + if (Runtime::Current()->IsActiveTransaction()) { + obj->SetFieldObjectVolatile<kTransactionActive>(field_offset, new_value); + } else { + obj->SetFieldObjectVolatile<kTransactionInactive>(field_offset, new_value); + } + break; + } + case VarHandle::AccessMode::kCompareAndSet: { + ReadBarrierForVarHandleAccess(obj, field_offset); + ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter); + ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter); + bool cas_result; + if (Runtime::Current()->IsActiveTransaction()) { + cas_result = obj->CasFieldStrongSequentiallyConsistentObject<kTransactionActive>( + field_offset, + expected_value, + desired_value); + } else { + cas_result = obj->CasFieldStrongSequentiallyConsistentObject<kTransactionInactive>( + field_offset, + expected_value, + desired_value); + } + StoreResult(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<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter); + ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter); + bool cas_result; + if (Runtime::Current()->IsActiveTransaction()) { + cas_result = obj->CasFieldWeakSequentiallyConsistentObject<kTransactionActive>( + field_offset, + expected_value, + desired_value); + } else { + cas_result = obj->CasFieldWeakSequentiallyConsistentObject<kTransactionInactive>( + field_offset, + expected_value, + desired_value); + } + StoreResult(cas_result, result); + break; + } + case VarHandle::AccessMode::kCompareAndExchange: + case VarHandle::AccessMode::kCompareAndExchangeAcquire: + case VarHandle::AccessMode::kCompareAndExchangeRelease: { + ReadBarrierForVarHandleAccess(obj, field_offset); + ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter); + ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter); + ObjPtr<Object> witness_value; + if (Runtime::Current()->IsActiveTransaction()) { + witness_value = obj->CompareAndExchangeFieldObject<kTransactionActive>( + field_offset, + expected_value, + desired_value); + } else { + witness_value = obj->CompareAndExchangeFieldObject<kTransactionInactive>( + 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<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter); + ObjPtr<Object> old_value; + if (Runtime::Current()->IsActiveTransaction()) { + old_value = obj->ExchangeFieldObject<kTransactionActive>(field_offset, new_value); + } else { + old_value = obj->ExchangeFieldObject<kTransactionInactive>(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<size_t>(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 <typename T> +class PrimitiveArrayElementAccessor { + public: + static T* GetElementAddress(ObjPtr<Array> target_array, int target_element) + REQUIRES_SHARED(Locks::mutator_lock_) { + auto primitive_array = ObjPtr<PrimitiveArray<T>>::DownCast(target_array); + DCHECK(primitive_array->CheckIsValidIndex(target_element)); + return &primitive_array->GetData()[target_element]; + } + + static bool Dispatch(VarHandle::AccessMode access_mode, + ObjPtr<Array> 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<T> accessor(result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kSet: { + T new_value = ValueGetter<T>::Get(getter); + SetAccessor<T> accessor(new_value); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAcquire: + case VarHandle::AccessMode::kGetOpaque: + case VarHandle::AccessMode::kGetVolatile: { + GetVolatileAccessor<T> accessor(result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kSetOpaque: + case VarHandle::AccessMode::kSetRelease: + case VarHandle::AccessMode::kSetVolatile: { + T new_value = ValueGetter<T>::Get(getter); + SetVolatileAccessor<T> accessor(new_value); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kCompareAndSet: { + T expected_value = ValueGetter<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + CompareAndSetAccessor<T> 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<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + CompareAndExchangeAccessor<T> 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<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAndSet: + case VarHandle::AccessMode::kGetAndSetAcquire: + case VarHandle::AccessMode::kGetAndSetRelease: { + T new_value = ValueGetter<T>::Get(getter); + GetAndSetAccessor<T> accessor(new_value, result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAndAdd: + case VarHandle::AccessMode::kGetAndAddAcquire: + case VarHandle::AccessMode::kGetAndAddRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndAddAccessor<T> accessor(value, result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseOr: + case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: + case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndBitwiseOrAccessor<T> accessor(value, result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseAnd: + case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: + case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndBitwiseAndAccessor<T> accessor(value, result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseXor: + case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: + case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { + T value = ValueGetter<T>::Get(getter); + GetAndBitwiseXorAccessor<T> accessor(value, result); + accessor.Access(element_address); + break; + } + } + return true; + } +}; + +// Class for accessing primitive array elements. +template <typename T> +class ByteArrayViewAccessor { + public: + static inline bool IsAccessAligned(int8_t* data, int data_index) { + static_assert(IsPowerOfTwo(sizeof(T)), "unexpected size"); + static_assert(std::is_arithmetic<T>::value, "unexpected type"); + uintptr_t alignment_mask = sizeof(T) - 1; + uintptr_t address = reinterpret_cast<uintptr_t>(data + data_index); + return (address & alignment_mask) == 0; + } + + static inline void MaybeByteSwap(bool byte_swap, T* const value) { + if (byte_swap) { + *value = BSWAP(*value); + } + } + + static bool Dispatch(const VarHandle::AccessMode access_mode, + int8_t* const data, + const int data_index, + const bool byte_swap, + ShadowFrameGetter* const getter, + JValue* const result) + REQUIRES_SHARED(Locks::mutator_lock_) { + const bool is_aligned = IsAccessAligned(data, data_index); + if (!is_aligned) { + switch (access_mode) { + case VarHandle::AccessMode::kGet: { + T value; + memcpy(&value, data + data_index, sizeof(T)); + MaybeByteSwap(byte_swap, &value); + StoreResult(value, result); + return true; + } + case VarHandle::AccessMode::kSet: { + T new_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &new_value); + memcpy(data + data_index, &new_value, sizeof(T)); + return true; + } + default: + // No other access modes support unaligned access. + ThrowIllegalStateException("Unaligned access not supported"); + return false; + } + } + + T* const element_address = reinterpret_cast<T*>(data + data_index); + CHECK(IsAccessAligned(reinterpret_cast<int8_t*>(element_address), 0)); + switch (access_mode) { + case VarHandle::AccessMode::kGet: { + GetAccessor<T> accessor(result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + case VarHandle::AccessMode::kSet: { + T new_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &new_value); + SetAccessor<T> accessor(new_value); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAcquire: + case VarHandle::AccessMode::kGetOpaque: + case VarHandle::AccessMode::kGetVolatile: { + GetVolatileAccessor<T> accessor(result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + case VarHandle::AccessMode::kSetOpaque: + case VarHandle::AccessMode::kSetRelease: + case VarHandle::AccessMode::kSetVolatile: { + T new_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &new_value); + SetVolatileAccessor<T> accessor(new_value); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kCompareAndSet: { + T expected_value = ValueGetter<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &expected_value); + MaybeByteSwap(byte_swap, &desired_value); + CompareAndSetAccessor<T> 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<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &expected_value); + MaybeByteSwap(byte_swap, &desired_value); + CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + case VarHandle::AccessMode::kWeakCompareAndSet: + case VarHandle::AccessMode::kWeakCompareAndSetAcquire: + case VarHandle::AccessMode::kWeakCompareAndSetPlain: + case VarHandle::AccessMode::kWeakCompareAndSetRelease: { + T expected_value = ValueGetter<T>::Get(getter); + T desired_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &expected_value); + MaybeByteSwap(byte_swap, &desired_value); + WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result); + accessor.Access(element_address); + break; + } + case VarHandle::AccessMode::kGetAndSet: + case VarHandle::AccessMode::kGetAndSetAcquire: + case VarHandle::AccessMode::kGetAndSetRelease: { + T new_value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &new_value); + GetAndSetAccessor<T> accessor(new_value, result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + case VarHandle::AccessMode::kGetAndAdd: + case VarHandle::AccessMode::kGetAndAddAcquire: + case VarHandle::AccessMode::kGetAndAddRelease: { + T value = ValueGetter<T>::Get(getter); + if (byte_swap) { + GetAndAddWithByteSwapAccessor<T> accessor(value, result); + accessor.Access(element_address); + } else { + GetAndAddAccessor<T> accessor(value, result); + accessor.Access(element_address); + } + break; + } + case VarHandle::AccessMode::kGetAndBitwiseOr: + case VarHandle::AccessMode::kGetAndBitwiseOrAcquire: + case VarHandle::AccessMode::kGetAndBitwiseOrRelease: { + T value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &value); + GetAndBitwiseOrAccessor<T> accessor(value, result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseAnd: + case VarHandle::AccessMode::kGetAndBitwiseAndAcquire: + case VarHandle::AccessMode::kGetAndBitwiseAndRelease: { + T value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &value); + GetAndBitwiseAndAccessor<T> accessor(value, result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + case VarHandle::AccessMode::kGetAndBitwiseXor: + case VarHandle::AccessMode::kGetAndBitwiseXorAcquire: + case VarHandle::AccessMode::kGetAndBitwiseXorRelease: { + T value = ValueGetter<T>::Get(getter); + MaybeByteSwap(byte_swap, &value); + GetAndBitwiseXorAccessor<T> accessor(value, result); + accessor.Access(element_address); + JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result); + break; + } + } + return true; + } +}; + } // namespace Class* VarHandle::GetVarType() { @@ -267,35 +1425,38 @@ int32_t VarHandle::GetAccessModesBitMask() { } bool VarHandle::IsMethodTypeCompatible(AccessMode access_mode, MethodType* method_type) { - ScopedAssertNoThreadSuspension ants(__FUNCTION__); - + StackHandleScope<3> hs(Thread::Current()); + Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType())); + Handle<VarHandle> vh(hs.NewHandle(this)); + Handle<Class> var_type(hs.NewHandle(vh->GetVarType())); AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode); - // Check return types first. - ObjPtr<Class> var_type = GetVarType(); - ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type); - ObjPtr<Class> void_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'); - ObjPtr<Class> mt_rtype = method_type->GetRType(); - - // If the mt_rtype is void, the result of the operation will be discarded (okay). - if (mt_rtype != void_type && mt_rtype != vh_rtype) { - return false; + + // Check return type first. + if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) { + // The result of the operation will be discarded. The return type + // of the VarHandle is immaterial. + } else { + ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get())); + if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) { + return false; + } } // Check the number of parameters matches. ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters]; const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes, access_mode_template, - var_type, + var_type.Get(), GetCoordinateType0(), GetCoordinateType1()); if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) { return false; } - // Check the parameter types match. + // Check the parameter types are compatible. ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes(); for (int32_t i = 0; i < vh_ptypes_count; ++i) { - if (mt_ptypes->Get(i) != vh_ptypes[i].Ptr()) { + if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) { return false; } } @@ -311,8 +1472,9 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self, StackHandleScope<3> hs(self); Handle<VarHandle> vh = hs.NewHandle(var_handle); Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType())); - const int32_t ptypes_count = - GetParameterCount(access_mode_template, vh->GetCoordinateType0(), vh->GetCoordinateType1()); + const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, + vh->GetCoordinateType0(), + vh->GetCoordinateType1()); Handle<ObjectArray<Class>> ptypes = hs.NewHandle(NewArrayOfClasses(self, ptypes_count)); if (ptypes == nullptr) { return nullptr; @@ -334,6 +1496,29 @@ MethodType* VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode acces return GetMethodTypeForAccessMode(self, this, access_mode); } +bool VarHandle::Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) { + Class* klass = GetClass(); + if (klass == FieldVarHandle::StaticClass()) { + auto vh = reinterpret_cast<FieldVarHandle*>(this); + return vh->Access(access_mode, shadow_frame, operands, result); + } else if (klass == ArrayElementVarHandle::StaticClass()) { + auto vh = reinterpret_cast<ArrayElementVarHandle*>(this); + return vh->Access(access_mode, shadow_frame, operands, result); + } else if (klass == ByteArrayViewVarHandle::StaticClass()) { + auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this); + return vh->Access(access_mode, shadow_frame, operands, result); + } else if (klass == ByteBufferViewVarHandle::StaticClass()) { + auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this); + return vh->Access(access_mode, shadow_frame, operands, result); + } else { + LOG(FATAL) << "Unknown varhandle kind"; + UNREACHABLE(); + } +} + const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) { AccessMode access_mode; if (!GetAccessModeByMethodName(accessor_name, &access_mode)) { @@ -369,6 +1554,10 @@ bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* a return true; } +Class* VarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { + return static_class_.Read(); +} + void VarHandle::SetClass(Class* klass) { CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass; CHECK(klass != nullptr); @@ -391,6 +1580,57 @@ ArtField* FieldVarHandle::GetField() { return reinterpret_cast<ArtField*>(opaque_field); } +bool FieldVarHandle::Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) { + ShadowFrameGetter getter(*shadow_frame, operands); + ArtField* field = GetField(); + ObjPtr<Object> obj; + if (field->IsStatic()) { + DCHECK_LE(operands->GetNumberOfOperands(), + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u)); + obj = field->GetDeclaringClass(); + } else { + DCHECK_GE(operands->GetNumberOfOperands(), 1u); + DCHECK_LE(operands->GetNumberOfOperands(), + 1u + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u)); + obj = getter.GetReference(); + if (obj.IsNull()) { + ThrowNullPointerExceptionForCoordinate(); + return false; + } + } + DCHECK(!obj.IsNull()); + + const MemberOffset offset = field->GetOffset(); + const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); + switch (primitive_type) { + case Primitive::Type::kPrimNot: + return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimBoolean: + return FieldAccessor<uint8_t>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimByte: + return FieldAccessor<int8_t>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimChar: + return FieldAccessor<uint16_t>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimShort: + return FieldAccessor<int16_t>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimInt: + return FieldAccessor<int32_t>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimFloat: + return FieldAccessor<float>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimLong: + return FieldAccessor<int64_t>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimDouble: + return FieldAccessor<double>::Dispatch(access_mode, obj, offset, &getter, result); + case Primitive::kPrimVoid: + break; + } + LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; + UNREACHABLE(); +} + Class* FieldVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { return static_class_.Read(); } @@ -412,6 +1652,94 @@ void FieldVarHandle::VisitRoots(RootVisitor* visitor) { GcRoot<Class> FieldVarHandle::static_class_; +bool ArrayElementVarHandle::Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) { + ShadowFrameGetter getter(*shadow_frame, operands); + + // The target array is the first co-ordinate type preceeding var type arguments. + ObjPtr<Object> raw_array(getter.GetReference()); + if (raw_array == nullptr) { + ThrowNullPointerExceptionForCoordinate(); + return false; + } + + ObjPtr<Array> target_array(raw_array->AsArray()); + + // The target array element is the second co-ordinate type preceeding var type arguments. + const int target_element = getter.Get(); + if (!target_array->CheckIsValidIndex(target_element)) { + DCHECK(Thread::Current()->IsExceptionPending()); + return false; + } + + const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); + switch (primitive_type) { + case Primitive::Type::kPrimNot: { + MemberOffset target_element_offset = + target_array->AsObjectArray<Object>()->OffsetOfElement(target_element); + return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, + target_array, + target_element_offset, + &getter, + result); + } + case Primitive::Type::kPrimBoolean: + return PrimitiveArrayElementAccessor<uint8_t>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimByte: + return PrimitiveArrayElementAccessor<int8_t>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimChar: + return PrimitiveArrayElementAccessor<uint16_t>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimShort: + return PrimitiveArrayElementAccessor<int16_t>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimInt: + return PrimitiveArrayElementAccessor<int32_t>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimLong: + return PrimitiveArrayElementAccessor<int64_t>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimFloat: + return PrimitiveArrayElementAccessor<float>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimDouble: + return PrimitiveArrayElementAccessor<double>::Dispatch(access_mode, + target_array, + target_element, + &getter, + result); + case Primitive::Type::kPrimVoid: + break; + } + LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; + UNREACHABLE(); +} + Class* ArrayElementVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { return static_class_.Read(); } @@ -437,6 +1765,90 @@ bool ByteArrayViewVarHandle::GetNativeByteOrder() { return GetFieldBoolean(NativeByteOrderOffset()); } +bool ByteArrayViewVarHandle::Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) { + ShadowFrameGetter getter(*shadow_frame, operands); + + // The byte array is the first co-ordinate type preceeding var type arguments. + ObjPtr<Object> raw_byte_array(getter.GetReference()); + if (raw_byte_array == nullptr) { + ThrowNullPointerExceptionForCoordinate(); + return false; + } + + ObjPtr<ByteArray> byte_array(raw_byte_array->AsByteArray()); + + // The offset in the byte array element is the second co-ordinate type. + const int32_t data_offset = getter.Get(); + + // Bounds check requested access. + const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); + if (!CheckElementIndex(primitive_type, data_offset, byte_array->GetLength())) { + return false; + } + + int8_t* const data = byte_array->GetData(); + bool byte_swap = !GetNativeByteOrder(); + switch (primitive_type) { + case Primitive::Type::kPrimNot: + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimVoid: + // These are not supported for byte array views and not instantiable. + break; + case Primitive::kPrimChar: + return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode, + data, + data_offset, + byte_swap, + &getter, + result); + case Primitive::kPrimShort: + return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode, + data, + data_offset, + byte_swap, + &getter, + result); + case Primitive::kPrimInt: + return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, + data, + data_offset, + byte_swap, + &getter, + result); + case Primitive::kPrimFloat: + // Treated as a bitwise representation. See javadoc comments for + // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). + return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, + data, + data_offset, + byte_swap, + &getter, + result); + case Primitive::kPrimLong: + return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, + data, + data_offset, + byte_swap, + &getter, + result); + case Primitive::kPrimDouble: + // Treated as a bitwise representation. See javadoc comments for + // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). + return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, + data, + data_offset, + byte_swap, + &getter, + result); + } + LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; + UNREACHABLE(); +} + Class* ByteArrayViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { return static_class_.Read(); } @@ -462,6 +1874,122 @@ bool ByteBufferViewVarHandle::GetNativeByteOrder() { return GetFieldBoolean(NativeByteOrderOffset()); } +bool ByteBufferViewVarHandle::Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) { + ShadowFrameGetter getter(*shadow_frame, operands); + + // The byte buffer is the first co-ordinate argument preceeding var type arguments. + ObjPtr<Object> byte_buffer(getter.GetReference()); + if (byte_buffer == nullptr) { + ThrowNullPointerExceptionForCoordinate(); + return false; + } + + // The byte index for access is the second co-ordinate + // argument. This is relative to the offset field of the ByteBuffer. + const int32_t byte_index = getter.Get(); + + // Check access_mode is compatible with ByteBuffer's read-only property. + bool is_read_only = byte_buffer->GetFieldBoolean( + GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_isReadOnly)); + if (is_read_only && !IsReadOnlyAccessMode(access_mode)) { + ThrowReadOnlyBufferException(); + return false; + } + + // The native_address is only set for ByteBuffer instances backed by native memory. + const int64_t native_address = + byte_buffer->GetField64(GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_address)); + + // Determine offset and limit for accesses. + int32_t byte_buffer_offset; + if (native_address == 0l) { + // Accessing a heap allocated byte buffer. + byte_buffer_offset = byte_buffer->GetField32( + GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_offset)); + } else { + // Accessing direct memory. + byte_buffer_offset = 0; + } + const int32_t byte_buffer_limit = byte_buffer->GetField32( + GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_limit)); + + const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType(); + if (!CheckElementIndex(primitive_type, byte_index, byte_buffer_offset, byte_buffer_limit)) { + return false; + } + const int32_t checked_offset32 = byte_buffer_offset + byte_index; + + int8_t* data; + if (native_address == 0) { + ObjPtr<ByteArray> heap_byte_array = byte_buffer->GetFieldObject<ByteArray>( + GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_hb)); + data = heap_byte_array->GetData(); + } else { + data = reinterpret_cast<int8_t*>(static_cast<uint32_t>(native_address)); + } + + bool byte_swap = !GetNativeByteOrder(); + switch (primitive_type) { + case Primitive::kPrimChar: + return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode, + data, + checked_offset32, + byte_swap, + &getter, + result); + case Primitive::kPrimShort: + return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode, + data, + checked_offset32, + byte_swap, + &getter, + result); + case Primitive::kPrimInt: + return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, + data, + checked_offset32, + byte_swap, + &getter, + result); + case Primitive::kPrimFloat: + // Treated as a bitwise representation. See javadoc comments for + // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). + return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode, + data, + checked_offset32, + byte_swap, + &getter, + result); + case Primitive::kPrimLong: + return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, + data, + checked_offset32, + byte_swap, + &getter, + result); + case Primitive::kPrimDouble: + // Treated as a bitwise representation. See javadoc comments for + // java.lang.invoke.MethodHandles.byteArrayViewVarHandle(). + return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode, + data, + checked_offset32, + byte_swap, + &getter, + result); + case Primitive::Type::kPrimNot: + case Primitive::kPrimBoolean: + case Primitive::kPrimByte: + case Primitive::kPrimVoid: + // These are not supported for byte array views and not instantiable. + break; + } + LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type; + UNREACHABLE(); +} + Class* ByteBufferViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { return static_class_.Read(); } diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h index 7b48669bba..6565af7f06 100644 --- a/runtime/mirror/var_handle.h +++ b/runtime/mirror/var_handle.h @@ -18,18 +18,24 @@ #define ART_RUNTIME_MIRROR_VAR_HANDLE_H_ #include "handle.h" +#include "interpreter/shadow_frame.h" #include "gc_root.h" +#include "jvalue.h" #include "object.h" namespace art { template<class T> class Handle; +class InstructionOperands; + struct VarHandleOffsets; struct FieldVarHandleOffsets; struct ArrayElementVarHandleOffsets; struct ByteArrayViewVarHandleOffsets; struct ByteBufferViewVarHandleOffsets; +class ShadowFrameGetter; + namespace mirror { class MethodType; @@ -44,6 +50,10 @@ class MANAGED VarHandle : public Object { // (array, index, old, new). static constexpr int kMaxAccessorParameters = 4; + // The maximum number of VarType parameters a VarHandle accessor + // method can take. + static constexpr size_t kMaxVarTypeParameters = 2; + // Enumeration of the possible access modes. This mirrors the enum // in java.lang.invoke.VarHandle. enum class AccessMode : uint32_t { @@ -101,11 +111,16 @@ class MANAGED VarHandle : public Object { // supported operation so the MethodType can be used when raising a // WrongMethodTypeException exception. MethodType* GetMethodTypeForAccessMode(Thread* self, AccessMode accessMode) - REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + REQUIRES_SHARED(Locks::mutator_lock_); - static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) { - return static_class_.Read(); - } + bool Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); + + // Gets the variable type that is operated on by this VarHandle instance. + Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_); // Gets the return type descriptor for a named accessor method, // nullptr if accessor_method is not supported. @@ -115,12 +130,13 @@ class MANAGED VarHandle : public Object { // VarHandle access method, such as "setOpaque". Returns false otherwise. static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode); + + static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); private: - Class* GetVarType() REQUIRES_SHARED(Locks::mutator_lock_); Class* GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_); Class* GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_); int32_t GetAccessModesBitMask() REQUIRES_SHARED(Locks::mutator_lock_); @@ -163,6 +179,12 @@ class MANAGED VarHandle : public Object { // The corresponding managed class in libart java.lang.invoke.FieldVarHandle. class MANAGED FieldVarHandle : public VarHandle { public: + bool Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); + ArtField* GetField() REQUIRES_SHARED(Locks::mutator_lock_); static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); @@ -190,6 +212,12 @@ class MANAGED FieldVarHandle : public VarHandle { // The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle. class MANAGED ArrayElementVarHandle : public VarHandle { public: + bool Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); + static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_); @@ -207,6 +235,12 @@ class MANAGED ArrayElementVarHandle : public VarHandle { // The corresponding managed class in libart java.lang.invoke.ByteArrayViewVarHandle. class MANAGED ByteArrayViewVarHandle : public VarHandle { public: + bool Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); + bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_); static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); @@ -234,10 +268,13 @@ class MANAGED ByteArrayViewVarHandle : public VarHandle { // The corresponding managed class in libart java.lang.invoke.ByteBufferViewVarHandle. class MANAGED ByteBufferViewVarHandle : public VarHandle { public: - bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_); + bool Access(AccessMode access_mode, + ShadowFrame* shadow_frame, + InstructionOperands* operands, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); - static ByteBufferViewVarHandle* Create(Thread* const self, bool native_byte_order) - REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_); static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_); static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_); @@ -245,6 +282,21 @@ class MANAGED ByteBufferViewVarHandle : public VarHandle { static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); private: + bool AccessHeapBuffer(AccessMode access_mode, + ObjPtr<Object> byte_buffer, + int buffer_offset, + ObjPtr<ByteArray> heap_byte_array, + ShadowFrameGetter* getter, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); + + bool AccessFixedMemory(AccessMode access_mode, + ObjPtr<Object> byte_buffer, + int buffer_offset, + ShadowFrameGetter* getter, + JValue* result) + REQUIRES_SHARED(Locks::mutator_lock_); + static MemberOffset NativeByteOrderOffset() { return MemberOffset(OFFSETOF_MEMBER(ByteBufferViewVarHandle, native_byte_order_)); } diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc index e844fd4436..d9fa07f207 100644 --- a/runtime/mirror/var_handle_test.cc +++ b/runtime/mirror/var_handle_test.cc @@ -327,7 +327,7 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) { EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)I"))); EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;II)V"))); EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)Z"))); - EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V"))); + EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(IIII)V"))); } // Check compatibility - "GetAndUpdate" pattern @@ -336,7 +336,7 @@ TEST_F(VarHandleTest, InstanceFieldVarHandle) { EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)I"))); EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)V"))); EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(Ljava/lang/Integer;I)Z"))); - EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V"))); + EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)S"))); } // Check synthesized method types match expected forms. @@ -461,8 +461,8 @@ TEST_F(VarHandleTest, StaticFieldVarHandle) { EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)I"))); EXPECT_TRUE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)V"))); EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(ID)I"))); - EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)D"))); - EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(III)V"))); + EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(II)S"))); + EXPECT_FALSE(fvh->IsMethodTypeCompatible(access_mode, MethodTypeOf("(IIJ)V"))); } // Check compatibility - "GetAndUpdate" pattern diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index afb3224944..3e9dfd18d7 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -4432,6 +4432,8 @@ bool MethodVerifier::CheckSignaturePolymorphicMethod(ArtMethod* method) { expected_return_descriptor = mirror::MethodHandle::GetReturnTypeDescriptor(method_name); } else if (klass == mirror::VarHandle::StaticClass()) { expected_return_descriptor = mirror::VarHandle::GetReturnTypeDescriptor(method_name); + // TODO: add compiler support for VarHandle accessor methods (b/71781600) + Fail(VERIFY_ERROR_FORCE_INTERPRETER); } else { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Signature polymorphic method in unsuppported class: " << klass->PrettyDescriptor(); diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 5fe10f5c12..902c3b84b5 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -72,6 +72,7 @@ jclass WellKnownClasses::java_lang_System; jclass WellKnownClasses::java_lang_Thread; jclass WellKnownClasses::java_lang_ThreadGroup; jclass WellKnownClasses::java_lang_Throwable; +jclass WellKnownClasses::java_nio_ByteBuffer; jclass WellKnownClasses::java_nio_DirectByteBuffer; jclass WellKnownClasses::java_util_ArrayList; jclass WellKnownClasses::java_util_Collections; @@ -142,6 +143,11 @@ jfieldID WellKnownClasses::java_lang_Throwable_stackState; jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions; jfieldID WellKnownClasses::java_lang_reflect_Executable_artMethod; jfieldID WellKnownClasses::java_lang_reflect_Proxy_h; +jfieldID WellKnownClasses::java_nio_ByteBuffer_address; +jfieldID WellKnownClasses::java_nio_ByteBuffer_hb; +jfieldID WellKnownClasses::java_nio_ByteBuffer_isReadOnly; +jfieldID WellKnownClasses::java_nio_ByteBuffer_limit; +jfieldID WellKnownClasses::java_nio_ByteBuffer_offset; jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity; jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress; jfieldID WellKnownClasses::java_util_ArrayList_array; @@ -318,6 +324,7 @@ void WellKnownClasses::Init(JNIEnv* env) { java_lang_Thread = CacheClass(env, "java/lang/Thread"); java_lang_ThreadGroup = CacheClass(env, "java/lang/ThreadGroup"); java_lang_Throwable = CacheClass(env, "java/lang/Throwable"); + java_nio_ByteBuffer = CacheClass(env, "java/nio/ByteBuffer"); java_nio_DirectByteBuffer = CacheClass(env, "java/nio/DirectByteBuffer"); java_util_ArrayList = CacheClass(env, "java/util/ArrayList"); java_util_Collections = CacheClass(env, "java/util/Collections"); @@ -379,6 +386,11 @@ void WellKnownClasses::Init(JNIEnv* env) { java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "backtrace", "Ljava/lang/Object;"); java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;"); java_lang_reflect_Executable_artMethod = CacheField(env, java_lang_reflect_Executable, false, "artMethod", "J"); + java_nio_ByteBuffer_address = CacheField(env, java_nio_ByteBuffer, false, "address", "J"); + java_nio_ByteBuffer_hb = CacheField(env, java_nio_ByteBuffer, false, "hb", "[B"); + java_nio_ByteBuffer_isReadOnly = CacheField(env, java_nio_ByteBuffer, false, "isReadOnly", "Z"); + java_nio_ByteBuffer_limit = CacheField(env, java_nio_ByteBuffer, false, "limit", "I"); + java_nio_ByteBuffer_offset = CacheField(env, java_nio_ByteBuffer, false, "offset", "I"); java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I"); java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "address", "J"); java_util_ArrayList_array = CacheField(env, java_util_ArrayList, false, "elementData", "[Ljava/lang/Object;"); @@ -462,6 +474,7 @@ void WellKnownClasses::Clear() { java_lang_Throwable = nullptr; java_util_ArrayList = nullptr; java_util_Collections = nullptr; + java_nio_ByteBuffer = nullptr; java_nio_DirectByteBuffer = nullptr; libcore_reflect_AnnotationFactory = nullptr; libcore_reflect_AnnotationMember = nullptr; @@ -530,6 +543,11 @@ void WellKnownClasses::Clear() { java_lang_Throwable_stackTrace = nullptr; java_lang_Throwable_stackState = nullptr; java_lang_Throwable_suppressedExceptions = nullptr; + java_nio_ByteBuffer_address = nullptr; + java_nio_ByteBuffer_hb = nullptr; + java_nio_ByteBuffer_isReadOnly = nullptr; + java_nio_ByteBuffer_limit = nullptr; + java_nio_ByteBuffer_offset = nullptr; java_nio_DirectByteBuffer_capacity = nullptr; java_nio_DirectByteBuffer_effectiveDirectAddress = nullptr; java_util_ArrayList_array = nullptr; diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h index 9e0b079b7b..d5d7033132 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -85,6 +85,7 @@ struct WellKnownClasses { static jclass java_lang_Throwable; static jclass java_util_ArrayList; static jclass java_util_Collections; + static jclass java_nio_ByteBuffer; static jclass java_nio_DirectByteBuffer; static jclass libcore_reflect_AnnotationFactory; static jclass libcore_reflect_AnnotationMember; @@ -153,8 +154,14 @@ struct WellKnownClasses { static jfieldID java_lang_Throwable_stackTrace; static jfieldID java_lang_Throwable_stackState; static jfieldID java_lang_Throwable_suppressedExceptions; + static jfieldID java_nio_ByteBuffer_address; + static jfieldID java_nio_ByteBuffer_hb; + static jfieldID java_nio_ByteBuffer_isReadOnly; + static jfieldID java_nio_ByteBuffer_limit; + static jfieldID java_nio_ByteBuffer_offset; static jfieldID java_nio_DirectByteBuffer_capacity; static jfieldID java_nio_DirectByteBuffer_effectiveDirectAddress; + static jfieldID java_util_ArrayList_array; static jfieldID java_util_ArrayList_size; static jfieldID java_util_Collections_EMPTY_LIST; diff --git a/test/712-varhandle-invocations/build b/test/712-varhandle-invocations/build new file mode 100755 index 0000000000..253765be91 --- /dev/null +++ b/test/712-varhandle-invocations/build @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Copyright 2018 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. + +# Make us exit on a failure +set -e + +# Set variables for source directories. Using src-art so we use +# VarHandles in the bootclasspath and can compile with the Java 8 +# compiler. +MANUAL_SRC=src +GENERATED_SRC=src2 + +# Build the Java files +mkdir -p src2 + +# Collate list of manual test classes +MANUAL_TESTS=$(cd "${MANUAL_SRC}" && find . -name 'Var*Tests.java' | sed -e 's@.*\(Var.*Tests\).*@\1@g' | sort) + +# Generate tests and Main that covers both the generated tests and manual tests +python3 ./util-src/generate_java.py "${GENERATED_SRC}" ${MANUAL_TESTS} + +# Desugar is not happy with our Java 9 byte code, it shouldn't be necessary here anyway. +export USE_DESUGAR=false + +# Invoke default build with increased heap size for dx +./default-build "$@" --experimental var-handles --dx-vm-option -JXmx384m diff --git a/test/712-varhandle-invocations/expected.txt b/test/712-varhandle-invocations/expected.txt new file mode 100644 index 0000000000..af921901f8 --- /dev/null +++ b/test/712-varhandle-invocations/expected.txt @@ -0,0 +1,3183 @@ +FieldGetBoolean...OK +FieldGetByte...OK +FieldGetShort...OK +FieldGetChar...OK +FieldGetInt...OK +FieldGetLong...OK +FieldGetFloat...OK +FieldGetDouble...OK +FieldSetBoolean...OK +FieldSetByte...OK +FieldSetShort...OK +FieldSetChar...OK +FieldSetInt...OK +FieldSetLong...OK +FieldSetFloat...OK +FieldSetDouble...OK +FieldGetVolatileBoolean...OK +FieldGetVolatileByte...OK +FieldGetVolatileShort...OK +FieldGetVolatileChar...OK +FieldGetVolatileInt...OK +FieldGetVolatileLong...OK +FieldGetVolatileFloat...OK +FieldGetVolatileDouble...OK +FieldSetVolatileBoolean...OK +FieldSetVolatileByte...OK +FieldSetVolatileShort...OK +FieldSetVolatileChar...OK +FieldSetVolatileInt...OK +FieldSetVolatileLong...OK +FieldSetVolatileFloat...OK +FieldSetVolatileDouble...OK +FieldGetAcquireBoolean...OK +FieldGetAcquireByte...OK +FieldGetAcquireShort...OK +FieldGetAcquireChar...OK +FieldGetAcquireInt...OK +FieldGetAcquireLong...OK +FieldGetAcquireFloat...OK +FieldGetAcquireDouble...OK +FieldSetReleaseBoolean...OK +FieldSetReleaseByte...OK +FieldSetReleaseShort...OK +FieldSetReleaseChar...OK +FieldSetReleaseInt...OK +FieldSetReleaseLong...OK +FieldSetReleaseFloat...OK +FieldSetReleaseDouble...OK +FieldGetOpaqueBoolean...OK +FieldGetOpaqueByte...OK +FieldGetOpaqueShort...OK +FieldGetOpaqueChar...OK +FieldGetOpaqueInt...OK +FieldGetOpaqueLong...OK +FieldGetOpaqueFloat...OK +FieldGetOpaqueDouble...OK +FieldSetOpaqueBoolean...OK +FieldSetOpaqueByte...OK +FieldSetOpaqueShort...OK +FieldSetOpaqueChar...OK +FieldSetOpaqueInt...OK +FieldSetOpaqueLong...OK +FieldSetOpaqueFloat...OK +FieldSetOpaqueDouble...OK +FieldCompareAndSetBoolean...OK +FieldCompareAndSetByte...OK +FieldCompareAndSetShort...OK +FieldCompareAndSetChar...OK +FieldCompareAndSetInt...OK +FieldCompareAndSetLong...OK +FieldCompareAndSetFloat...OK +FieldCompareAndSetDouble...OK +FieldCompareAndExchangeBoolean...OK +FieldCompareAndExchangeByte...OK +FieldCompareAndExchangeShort...OK +FieldCompareAndExchangeChar...OK +FieldCompareAndExchangeInt...OK +FieldCompareAndExchangeLong...OK +FieldCompareAndExchangeFloat...OK +FieldCompareAndExchangeDouble...OK +FieldCompareAndExchangeAcquireBoolean...OK +FieldCompareAndExchangeAcquireByte...OK +FieldCompareAndExchangeAcquireShort...OK +FieldCompareAndExchangeAcquireChar...OK +FieldCompareAndExchangeAcquireInt...OK +FieldCompareAndExchangeAcquireLong...OK +FieldCompareAndExchangeAcquireFloat...OK +FieldCompareAndExchangeAcquireDouble...OK +FieldCompareAndExchangeReleaseBoolean...OK +FieldCompareAndExchangeReleaseByte...OK +FieldCompareAndExchangeReleaseShort...OK +FieldCompareAndExchangeReleaseChar...OK +FieldCompareAndExchangeReleaseInt...OK +FieldCompareAndExchangeReleaseLong...OK +FieldCompareAndExchangeReleaseFloat...OK +FieldCompareAndExchangeReleaseDouble...OK +FieldWeakCompareAndSetPlainBoolean...OK +FieldWeakCompareAndSetPlainByte...OK +FieldWeakCompareAndSetPlainShort...OK +FieldWeakCompareAndSetPlainChar...OK +FieldWeakCompareAndSetPlainInt...OK +FieldWeakCompareAndSetPlainLong...OK +FieldWeakCompareAndSetPlainFloat...OK +FieldWeakCompareAndSetPlainDouble...OK +FieldWeakCompareAndSetBoolean...OK +FieldWeakCompareAndSetByte...OK +FieldWeakCompareAndSetShort...OK +FieldWeakCompareAndSetChar...OK +FieldWeakCompareAndSetInt...OK +FieldWeakCompareAndSetLong...OK +FieldWeakCompareAndSetFloat...OK +FieldWeakCompareAndSetDouble...OK +FieldWeakCompareAndSetAcquireBoolean...OK +FieldWeakCompareAndSetAcquireByte...OK +FieldWeakCompareAndSetAcquireShort...OK +FieldWeakCompareAndSetAcquireChar...OK +FieldWeakCompareAndSetAcquireInt...OK +FieldWeakCompareAndSetAcquireLong...OK +FieldWeakCompareAndSetAcquireFloat...OK +FieldWeakCompareAndSetAcquireDouble...OK +FieldWeakCompareAndSetReleaseBoolean...OK +FieldWeakCompareAndSetReleaseByte...OK +FieldWeakCompareAndSetReleaseShort...OK +FieldWeakCompareAndSetReleaseChar...OK +FieldWeakCompareAndSetReleaseInt...OK +FieldWeakCompareAndSetReleaseLong...OK +FieldWeakCompareAndSetReleaseFloat...OK +FieldWeakCompareAndSetReleaseDouble...OK +FieldGetAndSetBoolean...OK +FieldGetAndSetByte...OK +FieldGetAndSetShort...OK +FieldGetAndSetChar...OK +FieldGetAndSetInt...OK +FieldGetAndSetLong...OK +FieldGetAndSetFloat...OK +FieldGetAndSetDouble...OK +FieldGetAndSetAcquireBoolean...OK +FieldGetAndSetAcquireByte...OK +FieldGetAndSetAcquireShort...OK +FieldGetAndSetAcquireChar...OK +FieldGetAndSetAcquireInt...OK +FieldGetAndSetAcquireLong...OK +FieldGetAndSetAcquireFloat...OK +FieldGetAndSetAcquireDouble...OK +FieldGetAndSetReleaseBoolean...OK +FieldGetAndSetReleaseByte...OK +FieldGetAndSetReleaseShort...OK +FieldGetAndSetReleaseChar...OK +FieldGetAndSetReleaseInt...OK +FieldGetAndSetReleaseLong...OK +FieldGetAndSetReleaseFloat...OK +FieldGetAndSetReleaseDouble...OK +FieldGetAndAddBoolean...OK +FieldGetAndAddByte...OK +FieldGetAndAddShort...OK +FieldGetAndAddChar...OK +FieldGetAndAddInt...OK +FieldGetAndAddLong...OK +FieldGetAndAddFloat...OK +FieldGetAndAddDouble...OK +FieldGetAndAddAcquireBoolean...OK +FieldGetAndAddAcquireByte...OK +FieldGetAndAddAcquireShort...OK +FieldGetAndAddAcquireChar...OK +FieldGetAndAddAcquireInt...OK +FieldGetAndAddAcquireLong...OK +FieldGetAndAddAcquireFloat...OK +FieldGetAndAddAcquireDouble...OK +FieldGetAndAddReleaseBoolean...OK +FieldGetAndAddReleaseByte...OK +FieldGetAndAddReleaseShort...OK +FieldGetAndAddReleaseChar...OK +FieldGetAndAddReleaseInt...OK +FieldGetAndAddReleaseLong...OK +FieldGetAndAddReleaseFloat...OK +FieldGetAndAddReleaseDouble...OK +FieldGetAndBitwiseOrBoolean...OK +FieldGetAndBitwiseOrByte...OK +FieldGetAndBitwiseOrShort...OK +FieldGetAndBitwiseOrChar...OK +FieldGetAndBitwiseOrInt...OK +FieldGetAndBitwiseOrLong...OK +FieldGetAndBitwiseOrFloat...OK +FieldGetAndBitwiseOrDouble...OK +FieldGetAndBitwiseOrReleaseBoolean...OK +FieldGetAndBitwiseOrReleaseByte...OK +FieldGetAndBitwiseOrReleaseShort...OK +FieldGetAndBitwiseOrReleaseChar...OK +FieldGetAndBitwiseOrReleaseInt...OK +FieldGetAndBitwiseOrReleaseLong...OK +FieldGetAndBitwiseOrReleaseFloat...OK +FieldGetAndBitwiseOrReleaseDouble...OK +FieldGetAndBitwiseOrAcquireBoolean...OK +FieldGetAndBitwiseOrAcquireByte...OK +FieldGetAndBitwiseOrAcquireShort...OK +FieldGetAndBitwiseOrAcquireChar...OK +FieldGetAndBitwiseOrAcquireInt...OK +FieldGetAndBitwiseOrAcquireLong...OK +FieldGetAndBitwiseOrAcquireFloat...OK +FieldGetAndBitwiseOrAcquireDouble...OK +FieldGetAndBitwiseAndBoolean...OK +FieldGetAndBitwiseAndByte...OK +FieldGetAndBitwiseAndShort...OK +FieldGetAndBitwiseAndChar...OK +FieldGetAndBitwiseAndInt...OK +FieldGetAndBitwiseAndLong...OK +FieldGetAndBitwiseAndFloat...OK +FieldGetAndBitwiseAndDouble...OK +FieldGetAndBitwiseAndReleaseBoolean...OK +FieldGetAndBitwiseAndReleaseByte...OK +FieldGetAndBitwiseAndReleaseShort...OK +FieldGetAndBitwiseAndReleaseChar...OK +FieldGetAndBitwiseAndReleaseInt...OK +FieldGetAndBitwiseAndReleaseLong...OK +FieldGetAndBitwiseAndReleaseFloat...OK +FieldGetAndBitwiseAndReleaseDouble...OK +FieldGetAndBitwiseAndAcquireBoolean...OK +FieldGetAndBitwiseAndAcquireByte...OK +FieldGetAndBitwiseAndAcquireShort...OK +FieldGetAndBitwiseAndAcquireChar...OK +FieldGetAndBitwiseAndAcquireInt...OK +FieldGetAndBitwiseAndAcquireLong...OK +FieldGetAndBitwiseAndAcquireFloat...OK +FieldGetAndBitwiseAndAcquireDouble...OK +FieldGetAndBitwiseXorBoolean...OK +FieldGetAndBitwiseXorByte...OK +FieldGetAndBitwiseXorShort...OK +FieldGetAndBitwiseXorChar...OK +FieldGetAndBitwiseXorInt...OK +FieldGetAndBitwiseXorLong...OK +FieldGetAndBitwiseXorFloat...OK +FieldGetAndBitwiseXorDouble...OK +FieldGetAndBitwiseXorReleaseBoolean...OK +FieldGetAndBitwiseXorReleaseByte...OK +FieldGetAndBitwiseXorReleaseShort...OK +FieldGetAndBitwiseXorReleaseChar...OK +FieldGetAndBitwiseXorReleaseInt...OK +FieldGetAndBitwiseXorReleaseLong...OK +FieldGetAndBitwiseXorReleaseFloat...OK +FieldGetAndBitwiseXorReleaseDouble...OK +FieldGetAndBitwiseXorAcquireBoolean...OK +FieldGetAndBitwiseXorAcquireByte...OK +FieldGetAndBitwiseXorAcquireShort...OK +FieldGetAndBitwiseXorAcquireChar...OK +FieldGetAndBitwiseXorAcquireInt...OK +FieldGetAndBitwiseXorAcquireLong...OK +FieldGetAndBitwiseXorAcquireFloat...OK +FieldGetAndBitwiseXorAcquireDouble...OK +FinalFieldGetBoolean...OK +FinalFieldGetByte...OK +FinalFieldGetShort...OK +FinalFieldGetChar...OK +FinalFieldGetInt...OK +FinalFieldGetLong...OK +FinalFieldGetFloat...OK +FinalFieldGetDouble...OK +FinalFieldSetBoolean...OK +FinalFieldSetByte...OK +FinalFieldSetShort...OK +FinalFieldSetChar...OK +FinalFieldSetInt...OK +FinalFieldSetLong...OK +FinalFieldSetFloat...OK +FinalFieldSetDouble...OK +FinalFieldGetVolatileBoolean...OK +FinalFieldGetVolatileByte...OK +FinalFieldGetVolatileShort...OK +FinalFieldGetVolatileChar...OK +FinalFieldGetVolatileInt...OK +FinalFieldGetVolatileLong...OK +FinalFieldGetVolatileFloat...OK +FinalFieldGetVolatileDouble...OK +FinalFieldSetVolatileBoolean...OK +FinalFieldSetVolatileByte...OK +FinalFieldSetVolatileShort...OK +FinalFieldSetVolatileChar...OK +FinalFieldSetVolatileInt...OK +FinalFieldSetVolatileLong...OK +FinalFieldSetVolatileFloat...OK +FinalFieldSetVolatileDouble...OK +FinalFieldGetAcquireBoolean...OK +FinalFieldGetAcquireByte...OK +FinalFieldGetAcquireShort...OK +FinalFieldGetAcquireChar...OK +FinalFieldGetAcquireInt...OK +FinalFieldGetAcquireLong...OK +FinalFieldGetAcquireFloat...OK +FinalFieldGetAcquireDouble...OK +FinalFieldSetReleaseBoolean...OK +FinalFieldSetReleaseByte...OK +FinalFieldSetReleaseShort...OK +FinalFieldSetReleaseChar...OK +FinalFieldSetReleaseInt...OK +FinalFieldSetReleaseLong...OK +FinalFieldSetReleaseFloat...OK +FinalFieldSetReleaseDouble...OK +FinalFieldGetOpaqueBoolean...OK +FinalFieldGetOpaqueByte...OK +FinalFieldGetOpaqueShort...OK +FinalFieldGetOpaqueChar...OK +FinalFieldGetOpaqueInt...OK +FinalFieldGetOpaqueLong...OK +FinalFieldGetOpaqueFloat...OK +FinalFieldGetOpaqueDouble...OK +FinalFieldSetOpaqueBoolean...OK +FinalFieldSetOpaqueByte...OK +FinalFieldSetOpaqueShort...OK +FinalFieldSetOpaqueChar...OK +FinalFieldSetOpaqueInt...OK +FinalFieldSetOpaqueLong...OK +FinalFieldSetOpaqueFloat...OK +FinalFieldSetOpaqueDouble...OK +FinalFieldCompareAndSetBoolean...OK +FinalFieldCompareAndSetByte...OK +FinalFieldCompareAndSetShort...OK +FinalFieldCompareAndSetChar...OK +FinalFieldCompareAndSetInt...OK +FinalFieldCompareAndSetLong...OK +FinalFieldCompareAndSetFloat...OK +FinalFieldCompareAndSetDouble...OK +FinalFieldCompareAndExchangeBoolean...OK +FinalFieldCompareAndExchangeByte...OK +FinalFieldCompareAndExchangeShort...OK +FinalFieldCompareAndExchangeChar...OK +FinalFieldCompareAndExchangeInt...OK +FinalFieldCompareAndExchangeLong...OK +FinalFieldCompareAndExchangeFloat...OK +FinalFieldCompareAndExchangeDouble...OK +FinalFieldCompareAndExchangeAcquireBoolean...OK +FinalFieldCompareAndExchangeAcquireByte...OK +FinalFieldCompareAndExchangeAcquireShort...OK +FinalFieldCompareAndExchangeAcquireChar...OK +FinalFieldCompareAndExchangeAcquireInt...OK +FinalFieldCompareAndExchangeAcquireLong...OK +FinalFieldCompareAndExchangeAcquireFloat...OK +FinalFieldCompareAndExchangeAcquireDouble...OK +FinalFieldCompareAndExchangeReleaseBoolean...OK +FinalFieldCompareAndExchangeReleaseByte...OK +FinalFieldCompareAndExchangeReleaseShort...OK +FinalFieldCompareAndExchangeReleaseChar...OK +FinalFieldCompareAndExchangeReleaseInt...OK +FinalFieldCompareAndExchangeReleaseLong...OK +FinalFieldCompareAndExchangeReleaseFloat...OK +FinalFieldCompareAndExchangeReleaseDouble...OK +FinalFieldWeakCompareAndSetPlainBoolean...OK +FinalFieldWeakCompareAndSetPlainByte...OK +FinalFieldWeakCompareAndSetPlainShort...OK +FinalFieldWeakCompareAndSetPlainChar...OK +FinalFieldWeakCompareAndSetPlainInt...OK +FinalFieldWeakCompareAndSetPlainLong...OK +FinalFieldWeakCompareAndSetPlainFloat...OK +FinalFieldWeakCompareAndSetPlainDouble...OK +FinalFieldWeakCompareAndSetBoolean...OK +FinalFieldWeakCompareAndSetByte...OK +FinalFieldWeakCompareAndSetShort...OK +FinalFieldWeakCompareAndSetChar...OK +FinalFieldWeakCompareAndSetInt...OK +FinalFieldWeakCompareAndSetLong...OK +FinalFieldWeakCompareAndSetFloat...OK +FinalFieldWeakCompareAndSetDouble...OK +FinalFieldWeakCompareAndSetAcquireBoolean...OK +FinalFieldWeakCompareAndSetAcquireByte...OK +FinalFieldWeakCompareAndSetAcquireShort...OK +FinalFieldWeakCompareAndSetAcquireChar...OK +FinalFieldWeakCompareAndSetAcquireInt...OK +FinalFieldWeakCompareAndSetAcquireLong...OK +FinalFieldWeakCompareAndSetAcquireFloat...OK +FinalFieldWeakCompareAndSetAcquireDouble...OK +FinalFieldWeakCompareAndSetReleaseBoolean...OK +FinalFieldWeakCompareAndSetReleaseByte...OK +FinalFieldWeakCompareAndSetReleaseShort...OK +FinalFieldWeakCompareAndSetReleaseChar...OK +FinalFieldWeakCompareAndSetReleaseInt...OK +FinalFieldWeakCompareAndSetReleaseLong...OK +FinalFieldWeakCompareAndSetReleaseFloat...OK +FinalFieldWeakCompareAndSetReleaseDouble...OK +FinalFieldGetAndSetBoolean...OK +FinalFieldGetAndSetByte...OK +FinalFieldGetAndSetShort...OK +FinalFieldGetAndSetChar...OK +FinalFieldGetAndSetInt...OK +FinalFieldGetAndSetLong...OK +FinalFieldGetAndSetFloat...OK +FinalFieldGetAndSetDouble...OK +FinalFieldGetAndSetAcquireBoolean...OK +FinalFieldGetAndSetAcquireByte...OK +FinalFieldGetAndSetAcquireShort...OK +FinalFieldGetAndSetAcquireChar...OK +FinalFieldGetAndSetAcquireInt...OK +FinalFieldGetAndSetAcquireLong...OK +FinalFieldGetAndSetAcquireFloat...OK +FinalFieldGetAndSetAcquireDouble...OK +FinalFieldGetAndSetReleaseBoolean...OK +FinalFieldGetAndSetReleaseByte...OK +FinalFieldGetAndSetReleaseShort...OK +FinalFieldGetAndSetReleaseChar...OK +FinalFieldGetAndSetReleaseInt...OK +FinalFieldGetAndSetReleaseLong...OK +FinalFieldGetAndSetReleaseFloat...OK +FinalFieldGetAndSetReleaseDouble...OK +FinalFieldGetAndAddBoolean...OK +FinalFieldGetAndAddByte...OK +FinalFieldGetAndAddShort...OK +FinalFieldGetAndAddChar...OK +FinalFieldGetAndAddInt...OK +FinalFieldGetAndAddLong...OK +FinalFieldGetAndAddFloat...OK +FinalFieldGetAndAddDouble...OK +FinalFieldGetAndAddAcquireBoolean...OK +FinalFieldGetAndAddAcquireByte...OK +FinalFieldGetAndAddAcquireShort...OK +FinalFieldGetAndAddAcquireChar...OK +FinalFieldGetAndAddAcquireInt...OK +FinalFieldGetAndAddAcquireLong...OK +FinalFieldGetAndAddAcquireFloat...OK +FinalFieldGetAndAddAcquireDouble...OK +FinalFieldGetAndAddReleaseBoolean...OK +FinalFieldGetAndAddReleaseByte...OK +FinalFieldGetAndAddReleaseShort...OK +FinalFieldGetAndAddReleaseChar...OK +FinalFieldGetAndAddReleaseInt...OK +FinalFieldGetAndAddReleaseLong...OK +FinalFieldGetAndAddReleaseFloat...OK +FinalFieldGetAndAddReleaseDouble...OK +FinalFieldGetAndBitwiseOrBoolean...OK +FinalFieldGetAndBitwiseOrByte...OK +FinalFieldGetAndBitwiseOrShort...OK +FinalFieldGetAndBitwiseOrChar...OK +FinalFieldGetAndBitwiseOrInt...OK +FinalFieldGetAndBitwiseOrLong...OK +FinalFieldGetAndBitwiseOrFloat...OK +FinalFieldGetAndBitwiseOrDouble...OK +FinalFieldGetAndBitwiseOrReleaseBoolean...OK +FinalFieldGetAndBitwiseOrReleaseByte...OK +FinalFieldGetAndBitwiseOrReleaseShort...OK +FinalFieldGetAndBitwiseOrReleaseChar...OK +FinalFieldGetAndBitwiseOrReleaseInt...OK +FinalFieldGetAndBitwiseOrReleaseLong...OK +FinalFieldGetAndBitwiseOrReleaseFloat...OK +FinalFieldGetAndBitwiseOrReleaseDouble...OK +FinalFieldGetAndBitwiseOrAcquireBoolean...OK +FinalFieldGetAndBitwiseOrAcquireByte...OK +FinalFieldGetAndBitwiseOrAcquireShort...OK +FinalFieldGetAndBitwiseOrAcquireChar...OK +FinalFieldGetAndBitwiseOrAcquireInt...OK +FinalFieldGetAndBitwiseOrAcquireLong...OK +FinalFieldGetAndBitwiseOrAcquireFloat...OK +FinalFieldGetAndBitwiseOrAcquireDouble...OK +FinalFieldGetAndBitwiseAndBoolean...OK +FinalFieldGetAndBitwiseAndByte...OK +FinalFieldGetAndBitwiseAndShort...OK +FinalFieldGetAndBitwiseAndChar...OK +FinalFieldGetAndBitwiseAndInt...OK +FinalFieldGetAndBitwiseAndLong...OK +FinalFieldGetAndBitwiseAndFloat...OK +FinalFieldGetAndBitwiseAndDouble...OK +FinalFieldGetAndBitwiseAndReleaseBoolean...OK +FinalFieldGetAndBitwiseAndReleaseByte...OK +FinalFieldGetAndBitwiseAndReleaseShort...OK +FinalFieldGetAndBitwiseAndReleaseChar...OK +FinalFieldGetAndBitwiseAndReleaseInt...OK +FinalFieldGetAndBitwiseAndReleaseLong...OK +FinalFieldGetAndBitwiseAndReleaseFloat...OK +FinalFieldGetAndBitwiseAndReleaseDouble...OK +FinalFieldGetAndBitwiseAndAcquireBoolean...OK +FinalFieldGetAndBitwiseAndAcquireByte...OK +FinalFieldGetAndBitwiseAndAcquireShort...OK +FinalFieldGetAndBitwiseAndAcquireChar...OK +FinalFieldGetAndBitwiseAndAcquireInt...OK +FinalFieldGetAndBitwiseAndAcquireLong...OK +FinalFieldGetAndBitwiseAndAcquireFloat...OK +FinalFieldGetAndBitwiseAndAcquireDouble...OK +FinalFieldGetAndBitwiseXorBoolean...OK +FinalFieldGetAndBitwiseXorByte...OK +FinalFieldGetAndBitwiseXorShort...OK +FinalFieldGetAndBitwiseXorChar...OK +FinalFieldGetAndBitwiseXorInt...OK +FinalFieldGetAndBitwiseXorLong...OK +FinalFieldGetAndBitwiseXorFloat...OK +FinalFieldGetAndBitwiseXorDouble...OK +FinalFieldGetAndBitwiseXorReleaseBoolean...OK +FinalFieldGetAndBitwiseXorReleaseByte...OK +FinalFieldGetAndBitwiseXorReleaseShort...OK +FinalFieldGetAndBitwiseXorReleaseChar...OK +FinalFieldGetAndBitwiseXorReleaseInt...OK +FinalFieldGetAndBitwiseXorReleaseLong...OK +FinalFieldGetAndBitwiseXorReleaseFloat...OK +FinalFieldGetAndBitwiseXorReleaseDouble...OK +FinalFieldGetAndBitwiseXorAcquireBoolean...OK +FinalFieldGetAndBitwiseXorAcquireByte...OK +FinalFieldGetAndBitwiseXorAcquireShort...OK +FinalFieldGetAndBitwiseXorAcquireChar...OK +FinalFieldGetAndBitwiseXorAcquireInt...OK +FinalFieldGetAndBitwiseXorAcquireLong...OK +FinalFieldGetAndBitwiseXorAcquireFloat...OK +FinalFieldGetAndBitwiseXorAcquireDouble...OK +StaticFieldGetBoolean...OK +StaticFieldGetByte...OK +StaticFieldGetShort...OK +StaticFieldGetChar...OK +StaticFieldGetInt...OK +StaticFieldGetLong...OK +StaticFieldGetFloat...OK +StaticFieldGetDouble...OK +StaticFieldSetBoolean...OK +StaticFieldSetByte...OK +StaticFieldSetShort...OK +StaticFieldSetChar...OK +StaticFieldSetInt...OK +StaticFieldSetLong...OK +StaticFieldSetFloat...OK +StaticFieldSetDouble...OK +StaticFieldGetVolatileBoolean...OK +StaticFieldGetVolatileByte...OK +StaticFieldGetVolatileShort...OK +StaticFieldGetVolatileChar...OK +StaticFieldGetVolatileInt...OK +StaticFieldGetVolatileLong...OK +StaticFieldGetVolatileFloat...OK +StaticFieldGetVolatileDouble...OK +StaticFieldSetVolatileBoolean...OK +StaticFieldSetVolatileByte...OK +StaticFieldSetVolatileShort...OK +StaticFieldSetVolatileChar...OK +StaticFieldSetVolatileInt...OK +StaticFieldSetVolatileLong...OK +StaticFieldSetVolatileFloat...OK +StaticFieldSetVolatileDouble...OK +StaticFieldGetAcquireBoolean...OK +StaticFieldGetAcquireByte...OK +StaticFieldGetAcquireShort...OK +StaticFieldGetAcquireChar...OK +StaticFieldGetAcquireInt...OK +StaticFieldGetAcquireLong...OK +StaticFieldGetAcquireFloat...OK +StaticFieldGetAcquireDouble...OK +StaticFieldSetReleaseBoolean...OK +StaticFieldSetReleaseByte...OK +StaticFieldSetReleaseShort...OK +StaticFieldSetReleaseChar...OK +StaticFieldSetReleaseInt...OK +StaticFieldSetReleaseLong...OK +StaticFieldSetReleaseFloat...OK +StaticFieldSetReleaseDouble...OK +StaticFieldGetOpaqueBoolean...OK +StaticFieldGetOpaqueByte...OK +StaticFieldGetOpaqueShort...OK +StaticFieldGetOpaqueChar...OK +StaticFieldGetOpaqueInt...OK +StaticFieldGetOpaqueLong...OK +StaticFieldGetOpaqueFloat...OK +StaticFieldGetOpaqueDouble...OK +StaticFieldSetOpaqueBoolean...OK +StaticFieldSetOpaqueByte...OK +StaticFieldSetOpaqueShort...OK +StaticFieldSetOpaqueChar...OK +StaticFieldSetOpaqueInt...OK +StaticFieldSetOpaqueLong...OK +StaticFieldSetOpaqueFloat...OK +StaticFieldSetOpaqueDouble...OK +StaticFieldCompareAndSetBoolean...OK +StaticFieldCompareAndSetByte...OK +StaticFieldCompareAndSetShort...OK +StaticFieldCompareAndSetChar...OK +StaticFieldCompareAndSetInt...OK +StaticFieldCompareAndSetLong...OK +StaticFieldCompareAndSetFloat...OK +StaticFieldCompareAndSetDouble...OK +StaticFieldCompareAndExchangeBoolean...OK +StaticFieldCompareAndExchangeByte...OK +StaticFieldCompareAndExchangeShort...OK +StaticFieldCompareAndExchangeChar...OK +StaticFieldCompareAndExchangeInt...OK +StaticFieldCompareAndExchangeLong...OK +StaticFieldCompareAndExchangeFloat...OK +StaticFieldCompareAndExchangeDouble...OK +StaticFieldCompareAndExchangeAcquireBoolean...OK +StaticFieldCompareAndExchangeAcquireByte...OK +StaticFieldCompareAndExchangeAcquireShort...OK +StaticFieldCompareAndExchangeAcquireChar...OK +StaticFieldCompareAndExchangeAcquireInt...OK +StaticFieldCompareAndExchangeAcquireLong...OK +StaticFieldCompareAndExchangeAcquireFloat...OK +StaticFieldCompareAndExchangeAcquireDouble...OK +StaticFieldCompareAndExchangeReleaseBoolean...OK +StaticFieldCompareAndExchangeReleaseByte...OK +StaticFieldCompareAndExchangeReleaseShort...OK +StaticFieldCompareAndExchangeReleaseChar...OK +StaticFieldCompareAndExchangeReleaseInt...OK +StaticFieldCompareAndExchangeReleaseLong...OK +StaticFieldCompareAndExchangeReleaseFloat...OK +StaticFieldCompareAndExchangeReleaseDouble...OK +StaticFieldWeakCompareAndSetPlainBoolean...OK +StaticFieldWeakCompareAndSetPlainByte...OK +StaticFieldWeakCompareAndSetPlainShort...OK +StaticFieldWeakCompareAndSetPlainChar...OK +StaticFieldWeakCompareAndSetPlainInt...OK +StaticFieldWeakCompareAndSetPlainLong...OK +StaticFieldWeakCompareAndSetPlainFloat...OK +StaticFieldWeakCompareAndSetPlainDouble...OK +StaticFieldWeakCompareAndSetBoolean...OK +StaticFieldWeakCompareAndSetByte...OK +StaticFieldWeakCompareAndSetShort...OK +StaticFieldWeakCompareAndSetChar...OK +StaticFieldWeakCompareAndSetInt...OK +StaticFieldWeakCompareAndSetLong...OK +StaticFieldWeakCompareAndSetFloat...OK +StaticFieldWeakCompareAndSetDouble...OK +StaticFieldWeakCompareAndSetAcquireBoolean...OK +StaticFieldWeakCompareAndSetAcquireByte...OK +StaticFieldWeakCompareAndSetAcquireShort...OK +StaticFieldWeakCompareAndSetAcquireChar...OK +StaticFieldWeakCompareAndSetAcquireInt...OK +StaticFieldWeakCompareAndSetAcquireLong...OK +StaticFieldWeakCompareAndSetAcquireFloat...OK +StaticFieldWeakCompareAndSetAcquireDouble...OK +StaticFieldWeakCompareAndSetReleaseBoolean...OK +StaticFieldWeakCompareAndSetReleaseByte...OK +StaticFieldWeakCompareAndSetReleaseShort...OK +StaticFieldWeakCompareAndSetReleaseChar...OK +StaticFieldWeakCompareAndSetReleaseInt...OK +StaticFieldWeakCompareAndSetReleaseLong...OK +StaticFieldWeakCompareAndSetReleaseFloat...OK +StaticFieldWeakCompareAndSetReleaseDouble...OK +StaticFieldGetAndSetBoolean...OK +StaticFieldGetAndSetByte...OK +StaticFieldGetAndSetShort...OK +StaticFieldGetAndSetChar...OK +StaticFieldGetAndSetInt...OK +StaticFieldGetAndSetLong...OK +StaticFieldGetAndSetFloat...OK +StaticFieldGetAndSetDouble...OK +StaticFieldGetAndSetAcquireBoolean...OK +StaticFieldGetAndSetAcquireByte...OK +StaticFieldGetAndSetAcquireShort...OK +StaticFieldGetAndSetAcquireChar...OK +StaticFieldGetAndSetAcquireInt...OK +StaticFieldGetAndSetAcquireLong...OK +StaticFieldGetAndSetAcquireFloat...OK +StaticFieldGetAndSetAcquireDouble...OK +StaticFieldGetAndSetReleaseBoolean...OK +StaticFieldGetAndSetReleaseByte...OK +StaticFieldGetAndSetReleaseShort...OK +StaticFieldGetAndSetReleaseChar...OK +StaticFieldGetAndSetReleaseInt...OK +StaticFieldGetAndSetReleaseLong...OK +StaticFieldGetAndSetReleaseFloat...OK +StaticFieldGetAndSetReleaseDouble...OK +StaticFieldGetAndAddBoolean...OK +StaticFieldGetAndAddByte...OK +StaticFieldGetAndAddShort...OK +StaticFieldGetAndAddChar...OK +StaticFieldGetAndAddInt...OK +StaticFieldGetAndAddLong...OK +StaticFieldGetAndAddFloat...OK +StaticFieldGetAndAddDouble...OK +StaticFieldGetAndAddAcquireBoolean...OK +StaticFieldGetAndAddAcquireByte...OK +StaticFieldGetAndAddAcquireShort...OK +StaticFieldGetAndAddAcquireChar...OK +StaticFieldGetAndAddAcquireInt...OK +StaticFieldGetAndAddAcquireLong...OK +StaticFieldGetAndAddAcquireFloat...OK +StaticFieldGetAndAddAcquireDouble...OK +StaticFieldGetAndAddReleaseBoolean...OK +StaticFieldGetAndAddReleaseByte...OK +StaticFieldGetAndAddReleaseShort...OK +StaticFieldGetAndAddReleaseChar...OK +StaticFieldGetAndAddReleaseInt...OK +StaticFieldGetAndAddReleaseLong...OK +StaticFieldGetAndAddReleaseFloat...OK +StaticFieldGetAndAddReleaseDouble...OK +StaticFieldGetAndBitwiseOrBoolean...OK +StaticFieldGetAndBitwiseOrByte...OK +StaticFieldGetAndBitwiseOrShort...OK +StaticFieldGetAndBitwiseOrChar...OK +StaticFieldGetAndBitwiseOrInt...OK +StaticFieldGetAndBitwiseOrLong...OK +StaticFieldGetAndBitwiseOrFloat...OK +StaticFieldGetAndBitwiseOrDouble...OK +StaticFieldGetAndBitwiseOrReleaseBoolean...OK +StaticFieldGetAndBitwiseOrReleaseByte...OK +StaticFieldGetAndBitwiseOrReleaseShort...OK +StaticFieldGetAndBitwiseOrReleaseChar...OK +StaticFieldGetAndBitwiseOrReleaseInt...OK +StaticFieldGetAndBitwiseOrReleaseLong...OK +StaticFieldGetAndBitwiseOrReleaseFloat...OK +StaticFieldGetAndBitwiseOrReleaseDouble...OK +StaticFieldGetAndBitwiseOrAcquireBoolean...OK +StaticFieldGetAndBitwiseOrAcquireByte...OK +StaticFieldGetAndBitwiseOrAcquireShort...OK +StaticFieldGetAndBitwiseOrAcquireChar...OK +StaticFieldGetAndBitwiseOrAcquireInt...OK +StaticFieldGetAndBitwiseOrAcquireLong...OK +StaticFieldGetAndBitwiseOrAcquireFloat...OK +StaticFieldGetAndBitwiseOrAcquireDouble...OK +StaticFieldGetAndBitwiseAndBoolean...OK +StaticFieldGetAndBitwiseAndByte...OK +StaticFieldGetAndBitwiseAndShort...OK +StaticFieldGetAndBitwiseAndChar...OK +StaticFieldGetAndBitwiseAndInt...OK +StaticFieldGetAndBitwiseAndLong...OK +StaticFieldGetAndBitwiseAndFloat...OK +StaticFieldGetAndBitwiseAndDouble...OK +StaticFieldGetAndBitwiseAndReleaseBoolean...OK +StaticFieldGetAndBitwiseAndReleaseByte...OK +StaticFieldGetAndBitwiseAndReleaseShort...OK +StaticFieldGetAndBitwiseAndReleaseChar...OK +StaticFieldGetAndBitwiseAndReleaseInt...OK +StaticFieldGetAndBitwiseAndReleaseLong...OK +StaticFieldGetAndBitwiseAndReleaseFloat...OK +StaticFieldGetAndBitwiseAndReleaseDouble...OK +StaticFieldGetAndBitwiseAndAcquireBoolean...OK +StaticFieldGetAndBitwiseAndAcquireByte...OK +StaticFieldGetAndBitwiseAndAcquireShort...OK +StaticFieldGetAndBitwiseAndAcquireChar...OK +StaticFieldGetAndBitwiseAndAcquireInt...OK +StaticFieldGetAndBitwiseAndAcquireLong...OK +StaticFieldGetAndBitwiseAndAcquireFloat...OK +StaticFieldGetAndBitwiseAndAcquireDouble...OK +StaticFieldGetAndBitwiseXorBoolean...OK +StaticFieldGetAndBitwiseXorByte...OK +StaticFieldGetAndBitwiseXorShort...OK +StaticFieldGetAndBitwiseXorChar...OK +StaticFieldGetAndBitwiseXorInt...OK +StaticFieldGetAndBitwiseXorLong...OK +StaticFieldGetAndBitwiseXorFloat...OK +StaticFieldGetAndBitwiseXorDouble...OK +StaticFieldGetAndBitwiseXorReleaseBoolean...OK +StaticFieldGetAndBitwiseXorReleaseByte...OK +StaticFieldGetAndBitwiseXorReleaseShort...OK +StaticFieldGetAndBitwiseXorReleaseChar...OK +StaticFieldGetAndBitwiseXorReleaseInt...OK +StaticFieldGetAndBitwiseXorReleaseLong...OK +StaticFieldGetAndBitwiseXorReleaseFloat...OK +StaticFieldGetAndBitwiseXorReleaseDouble...OK +StaticFieldGetAndBitwiseXorAcquireBoolean...OK +StaticFieldGetAndBitwiseXorAcquireByte...OK +StaticFieldGetAndBitwiseXorAcquireShort...OK +StaticFieldGetAndBitwiseXorAcquireChar...OK +StaticFieldGetAndBitwiseXorAcquireInt...OK +StaticFieldGetAndBitwiseXorAcquireLong...OK +StaticFieldGetAndBitwiseXorAcquireFloat...OK +StaticFieldGetAndBitwiseXorAcquireDouble...OK +StaticFinalFieldGetBoolean...OK +StaticFinalFieldGetByte...OK +StaticFinalFieldGetShort...OK +StaticFinalFieldGetChar...OK +StaticFinalFieldGetInt...OK +StaticFinalFieldGetLong...OK +StaticFinalFieldGetFloat...OK +StaticFinalFieldGetDouble...OK +StaticFinalFieldSetBoolean...OK +StaticFinalFieldSetByte...OK +StaticFinalFieldSetShort...OK +StaticFinalFieldSetChar...OK +StaticFinalFieldSetInt...OK +StaticFinalFieldSetLong...OK +StaticFinalFieldSetFloat...OK +StaticFinalFieldSetDouble...OK +StaticFinalFieldGetVolatileBoolean...OK +StaticFinalFieldGetVolatileByte...OK +StaticFinalFieldGetVolatileShort...OK +StaticFinalFieldGetVolatileChar...OK +StaticFinalFieldGetVolatileInt...OK +StaticFinalFieldGetVolatileLong...OK +StaticFinalFieldGetVolatileFloat...OK +StaticFinalFieldGetVolatileDouble...OK +StaticFinalFieldSetVolatileBoolean...OK +StaticFinalFieldSetVolatileByte...OK +StaticFinalFieldSetVolatileShort...OK +StaticFinalFieldSetVolatileChar...OK +StaticFinalFieldSetVolatileInt...OK +StaticFinalFieldSetVolatileLong...OK +StaticFinalFieldSetVolatileFloat...OK +StaticFinalFieldSetVolatileDouble...OK +StaticFinalFieldGetAcquireBoolean...OK +StaticFinalFieldGetAcquireByte...OK +StaticFinalFieldGetAcquireShort...OK +StaticFinalFieldGetAcquireChar...OK +StaticFinalFieldGetAcquireInt...OK +StaticFinalFieldGetAcquireLong...OK +StaticFinalFieldGetAcquireFloat...OK +StaticFinalFieldGetAcquireDouble...OK +StaticFinalFieldSetReleaseBoolean...OK +StaticFinalFieldSetReleaseByte...OK +StaticFinalFieldSetReleaseShort...OK +StaticFinalFieldSetReleaseChar...OK +StaticFinalFieldSetReleaseInt...OK +StaticFinalFieldSetReleaseLong...OK +StaticFinalFieldSetReleaseFloat...OK +StaticFinalFieldSetReleaseDouble...OK +StaticFinalFieldGetOpaqueBoolean...OK +StaticFinalFieldGetOpaqueByte...OK +StaticFinalFieldGetOpaqueShort...OK +StaticFinalFieldGetOpaqueChar...OK +StaticFinalFieldGetOpaqueInt...OK +StaticFinalFieldGetOpaqueLong...OK +StaticFinalFieldGetOpaqueFloat...OK +StaticFinalFieldGetOpaqueDouble...OK +StaticFinalFieldSetOpaqueBoolean...OK +StaticFinalFieldSetOpaqueByte...OK +StaticFinalFieldSetOpaqueShort...OK +StaticFinalFieldSetOpaqueChar...OK +StaticFinalFieldSetOpaqueInt...OK +StaticFinalFieldSetOpaqueLong...OK +StaticFinalFieldSetOpaqueFloat...OK +StaticFinalFieldSetOpaqueDouble...OK +StaticFinalFieldCompareAndSetBoolean...OK +StaticFinalFieldCompareAndSetByte...OK +StaticFinalFieldCompareAndSetShort...OK +StaticFinalFieldCompareAndSetChar...OK +StaticFinalFieldCompareAndSetInt...OK +StaticFinalFieldCompareAndSetLong...OK +StaticFinalFieldCompareAndSetFloat...OK +StaticFinalFieldCompareAndSetDouble...OK +StaticFinalFieldCompareAndExchangeBoolean...OK +StaticFinalFieldCompareAndExchangeByte...OK +StaticFinalFieldCompareAndExchangeShort...OK +StaticFinalFieldCompareAndExchangeChar...OK +StaticFinalFieldCompareAndExchangeInt...OK +StaticFinalFieldCompareAndExchangeLong...OK +StaticFinalFieldCompareAndExchangeFloat...OK +StaticFinalFieldCompareAndExchangeDouble...OK +StaticFinalFieldCompareAndExchangeAcquireBoolean...OK +StaticFinalFieldCompareAndExchangeAcquireByte...OK +StaticFinalFieldCompareAndExchangeAcquireShort...OK +StaticFinalFieldCompareAndExchangeAcquireChar...OK +StaticFinalFieldCompareAndExchangeAcquireInt...OK +StaticFinalFieldCompareAndExchangeAcquireLong...OK +StaticFinalFieldCompareAndExchangeAcquireFloat...OK +StaticFinalFieldCompareAndExchangeAcquireDouble...OK +StaticFinalFieldCompareAndExchangeReleaseBoolean...OK +StaticFinalFieldCompareAndExchangeReleaseByte...OK +StaticFinalFieldCompareAndExchangeReleaseShort...OK +StaticFinalFieldCompareAndExchangeReleaseChar...OK +StaticFinalFieldCompareAndExchangeReleaseInt...OK +StaticFinalFieldCompareAndExchangeReleaseLong...OK +StaticFinalFieldCompareAndExchangeReleaseFloat...OK +StaticFinalFieldCompareAndExchangeReleaseDouble...OK +StaticFinalFieldWeakCompareAndSetPlainBoolean...OK +StaticFinalFieldWeakCompareAndSetPlainByte...OK +StaticFinalFieldWeakCompareAndSetPlainShort...OK +StaticFinalFieldWeakCompareAndSetPlainChar...OK +StaticFinalFieldWeakCompareAndSetPlainInt...OK +StaticFinalFieldWeakCompareAndSetPlainLong...OK +StaticFinalFieldWeakCompareAndSetPlainFloat...OK +StaticFinalFieldWeakCompareAndSetPlainDouble...OK +StaticFinalFieldWeakCompareAndSetBoolean...OK +StaticFinalFieldWeakCompareAndSetByte...OK +StaticFinalFieldWeakCompareAndSetShort...OK +StaticFinalFieldWeakCompareAndSetChar...OK +StaticFinalFieldWeakCompareAndSetInt...OK +StaticFinalFieldWeakCompareAndSetLong...OK +StaticFinalFieldWeakCompareAndSetFloat...OK +StaticFinalFieldWeakCompareAndSetDouble...OK +StaticFinalFieldWeakCompareAndSetAcquireBoolean...OK +StaticFinalFieldWeakCompareAndSetAcquireByte...OK +StaticFinalFieldWeakCompareAndSetAcquireShort...OK +StaticFinalFieldWeakCompareAndSetAcquireChar...OK +StaticFinalFieldWeakCompareAndSetAcquireInt...OK +StaticFinalFieldWeakCompareAndSetAcquireLong...OK +StaticFinalFieldWeakCompareAndSetAcquireFloat...OK +StaticFinalFieldWeakCompareAndSetAcquireDouble...OK +StaticFinalFieldWeakCompareAndSetReleaseBoolean...OK +StaticFinalFieldWeakCompareAndSetReleaseByte...OK +StaticFinalFieldWeakCompareAndSetReleaseShort...OK +StaticFinalFieldWeakCompareAndSetReleaseChar...OK +StaticFinalFieldWeakCompareAndSetReleaseInt...OK +StaticFinalFieldWeakCompareAndSetReleaseLong...OK +StaticFinalFieldWeakCompareAndSetReleaseFloat...OK +StaticFinalFieldWeakCompareAndSetReleaseDouble...OK +StaticFinalFieldGetAndSetBoolean...OK +StaticFinalFieldGetAndSetByte...OK +StaticFinalFieldGetAndSetShort...OK +StaticFinalFieldGetAndSetChar...OK +StaticFinalFieldGetAndSetInt...OK +StaticFinalFieldGetAndSetLong...OK +StaticFinalFieldGetAndSetFloat...OK +StaticFinalFieldGetAndSetDouble...OK +StaticFinalFieldGetAndSetAcquireBoolean...OK +StaticFinalFieldGetAndSetAcquireByte...OK +StaticFinalFieldGetAndSetAcquireShort...OK +StaticFinalFieldGetAndSetAcquireChar...OK +StaticFinalFieldGetAndSetAcquireInt...OK +StaticFinalFieldGetAndSetAcquireLong...OK +StaticFinalFieldGetAndSetAcquireFloat...OK +StaticFinalFieldGetAndSetAcquireDouble...OK +StaticFinalFieldGetAndSetReleaseBoolean...OK +StaticFinalFieldGetAndSetReleaseByte...OK +StaticFinalFieldGetAndSetReleaseShort...OK +StaticFinalFieldGetAndSetReleaseChar...OK +StaticFinalFieldGetAndSetReleaseInt...OK +StaticFinalFieldGetAndSetReleaseLong...OK +StaticFinalFieldGetAndSetReleaseFloat...OK +StaticFinalFieldGetAndSetReleaseDouble...OK +StaticFinalFieldGetAndAddBoolean...OK +StaticFinalFieldGetAndAddByte...OK +StaticFinalFieldGetAndAddShort...OK +StaticFinalFieldGetAndAddChar...OK +StaticFinalFieldGetAndAddInt...OK +StaticFinalFieldGetAndAddLong...OK +StaticFinalFieldGetAndAddFloat...OK +StaticFinalFieldGetAndAddDouble...OK +StaticFinalFieldGetAndAddAcquireBoolean...OK +StaticFinalFieldGetAndAddAcquireByte...OK +StaticFinalFieldGetAndAddAcquireShort...OK +StaticFinalFieldGetAndAddAcquireChar...OK +StaticFinalFieldGetAndAddAcquireInt...OK +StaticFinalFieldGetAndAddAcquireLong...OK +StaticFinalFieldGetAndAddAcquireFloat...OK +StaticFinalFieldGetAndAddAcquireDouble...OK +StaticFinalFieldGetAndAddReleaseBoolean...OK +StaticFinalFieldGetAndAddReleaseByte...OK +StaticFinalFieldGetAndAddReleaseShort...OK +StaticFinalFieldGetAndAddReleaseChar...OK +StaticFinalFieldGetAndAddReleaseInt...OK +StaticFinalFieldGetAndAddReleaseLong...OK +StaticFinalFieldGetAndAddReleaseFloat...OK +StaticFinalFieldGetAndAddReleaseDouble...OK +StaticFinalFieldGetAndBitwiseOrBoolean...OK +StaticFinalFieldGetAndBitwiseOrByte...OK +StaticFinalFieldGetAndBitwiseOrShort...OK +StaticFinalFieldGetAndBitwiseOrChar...OK +StaticFinalFieldGetAndBitwiseOrInt...OK +StaticFinalFieldGetAndBitwiseOrLong...OK +StaticFinalFieldGetAndBitwiseOrFloat...OK +StaticFinalFieldGetAndBitwiseOrDouble...OK +StaticFinalFieldGetAndBitwiseOrReleaseBoolean...OK +StaticFinalFieldGetAndBitwiseOrReleaseByte...OK +StaticFinalFieldGetAndBitwiseOrReleaseShort...OK +StaticFinalFieldGetAndBitwiseOrReleaseChar...OK +StaticFinalFieldGetAndBitwiseOrReleaseInt...OK +StaticFinalFieldGetAndBitwiseOrReleaseLong...OK +StaticFinalFieldGetAndBitwiseOrReleaseFloat...OK +StaticFinalFieldGetAndBitwiseOrReleaseDouble...OK +StaticFinalFieldGetAndBitwiseOrAcquireBoolean...OK +StaticFinalFieldGetAndBitwiseOrAcquireByte...OK +StaticFinalFieldGetAndBitwiseOrAcquireShort...OK +StaticFinalFieldGetAndBitwiseOrAcquireChar...OK +StaticFinalFieldGetAndBitwiseOrAcquireInt...OK +StaticFinalFieldGetAndBitwiseOrAcquireLong...OK +StaticFinalFieldGetAndBitwiseOrAcquireFloat...OK +StaticFinalFieldGetAndBitwiseOrAcquireDouble...OK +StaticFinalFieldGetAndBitwiseAndBoolean...OK +StaticFinalFieldGetAndBitwiseAndByte...OK +StaticFinalFieldGetAndBitwiseAndShort...OK +StaticFinalFieldGetAndBitwiseAndChar...OK +StaticFinalFieldGetAndBitwiseAndInt...OK +StaticFinalFieldGetAndBitwiseAndLong...OK +StaticFinalFieldGetAndBitwiseAndFloat...OK +StaticFinalFieldGetAndBitwiseAndDouble...OK +StaticFinalFieldGetAndBitwiseAndReleaseBoolean...OK +StaticFinalFieldGetAndBitwiseAndReleaseByte...OK +StaticFinalFieldGetAndBitwiseAndReleaseShort...OK +StaticFinalFieldGetAndBitwiseAndReleaseChar...OK +StaticFinalFieldGetAndBitwiseAndReleaseInt...OK +StaticFinalFieldGetAndBitwiseAndReleaseLong...OK +StaticFinalFieldGetAndBitwiseAndReleaseFloat...OK +StaticFinalFieldGetAndBitwiseAndReleaseDouble...OK +StaticFinalFieldGetAndBitwiseAndAcquireBoolean...OK +StaticFinalFieldGetAndBitwiseAndAcquireByte...OK +StaticFinalFieldGetAndBitwiseAndAcquireShort...OK +StaticFinalFieldGetAndBitwiseAndAcquireChar...OK +StaticFinalFieldGetAndBitwiseAndAcquireInt...OK +StaticFinalFieldGetAndBitwiseAndAcquireLong...OK +StaticFinalFieldGetAndBitwiseAndAcquireFloat...OK +StaticFinalFieldGetAndBitwiseAndAcquireDouble...OK +StaticFinalFieldGetAndBitwiseXorBoolean...OK +StaticFinalFieldGetAndBitwiseXorByte...OK +StaticFinalFieldGetAndBitwiseXorShort...OK +StaticFinalFieldGetAndBitwiseXorChar...OK +StaticFinalFieldGetAndBitwiseXorInt...OK +StaticFinalFieldGetAndBitwiseXorLong...OK +StaticFinalFieldGetAndBitwiseXorFloat...OK +StaticFinalFieldGetAndBitwiseXorDouble...OK +StaticFinalFieldGetAndBitwiseXorReleaseBoolean...OK +StaticFinalFieldGetAndBitwiseXorReleaseByte...OK +StaticFinalFieldGetAndBitwiseXorReleaseShort...OK +StaticFinalFieldGetAndBitwiseXorReleaseChar...OK +StaticFinalFieldGetAndBitwiseXorReleaseInt...OK +StaticFinalFieldGetAndBitwiseXorReleaseLong...OK +StaticFinalFieldGetAndBitwiseXorReleaseFloat...OK +StaticFinalFieldGetAndBitwiseXorReleaseDouble...OK +StaticFinalFieldGetAndBitwiseXorAcquireBoolean...OK +StaticFinalFieldGetAndBitwiseXorAcquireByte...OK +StaticFinalFieldGetAndBitwiseXorAcquireShort...OK +StaticFinalFieldGetAndBitwiseXorAcquireChar...OK +StaticFinalFieldGetAndBitwiseXorAcquireInt...OK +StaticFinalFieldGetAndBitwiseXorAcquireLong...OK +StaticFinalFieldGetAndBitwiseXorAcquireFloat...OK +StaticFinalFieldGetAndBitwiseXorAcquireDouble...OK +ArrayElementGetBoolean...OK +ArrayElementGetByte...OK +ArrayElementGetShort...OK +ArrayElementGetChar...OK +ArrayElementGetInt...OK +ArrayElementGetLong...OK +ArrayElementGetFloat...OK +ArrayElementGetDouble...OK +ArrayElementSetBoolean...OK +ArrayElementSetByte...OK +ArrayElementSetShort...OK +ArrayElementSetChar...OK +ArrayElementSetInt...OK +ArrayElementSetLong...OK +ArrayElementSetFloat...OK +ArrayElementSetDouble...OK +ArrayElementGetVolatileBoolean...OK +ArrayElementGetVolatileByte...OK +ArrayElementGetVolatileShort...OK +ArrayElementGetVolatileChar...OK +ArrayElementGetVolatileInt...OK +ArrayElementGetVolatileLong...OK +ArrayElementGetVolatileFloat...OK +ArrayElementGetVolatileDouble...OK +ArrayElementSetVolatileBoolean...OK +ArrayElementSetVolatileByte...OK +ArrayElementSetVolatileShort...OK +ArrayElementSetVolatileChar...OK +ArrayElementSetVolatileInt...OK +ArrayElementSetVolatileLong...OK +ArrayElementSetVolatileFloat...OK +ArrayElementSetVolatileDouble...OK +ArrayElementGetAcquireBoolean...OK +ArrayElementGetAcquireByte...OK +ArrayElementGetAcquireShort...OK +ArrayElementGetAcquireChar...OK +ArrayElementGetAcquireInt...OK +ArrayElementGetAcquireLong...OK +ArrayElementGetAcquireFloat...OK +ArrayElementGetAcquireDouble...OK +ArrayElementSetReleaseBoolean...OK +ArrayElementSetReleaseByte...OK +ArrayElementSetReleaseShort...OK +ArrayElementSetReleaseChar...OK +ArrayElementSetReleaseInt...OK +ArrayElementSetReleaseLong...OK +ArrayElementSetReleaseFloat...OK +ArrayElementSetReleaseDouble...OK +ArrayElementGetOpaqueBoolean...OK +ArrayElementGetOpaqueByte...OK +ArrayElementGetOpaqueShort...OK +ArrayElementGetOpaqueChar...OK +ArrayElementGetOpaqueInt...OK +ArrayElementGetOpaqueLong...OK +ArrayElementGetOpaqueFloat...OK +ArrayElementGetOpaqueDouble...OK +ArrayElementSetOpaqueBoolean...OK +ArrayElementSetOpaqueByte...OK +ArrayElementSetOpaqueShort...OK +ArrayElementSetOpaqueChar...OK +ArrayElementSetOpaqueInt...OK +ArrayElementSetOpaqueLong...OK +ArrayElementSetOpaqueFloat...OK +ArrayElementSetOpaqueDouble...OK +ArrayElementCompareAndSetBoolean...OK +ArrayElementCompareAndSetByte...OK +ArrayElementCompareAndSetShort...OK +ArrayElementCompareAndSetChar...OK +ArrayElementCompareAndSetInt...OK +ArrayElementCompareAndSetLong...OK +ArrayElementCompareAndSetFloat...OK +ArrayElementCompareAndSetDouble...OK +ArrayElementCompareAndExchangeBoolean...OK +ArrayElementCompareAndExchangeByte...OK +ArrayElementCompareAndExchangeShort...OK +ArrayElementCompareAndExchangeChar...OK +ArrayElementCompareAndExchangeInt...OK +ArrayElementCompareAndExchangeLong...OK +ArrayElementCompareAndExchangeFloat...OK +ArrayElementCompareAndExchangeDouble...OK +ArrayElementCompareAndExchangeAcquireBoolean...OK +ArrayElementCompareAndExchangeAcquireByte...OK +ArrayElementCompareAndExchangeAcquireShort...OK +ArrayElementCompareAndExchangeAcquireChar...OK +ArrayElementCompareAndExchangeAcquireInt...OK +ArrayElementCompareAndExchangeAcquireLong...OK +ArrayElementCompareAndExchangeAcquireFloat...OK +ArrayElementCompareAndExchangeAcquireDouble...OK +ArrayElementCompareAndExchangeReleaseBoolean...OK +ArrayElementCompareAndExchangeReleaseByte...OK +ArrayElementCompareAndExchangeReleaseShort...OK +ArrayElementCompareAndExchangeReleaseChar...OK +ArrayElementCompareAndExchangeReleaseInt...OK +ArrayElementCompareAndExchangeReleaseLong...OK +ArrayElementCompareAndExchangeReleaseFloat...OK +ArrayElementCompareAndExchangeReleaseDouble...OK +ArrayElementWeakCompareAndSetPlainBoolean...OK +ArrayElementWeakCompareAndSetPlainByte...OK +ArrayElementWeakCompareAndSetPlainShort...OK +ArrayElementWeakCompareAndSetPlainChar...OK +ArrayElementWeakCompareAndSetPlainInt...OK +ArrayElementWeakCompareAndSetPlainLong...OK +ArrayElementWeakCompareAndSetPlainFloat...OK +ArrayElementWeakCompareAndSetPlainDouble...OK +ArrayElementWeakCompareAndSetBoolean...OK +ArrayElementWeakCompareAndSetByte...OK +ArrayElementWeakCompareAndSetShort...OK +ArrayElementWeakCompareAndSetChar...OK +ArrayElementWeakCompareAndSetInt...OK +ArrayElementWeakCompareAndSetLong...OK +ArrayElementWeakCompareAndSetFloat...OK +ArrayElementWeakCompareAndSetDouble...OK +ArrayElementWeakCompareAndSetAcquireBoolean...OK +ArrayElementWeakCompareAndSetAcquireByte...OK +ArrayElementWeakCompareAndSetAcquireShort...OK +ArrayElementWeakCompareAndSetAcquireChar...OK +ArrayElementWeakCompareAndSetAcquireInt...OK +ArrayElementWeakCompareAndSetAcquireLong...OK +ArrayElementWeakCompareAndSetAcquireFloat...OK +ArrayElementWeakCompareAndSetAcquireDouble...OK +ArrayElementWeakCompareAndSetReleaseBoolean...OK +ArrayElementWeakCompareAndSetReleaseByte...OK +ArrayElementWeakCompareAndSetReleaseShort...OK +ArrayElementWeakCompareAndSetReleaseChar...OK +ArrayElementWeakCompareAndSetReleaseInt...OK +ArrayElementWeakCompareAndSetReleaseLong...OK +ArrayElementWeakCompareAndSetReleaseFloat...OK +ArrayElementWeakCompareAndSetReleaseDouble...OK +ArrayElementGetAndSetBoolean...OK +ArrayElementGetAndSetByte...OK +ArrayElementGetAndSetShort...OK +ArrayElementGetAndSetChar...OK +ArrayElementGetAndSetInt...OK +ArrayElementGetAndSetLong...OK +ArrayElementGetAndSetFloat...OK +ArrayElementGetAndSetDouble...OK +ArrayElementGetAndSetAcquireBoolean...OK +ArrayElementGetAndSetAcquireByte...OK +ArrayElementGetAndSetAcquireShort...OK +ArrayElementGetAndSetAcquireChar...OK +ArrayElementGetAndSetAcquireInt...OK +ArrayElementGetAndSetAcquireLong...OK +ArrayElementGetAndSetAcquireFloat...OK +ArrayElementGetAndSetAcquireDouble...OK +ArrayElementGetAndSetReleaseBoolean...OK +ArrayElementGetAndSetReleaseByte...OK +ArrayElementGetAndSetReleaseShort...OK +ArrayElementGetAndSetReleaseChar...OK +ArrayElementGetAndSetReleaseInt...OK +ArrayElementGetAndSetReleaseLong...OK +ArrayElementGetAndSetReleaseFloat...OK +ArrayElementGetAndSetReleaseDouble...OK +ArrayElementGetAndAddBoolean...OK +ArrayElementGetAndAddByte...OK +ArrayElementGetAndAddShort...OK +ArrayElementGetAndAddChar...OK +ArrayElementGetAndAddInt...OK +ArrayElementGetAndAddLong...OK +ArrayElementGetAndAddFloat...OK +ArrayElementGetAndAddDouble...OK +ArrayElementGetAndAddAcquireBoolean...OK +ArrayElementGetAndAddAcquireByte...OK +ArrayElementGetAndAddAcquireShort...OK +ArrayElementGetAndAddAcquireChar...OK +ArrayElementGetAndAddAcquireInt...OK +ArrayElementGetAndAddAcquireLong...OK +ArrayElementGetAndAddAcquireFloat...OK +ArrayElementGetAndAddAcquireDouble...OK +ArrayElementGetAndAddReleaseBoolean...OK +ArrayElementGetAndAddReleaseByte...OK +ArrayElementGetAndAddReleaseShort...OK +ArrayElementGetAndAddReleaseChar...OK +ArrayElementGetAndAddReleaseInt...OK +ArrayElementGetAndAddReleaseLong...OK +ArrayElementGetAndAddReleaseFloat...OK +ArrayElementGetAndAddReleaseDouble...OK +ArrayElementGetAndBitwiseOrBoolean...OK +ArrayElementGetAndBitwiseOrByte...OK +ArrayElementGetAndBitwiseOrShort...OK +ArrayElementGetAndBitwiseOrChar...OK +ArrayElementGetAndBitwiseOrInt...OK +ArrayElementGetAndBitwiseOrLong...OK +ArrayElementGetAndBitwiseOrFloat...OK +ArrayElementGetAndBitwiseOrDouble...OK +ArrayElementGetAndBitwiseOrReleaseBoolean...OK +ArrayElementGetAndBitwiseOrReleaseByte...OK +ArrayElementGetAndBitwiseOrReleaseShort...OK +ArrayElementGetAndBitwiseOrReleaseChar...OK +ArrayElementGetAndBitwiseOrReleaseInt...OK +ArrayElementGetAndBitwiseOrReleaseLong...OK +ArrayElementGetAndBitwiseOrReleaseFloat...OK +ArrayElementGetAndBitwiseOrReleaseDouble...OK +ArrayElementGetAndBitwiseOrAcquireBoolean...OK +ArrayElementGetAndBitwiseOrAcquireByte...OK +ArrayElementGetAndBitwiseOrAcquireShort...OK +ArrayElementGetAndBitwiseOrAcquireChar...OK +ArrayElementGetAndBitwiseOrAcquireInt...OK +ArrayElementGetAndBitwiseOrAcquireLong...OK +ArrayElementGetAndBitwiseOrAcquireFloat...OK +ArrayElementGetAndBitwiseOrAcquireDouble...OK +ArrayElementGetAndBitwiseAndBoolean...OK +ArrayElementGetAndBitwiseAndByte...OK +ArrayElementGetAndBitwiseAndShort...OK +ArrayElementGetAndBitwiseAndChar...OK +ArrayElementGetAndBitwiseAndInt...OK +ArrayElementGetAndBitwiseAndLong...OK +ArrayElementGetAndBitwiseAndFloat...OK +ArrayElementGetAndBitwiseAndDouble...OK +ArrayElementGetAndBitwiseAndReleaseBoolean...OK +ArrayElementGetAndBitwiseAndReleaseByte...OK +ArrayElementGetAndBitwiseAndReleaseShort...OK +ArrayElementGetAndBitwiseAndReleaseChar...OK +ArrayElementGetAndBitwiseAndReleaseInt...OK +ArrayElementGetAndBitwiseAndReleaseLong...OK +ArrayElementGetAndBitwiseAndReleaseFloat...OK +ArrayElementGetAndBitwiseAndReleaseDouble...OK +ArrayElementGetAndBitwiseAndAcquireBoolean...OK +ArrayElementGetAndBitwiseAndAcquireByte...OK +ArrayElementGetAndBitwiseAndAcquireShort...OK +ArrayElementGetAndBitwiseAndAcquireChar...OK +ArrayElementGetAndBitwiseAndAcquireInt...OK +ArrayElementGetAndBitwiseAndAcquireLong...OK +ArrayElementGetAndBitwiseAndAcquireFloat...OK +ArrayElementGetAndBitwiseAndAcquireDouble...OK +ArrayElementGetAndBitwiseXorBoolean...OK +ArrayElementGetAndBitwiseXorByte...OK +ArrayElementGetAndBitwiseXorShort...OK +ArrayElementGetAndBitwiseXorChar...OK +ArrayElementGetAndBitwiseXorInt...OK +ArrayElementGetAndBitwiseXorLong...OK +ArrayElementGetAndBitwiseXorFloat...OK +ArrayElementGetAndBitwiseXorDouble...OK +ArrayElementGetAndBitwiseXorReleaseBoolean...OK +ArrayElementGetAndBitwiseXorReleaseByte...OK +ArrayElementGetAndBitwiseXorReleaseShort...OK +ArrayElementGetAndBitwiseXorReleaseChar...OK +ArrayElementGetAndBitwiseXorReleaseInt...OK +ArrayElementGetAndBitwiseXorReleaseLong...OK +ArrayElementGetAndBitwiseXorReleaseFloat...OK +ArrayElementGetAndBitwiseXorReleaseDouble...OK +ArrayElementGetAndBitwiseXorAcquireBoolean...OK +ArrayElementGetAndBitwiseXorAcquireByte...OK +ArrayElementGetAndBitwiseXorAcquireShort...OK +ArrayElementGetAndBitwiseXorAcquireChar...OK +ArrayElementGetAndBitwiseXorAcquireInt...OK +ArrayElementGetAndBitwiseXorAcquireLong...OK +ArrayElementGetAndBitwiseXorAcquireFloat...OK +ArrayElementGetAndBitwiseXorAcquireDouble...OK +ByteArrayViewLEGetShort...OK +ByteArrayViewLEGetChar...OK +ByteArrayViewLEGetInt...OK +ByteArrayViewLEGetLong...OK +ByteArrayViewLEGetFloat...OK +ByteArrayViewLEGetDouble...OK +ByteArrayViewLESetShort...OK +ByteArrayViewLESetChar...OK +ByteArrayViewLESetInt...OK +ByteArrayViewLESetLong...OK +ByteArrayViewLESetFloat...OK +ByteArrayViewLESetDouble...OK +ByteArrayViewLEGetVolatileShort...OK +ByteArrayViewLEGetVolatileChar...OK +ByteArrayViewLEGetVolatileInt...OK +ByteArrayViewLEGetVolatileLong...OK +ByteArrayViewLEGetVolatileFloat...OK +ByteArrayViewLEGetVolatileDouble...OK +ByteArrayViewLESetVolatileShort...OK +ByteArrayViewLESetVolatileChar...OK +ByteArrayViewLESetVolatileInt...OK +ByteArrayViewLESetVolatileLong...OK +ByteArrayViewLESetVolatileFloat...OK +ByteArrayViewLESetVolatileDouble...OK +ByteArrayViewLEGetAcquireShort...OK +ByteArrayViewLEGetAcquireChar...OK +ByteArrayViewLEGetAcquireInt...OK +ByteArrayViewLEGetAcquireLong...OK +ByteArrayViewLEGetAcquireFloat...OK +ByteArrayViewLEGetAcquireDouble...OK +ByteArrayViewLESetReleaseShort...OK +ByteArrayViewLESetReleaseChar...OK +ByteArrayViewLESetReleaseInt...OK +ByteArrayViewLESetReleaseLong...OK +ByteArrayViewLESetReleaseFloat...OK +ByteArrayViewLESetReleaseDouble...OK +ByteArrayViewLEGetOpaqueShort...OK +ByteArrayViewLEGetOpaqueChar...OK +ByteArrayViewLEGetOpaqueInt...OK +ByteArrayViewLEGetOpaqueLong...OK +ByteArrayViewLEGetOpaqueFloat...OK +ByteArrayViewLEGetOpaqueDouble...OK +ByteArrayViewLESetOpaqueShort...OK +ByteArrayViewLESetOpaqueChar...OK +ByteArrayViewLESetOpaqueInt...OK +ByteArrayViewLESetOpaqueLong...OK +ByteArrayViewLESetOpaqueFloat...OK +ByteArrayViewLESetOpaqueDouble...OK +ByteArrayViewLECompareAndSetShort...OK +ByteArrayViewLECompareAndSetChar...OK +ByteArrayViewLECompareAndSetInt...OK +ByteArrayViewLECompareAndSetLong...OK +ByteArrayViewLECompareAndSetFloat...OK +ByteArrayViewLECompareAndSetDouble...OK +ByteArrayViewLECompareAndExchangeShort...OK +ByteArrayViewLECompareAndExchangeChar...OK +ByteArrayViewLECompareAndExchangeInt...OK +ByteArrayViewLECompareAndExchangeLong...OK +ByteArrayViewLECompareAndExchangeFloat...OK +ByteArrayViewLECompareAndExchangeDouble...OK +ByteArrayViewLECompareAndExchangeAcquireShort...OK +ByteArrayViewLECompareAndExchangeAcquireChar...OK +ByteArrayViewLECompareAndExchangeAcquireInt...OK +ByteArrayViewLECompareAndExchangeAcquireLong...OK +ByteArrayViewLECompareAndExchangeAcquireFloat...OK +ByteArrayViewLECompareAndExchangeAcquireDouble...OK +ByteArrayViewLECompareAndExchangeReleaseShort...OK +ByteArrayViewLECompareAndExchangeReleaseChar...OK +ByteArrayViewLECompareAndExchangeReleaseInt...OK +ByteArrayViewLECompareAndExchangeReleaseLong...OK +ByteArrayViewLECompareAndExchangeReleaseFloat...OK +ByteArrayViewLECompareAndExchangeReleaseDouble...OK +ByteArrayViewLEWeakCompareAndSetPlainShort...OK +ByteArrayViewLEWeakCompareAndSetPlainChar...OK +ByteArrayViewLEWeakCompareAndSetPlainInt...OK +ByteArrayViewLEWeakCompareAndSetPlainLong...OK +ByteArrayViewLEWeakCompareAndSetPlainFloat...OK +ByteArrayViewLEWeakCompareAndSetPlainDouble...OK +ByteArrayViewLEWeakCompareAndSetShort...OK +ByteArrayViewLEWeakCompareAndSetChar...OK +ByteArrayViewLEWeakCompareAndSetInt...OK +ByteArrayViewLEWeakCompareAndSetLong...OK +ByteArrayViewLEWeakCompareAndSetFloat...OK +ByteArrayViewLEWeakCompareAndSetDouble...OK +ByteArrayViewLEWeakCompareAndSetAcquireShort...OK +ByteArrayViewLEWeakCompareAndSetAcquireChar...OK +ByteArrayViewLEWeakCompareAndSetAcquireInt...OK +ByteArrayViewLEWeakCompareAndSetAcquireLong...OK +ByteArrayViewLEWeakCompareAndSetAcquireFloat...OK +ByteArrayViewLEWeakCompareAndSetAcquireDouble...OK +ByteArrayViewLEWeakCompareAndSetReleaseShort...OK +ByteArrayViewLEWeakCompareAndSetReleaseChar...OK +ByteArrayViewLEWeakCompareAndSetReleaseInt...OK +ByteArrayViewLEWeakCompareAndSetReleaseLong...OK +ByteArrayViewLEWeakCompareAndSetReleaseFloat...OK +ByteArrayViewLEWeakCompareAndSetReleaseDouble...OK +ByteArrayViewLEGetAndSetShort...OK +ByteArrayViewLEGetAndSetChar...OK +ByteArrayViewLEGetAndSetInt...OK +ByteArrayViewLEGetAndSetLong...OK +ByteArrayViewLEGetAndSetFloat...OK +ByteArrayViewLEGetAndSetDouble...OK +ByteArrayViewLEGetAndSetAcquireShort...OK +ByteArrayViewLEGetAndSetAcquireChar...OK +ByteArrayViewLEGetAndSetAcquireInt...OK +ByteArrayViewLEGetAndSetAcquireLong...OK +ByteArrayViewLEGetAndSetAcquireFloat...OK +ByteArrayViewLEGetAndSetAcquireDouble...OK +ByteArrayViewLEGetAndSetReleaseShort...OK +ByteArrayViewLEGetAndSetReleaseChar...OK +ByteArrayViewLEGetAndSetReleaseInt...OK +ByteArrayViewLEGetAndSetReleaseLong...OK +ByteArrayViewLEGetAndSetReleaseFloat...OK +ByteArrayViewLEGetAndSetReleaseDouble...OK +ByteArrayViewLEGetAndAddShort...OK +ByteArrayViewLEGetAndAddChar...OK +ByteArrayViewLEGetAndAddInt...OK +ByteArrayViewLEGetAndAddLong...OK +ByteArrayViewLEGetAndAddFloat...OK +ByteArrayViewLEGetAndAddDouble...OK +ByteArrayViewLEGetAndAddAcquireShort...OK +ByteArrayViewLEGetAndAddAcquireChar...OK +ByteArrayViewLEGetAndAddAcquireInt...OK +ByteArrayViewLEGetAndAddAcquireLong...OK +ByteArrayViewLEGetAndAddAcquireFloat...OK +ByteArrayViewLEGetAndAddAcquireDouble...OK +ByteArrayViewLEGetAndAddReleaseShort...OK +ByteArrayViewLEGetAndAddReleaseChar...OK +ByteArrayViewLEGetAndAddReleaseInt...OK +ByteArrayViewLEGetAndAddReleaseLong...OK +ByteArrayViewLEGetAndAddReleaseFloat...OK +ByteArrayViewLEGetAndAddReleaseDouble...OK +ByteArrayViewLEGetAndBitwiseOrShort...OK +ByteArrayViewLEGetAndBitwiseOrChar...OK +ByteArrayViewLEGetAndBitwiseOrInt...OK +ByteArrayViewLEGetAndBitwiseOrLong...OK +ByteArrayViewLEGetAndBitwiseOrFloat...OK +ByteArrayViewLEGetAndBitwiseOrDouble...OK +ByteArrayViewLEGetAndBitwiseOrReleaseShort...OK +ByteArrayViewLEGetAndBitwiseOrReleaseChar...OK +ByteArrayViewLEGetAndBitwiseOrReleaseInt...OK +ByteArrayViewLEGetAndBitwiseOrReleaseLong...OK +ByteArrayViewLEGetAndBitwiseOrReleaseFloat...OK +ByteArrayViewLEGetAndBitwiseOrReleaseDouble...OK +ByteArrayViewLEGetAndBitwiseOrAcquireShort...OK +ByteArrayViewLEGetAndBitwiseOrAcquireChar...OK +ByteArrayViewLEGetAndBitwiseOrAcquireInt...OK +ByteArrayViewLEGetAndBitwiseOrAcquireLong...OK +ByteArrayViewLEGetAndBitwiseOrAcquireFloat...OK +ByteArrayViewLEGetAndBitwiseOrAcquireDouble...OK +ByteArrayViewLEGetAndBitwiseAndShort...OK +ByteArrayViewLEGetAndBitwiseAndChar...OK +ByteArrayViewLEGetAndBitwiseAndInt...OK +ByteArrayViewLEGetAndBitwiseAndLong...OK +ByteArrayViewLEGetAndBitwiseAndFloat...OK +ByteArrayViewLEGetAndBitwiseAndDouble...OK +ByteArrayViewLEGetAndBitwiseAndReleaseShort...OK +ByteArrayViewLEGetAndBitwiseAndReleaseChar...OK +ByteArrayViewLEGetAndBitwiseAndReleaseInt...OK +ByteArrayViewLEGetAndBitwiseAndReleaseLong...OK +ByteArrayViewLEGetAndBitwiseAndReleaseFloat...OK +ByteArrayViewLEGetAndBitwiseAndReleaseDouble...OK +ByteArrayViewLEGetAndBitwiseAndAcquireShort...OK +ByteArrayViewLEGetAndBitwiseAndAcquireChar...OK +ByteArrayViewLEGetAndBitwiseAndAcquireInt...OK +ByteArrayViewLEGetAndBitwiseAndAcquireLong...OK +ByteArrayViewLEGetAndBitwiseAndAcquireFloat...OK +ByteArrayViewLEGetAndBitwiseAndAcquireDouble...OK +ByteArrayViewLEGetAndBitwiseXorShort...OK +ByteArrayViewLEGetAndBitwiseXorChar...OK +ByteArrayViewLEGetAndBitwiseXorInt...OK +ByteArrayViewLEGetAndBitwiseXorLong...OK +ByteArrayViewLEGetAndBitwiseXorFloat...OK +ByteArrayViewLEGetAndBitwiseXorDouble...OK +ByteArrayViewLEGetAndBitwiseXorReleaseShort...OK +ByteArrayViewLEGetAndBitwiseXorReleaseChar...OK +ByteArrayViewLEGetAndBitwiseXorReleaseInt...OK +ByteArrayViewLEGetAndBitwiseXorReleaseLong...OK +ByteArrayViewLEGetAndBitwiseXorReleaseFloat...OK +ByteArrayViewLEGetAndBitwiseXorReleaseDouble...OK +ByteArrayViewLEGetAndBitwiseXorAcquireShort...OK +ByteArrayViewLEGetAndBitwiseXorAcquireChar...OK +ByteArrayViewLEGetAndBitwiseXorAcquireInt...OK +ByteArrayViewLEGetAndBitwiseXorAcquireLong...OK +ByteArrayViewLEGetAndBitwiseXorAcquireFloat...OK +ByteArrayViewLEGetAndBitwiseXorAcquireDouble...OK +ByteArrayViewBEGetShort...OK +ByteArrayViewBEGetChar...OK +ByteArrayViewBEGetInt...OK +ByteArrayViewBEGetLong...OK +ByteArrayViewBEGetFloat...OK +ByteArrayViewBEGetDouble...OK +ByteArrayViewBESetShort...OK +ByteArrayViewBESetChar...OK +ByteArrayViewBESetInt...OK +ByteArrayViewBESetLong...OK +ByteArrayViewBESetFloat...OK +ByteArrayViewBESetDouble...OK +ByteArrayViewBEGetVolatileShort...OK +ByteArrayViewBEGetVolatileChar...OK +ByteArrayViewBEGetVolatileInt...OK +ByteArrayViewBEGetVolatileLong...OK +ByteArrayViewBEGetVolatileFloat...OK +ByteArrayViewBEGetVolatileDouble...OK +ByteArrayViewBESetVolatileShort...OK +ByteArrayViewBESetVolatileChar...OK +ByteArrayViewBESetVolatileInt...OK +ByteArrayViewBESetVolatileLong...OK +ByteArrayViewBESetVolatileFloat...OK +ByteArrayViewBESetVolatileDouble...OK +ByteArrayViewBEGetAcquireShort...OK +ByteArrayViewBEGetAcquireChar...OK +ByteArrayViewBEGetAcquireInt...OK +ByteArrayViewBEGetAcquireLong...OK +ByteArrayViewBEGetAcquireFloat...OK +ByteArrayViewBEGetAcquireDouble...OK +ByteArrayViewBESetReleaseShort...OK +ByteArrayViewBESetReleaseChar...OK +ByteArrayViewBESetReleaseInt...OK +ByteArrayViewBESetReleaseLong...OK +ByteArrayViewBESetReleaseFloat...OK +ByteArrayViewBESetReleaseDouble...OK +ByteArrayViewBEGetOpaqueShort...OK +ByteArrayViewBEGetOpaqueChar...OK +ByteArrayViewBEGetOpaqueInt...OK +ByteArrayViewBEGetOpaqueLong...OK +ByteArrayViewBEGetOpaqueFloat...OK +ByteArrayViewBEGetOpaqueDouble...OK +ByteArrayViewBESetOpaqueShort...OK +ByteArrayViewBESetOpaqueChar...OK +ByteArrayViewBESetOpaqueInt...OK +ByteArrayViewBESetOpaqueLong...OK +ByteArrayViewBESetOpaqueFloat...OK +ByteArrayViewBESetOpaqueDouble...OK +ByteArrayViewBECompareAndSetShort...OK +ByteArrayViewBECompareAndSetChar...OK +ByteArrayViewBECompareAndSetInt...OK +ByteArrayViewBECompareAndSetLong...OK +ByteArrayViewBECompareAndSetFloat...OK +ByteArrayViewBECompareAndSetDouble...OK +ByteArrayViewBECompareAndExchangeShort...OK +ByteArrayViewBECompareAndExchangeChar...OK +ByteArrayViewBECompareAndExchangeInt...OK +ByteArrayViewBECompareAndExchangeLong...OK +ByteArrayViewBECompareAndExchangeFloat...OK +ByteArrayViewBECompareAndExchangeDouble...OK +ByteArrayViewBECompareAndExchangeAcquireShort...OK +ByteArrayViewBECompareAndExchangeAcquireChar...OK +ByteArrayViewBECompareAndExchangeAcquireInt...OK +ByteArrayViewBECompareAndExchangeAcquireLong...OK +ByteArrayViewBECompareAndExchangeAcquireFloat...OK +ByteArrayViewBECompareAndExchangeAcquireDouble...OK +ByteArrayViewBECompareAndExchangeReleaseShort...OK +ByteArrayViewBECompareAndExchangeReleaseChar...OK +ByteArrayViewBECompareAndExchangeReleaseInt...OK +ByteArrayViewBECompareAndExchangeReleaseLong...OK +ByteArrayViewBECompareAndExchangeReleaseFloat...OK +ByteArrayViewBECompareAndExchangeReleaseDouble...OK +ByteArrayViewBEWeakCompareAndSetPlainShort...OK +ByteArrayViewBEWeakCompareAndSetPlainChar...OK +ByteArrayViewBEWeakCompareAndSetPlainInt...OK +ByteArrayViewBEWeakCompareAndSetPlainLong...OK +ByteArrayViewBEWeakCompareAndSetPlainFloat...OK +ByteArrayViewBEWeakCompareAndSetPlainDouble...OK +ByteArrayViewBEWeakCompareAndSetShort...OK +ByteArrayViewBEWeakCompareAndSetChar...OK +ByteArrayViewBEWeakCompareAndSetInt...OK +ByteArrayViewBEWeakCompareAndSetLong...OK +ByteArrayViewBEWeakCompareAndSetFloat...OK +ByteArrayViewBEWeakCompareAndSetDouble...OK +ByteArrayViewBEWeakCompareAndSetAcquireShort...OK +ByteArrayViewBEWeakCompareAndSetAcquireChar...OK +ByteArrayViewBEWeakCompareAndSetAcquireInt...OK +ByteArrayViewBEWeakCompareAndSetAcquireLong...OK +ByteArrayViewBEWeakCompareAndSetAcquireFloat...OK +ByteArrayViewBEWeakCompareAndSetAcquireDouble...OK +ByteArrayViewBEWeakCompareAndSetReleaseShort...OK +ByteArrayViewBEWeakCompareAndSetReleaseChar...OK +ByteArrayViewBEWeakCompareAndSetReleaseInt...OK +ByteArrayViewBEWeakCompareAndSetReleaseLong...OK +ByteArrayViewBEWeakCompareAndSetReleaseFloat...OK +ByteArrayViewBEWeakCompareAndSetReleaseDouble...OK +ByteArrayViewBEGetAndSetShort...OK +ByteArrayViewBEGetAndSetChar...OK +ByteArrayViewBEGetAndSetInt...OK +ByteArrayViewBEGetAndSetLong...OK +ByteArrayViewBEGetAndSetFloat...OK +ByteArrayViewBEGetAndSetDouble...OK +ByteArrayViewBEGetAndSetAcquireShort...OK +ByteArrayViewBEGetAndSetAcquireChar...OK +ByteArrayViewBEGetAndSetAcquireInt...OK +ByteArrayViewBEGetAndSetAcquireLong...OK +ByteArrayViewBEGetAndSetAcquireFloat...OK +ByteArrayViewBEGetAndSetAcquireDouble...OK +ByteArrayViewBEGetAndSetReleaseShort...OK +ByteArrayViewBEGetAndSetReleaseChar...OK +ByteArrayViewBEGetAndSetReleaseInt...OK +ByteArrayViewBEGetAndSetReleaseLong...OK +ByteArrayViewBEGetAndSetReleaseFloat...OK +ByteArrayViewBEGetAndSetReleaseDouble...OK +ByteArrayViewBEGetAndAddShort...OK +ByteArrayViewBEGetAndAddChar...OK +ByteArrayViewBEGetAndAddInt...OK +ByteArrayViewBEGetAndAddLong...OK +ByteArrayViewBEGetAndAddFloat...OK +ByteArrayViewBEGetAndAddDouble...OK +ByteArrayViewBEGetAndAddAcquireShort...OK +ByteArrayViewBEGetAndAddAcquireChar...OK +ByteArrayViewBEGetAndAddAcquireInt...OK +ByteArrayViewBEGetAndAddAcquireLong...OK +ByteArrayViewBEGetAndAddAcquireFloat...OK +ByteArrayViewBEGetAndAddAcquireDouble...OK +ByteArrayViewBEGetAndAddReleaseShort...OK +ByteArrayViewBEGetAndAddReleaseChar...OK +ByteArrayViewBEGetAndAddReleaseInt...OK +ByteArrayViewBEGetAndAddReleaseLong...OK +ByteArrayViewBEGetAndAddReleaseFloat...OK +ByteArrayViewBEGetAndAddReleaseDouble...OK +ByteArrayViewBEGetAndBitwiseOrShort...OK +ByteArrayViewBEGetAndBitwiseOrChar...OK +ByteArrayViewBEGetAndBitwiseOrInt...OK +ByteArrayViewBEGetAndBitwiseOrLong...OK +ByteArrayViewBEGetAndBitwiseOrFloat...OK +ByteArrayViewBEGetAndBitwiseOrDouble...OK +ByteArrayViewBEGetAndBitwiseOrReleaseShort...OK +ByteArrayViewBEGetAndBitwiseOrReleaseChar...OK +ByteArrayViewBEGetAndBitwiseOrReleaseInt...OK +ByteArrayViewBEGetAndBitwiseOrReleaseLong...OK +ByteArrayViewBEGetAndBitwiseOrReleaseFloat...OK +ByteArrayViewBEGetAndBitwiseOrReleaseDouble...OK +ByteArrayViewBEGetAndBitwiseOrAcquireShort...OK +ByteArrayViewBEGetAndBitwiseOrAcquireChar...OK +ByteArrayViewBEGetAndBitwiseOrAcquireInt...OK +ByteArrayViewBEGetAndBitwiseOrAcquireLong...OK +ByteArrayViewBEGetAndBitwiseOrAcquireFloat...OK +ByteArrayViewBEGetAndBitwiseOrAcquireDouble...OK +ByteArrayViewBEGetAndBitwiseAndShort...OK +ByteArrayViewBEGetAndBitwiseAndChar...OK +ByteArrayViewBEGetAndBitwiseAndInt...OK +ByteArrayViewBEGetAndBitwiseAndLong...OK +ByteArrayViewBEGetAndBitwiseAndFloat...OK +ByteArrayViewBEGetAndBitwiseAndDouble...OK +ByteArrayViewBEGetAndBitwiseAndReleaseShort...OK +ByteArrayViewBEGetAndBitwiseAndReleaseChar...OK +ByteArrayViewBEGetAndBitwiseAndReleaseInt...OK +ByteArrayViewBEGetAndBitwiseAndReleaseLong...OK +ByteArrayViewBEGetAndBitwiseAndReleaseFloat...OK +ByteArrayViewBEGetAndBitwiseAndReleaseDouble...OK +ByteArrayViewBEGetAndBitwiseAndAcquireShort...OK +ByteArrayViewBEGetAndBitwiseAndAcquireChar...OK +ByteArrayViewBEGetAndBitwiseAndAcquireInt...OK +ByteArrayViewBEGetAndBitwiseAndAcquireLong...OK +ByteArrayViewBEGetAndBitwiseAndAcquireFloat...OK +ByteArrayViewBEGetAndBitwiseAndAcquireDouble...OK +ByteArrayViewBEGetAndBitwiseXorShort...OK +ByteArrayViewBEGetAndBitwiseXorChar...OK +ByteArrayViewBEGetAndBitwiseXorInt...OK +ByteArrayViewBEGetAndBitwiseXorLong...OK +ByteArrayViewBEGetAndBitwiseXorFloat...OK +ByteArrayViewBEGetAndBitwiseXorDouble...OK +ByteArrayViewBEGetAndBitwiseXorReleaseShort...OK +ByteArrayViewBEGetAndBitwiseXorReleaseChar...OK +ByteArrayViewBEGetAndBitwiseXorReleaseInt...OK +ByteArrayViewBEGetAndBitwiseXorReleaseLong...OK +ByteArrayViewBEGetAndBitwiseXorReleaseFloat...OK +ByteArrayViewBEGetAndBitwiseXorReleaseDouble...OK +ByteArrayViewBEGetAndBitwiseXorAcquireShort...OK +ByteArrayViewBEGetAndBitwiseXorAcquireChar...OK +ByteArrayViewBEGetAndBitwiseXorAcquireInt...OK +ByteArrayViewBEGetAndBitwiseXorAcquireLong...OK +ByteArrayViewBEGetAndBitwiseXorAcquireFloat...OK +ByteArrayViewBEGetAndBitwiseXorAcquireDouble...OK +DirectByteBufferViewLEGetShort...OK +DirectByteBufferViewLEGetChar...OK +DirectByteBufferViewLEGetInt...OK +DirectByteBufferViewLEGetLong...OK +DirectByteBufferViewLEGetFloat...OK +DirectByteBufferViewLEGetDouble...OK +DirectByteBufferViewLESetShort...OK +DirectByteBufferViewLESetChar...OK +DirectByteBufferViewLESetInt...OK +DirectByteBufferViewLESetLong...OK +DirectByteBufferViewLESetFloat...OK +DirectByteBufferViewLESetDouble...OK +DirectByteBufferViewLEGetVolatileShort...OK +DirectByteBufferViewLEGetVolatileChar...OK +DirectByteBufferViewLEGetVolatileInt...OK +DirectByteBufferViewLEGetVolatileLong...OK +DirectByteBufferViewLEGetVolatileFloat...OK +DirectByteBufferViewLEGetVolatileDouble...OK +DirectByteBufferViewLESetVolatileShort...OK +DirectByteBufferViewLESetVolatileChar...OK +DirectByteBufferViewLESetVolatileInt...OK +DirectByteBufferViewLESetVolatileLong...OK +DirectByteBufferViewLESetVolatileFloat...OK +DirectByteBufferViewLESetVolatileDouble...OK +DirectByteBufferViewLEGetAcquireShort...OK +DirectByteBufferViewLEGetAcquireChar...OK +DirectByteBufferViewLEGetAcquireInt...OK +DirectByteBufferViewLEGetAcquireLong...OK +DirectByteBufferViewLEGetAcquireFloat...OK +DirectByteBufferViewLEGetAcquireDouble...OK +DirectByteBufferViewLESetReleaseShort...OK +DirectByteBufferViewLESetReleaseChar...OK +DirectByteBufferViewLESetReleaseInt...OK +DirectByteBufferViewLESetReleaseLong...OK +DirectByteBufferViewLESetReleaseFloat...OK +DirectByteBufferViewLESetReleaseDouble...OK +DirectByteBufferViewLEGetOpaqueShort...OK +DirectByteBufferViewLEGetOpaqueChar...OK +DirectByteBufferViewLEGetOpaqueInt...OK +DirectByteBufferViewLEGetOpaqueLong...OK +DirectByteBufferViewLEGetOpaqueFloat...OK +DirectByteBufferViewLEGetOpaqueDouble...OK +DirectByteBufferViewLESetOpaqueShort...OK +DirectByteBufferViewLESetOpaqueChar...OK +DirectByteBufferViewLESetOpaqueInt...OK +DirectByteBufferViewLESetOpaqueLong...OK +DirectByteBufferViewLESetOpaqueFloat...OK +DirectByteBufferViewLESetOpaqueDouble...OK +DirectByteBufferViewLECompareAndSetShort...OK +DirectByteBufferViewLECompareAndSetChar...OK +DirectByteBufferViewLECompareAndSetInt...OK +DirectByteBufferViewLECompareAndSetLong...OK +DirectByteBufferViewLECompareAndSetFloat...OK +DirectByteBufferViewLECompareAndSetDouble...OK +DirectByteBufferViewLECompareAndExchangeShort...OK +DirectByteBufferViewLECompareAndExchangeChar...OK +DirectByteBufferViewLECompareAndExchangeInt...OK +DirectByteBufferViewLECompareAndExchangeLong...OK +DirectByteBufferViewLECompareAndExchangeFloat...OK +DirectByteBufferViewLECompareAndExchangeDouble...OK +DirectByteBufferViewLECompareAndExchangeAcquireShort...OK +DirectByteBufferViewLECompareAndExchangeAcquireChar...OK +DirectByteBufferViewLECompareAndExchangeAcquireInt...OK +DirectByteBufferViewLECompareAndExchangeAcquireLong...OK +DirectByteBufferViewLECompareAndExchangeAcquireFloat...OK +DirectByteBufferViewLECompareAndExchangeAcquireDouble...OK +DirectByteBufferViewLECompareAndExchangeReleaseShort...OK +DirectByteBufferViewLECompareAndExchangeReleaseChar...OK +DirectByteBufferViewLECompareAndExchangeReleaseInt...OK +DirectByteBufferViewLECompareAndExchangeReleaseLong...OK +DirectByteBufferViewLECompareAndExchangeReleaseFloat...OK +DirectByteBufferViewLECompareAndExchangeReleaseDouble...OK +DirectByteBufferViewLEWeakCompareAndSetPlainShort...OK +DirectByteBufferViewLEWeakCompareAndSetPlainChar...OK +DirectByteBufferViewLEWeakCompareAndSetPlainInt...OK +DirectByteBufferViewLEWeakCompareAndSetPlainLong...OK +DirectByteBufferViewLEWeakCompareAndSetPlainFloat...OK +DirectByteBufferViewLEWeakCompareAndSetPlainDouble...OK +DirectByteBufferViewLEWeakCompareAndSetShort...OK +DirectByteBufferViewLEWeakCompareAndSetChar...OK +DirectByteBufferViewLEWeakCompareAndSetInt...OK +DirectByteBufferViewLEWeakCompareAndSetLong...OK +DirectByteBufferViewLEWeakCompareAndSetFloat...OK +DirectByteBufferViewLEWeakCompareAndSetDouble...OK +DirectByteBufferViewLEWeakCompareAndSetAcquireShort...OK +DirectByteBufferViewLEWeakCompareAndSetAcquireChar...OK +DirectByteBufferViewLEWeakCompareAndSetAcquireInt...OK +DirectByteBufferViewLEWeakCompareAndSetAcquireLong...OK +DirectByteBufferViewLEWeakCompareAndSetAcquireFloat...OK +DirectByteBufferViewLEWeakCompareAndSetAcquireDouble...OK +DirectByteBufferViewLEWeakCompareAndSetReleaseShort...OK +DirectByteBufferViewLEWeakCompareAndSetReleaseChar...OK +DirectByteBufferViewLEWeakCompareAndSetReleaseInt...OK +DirectByteBufferViewLEWeakCompareAndSetReleaseLong...OK +DirectByteBufferViewLEWeakCompareAndSetReleaseFloat...OK +DirectByteBufferViewLEWeakCompareAndSetReleaseDouble...OK +DirectByteBufferViewLEGetAndSetShort...OK +DirectByteBufferViewLEGetAndSetChar...OK +DirectByteBufferViewLEGetAndSetInt...OK +DirectByteBufferViewLEGetAndSetLong...OK +DirectByteBufferViewLEGetAndSetFloat...OK +DirectByteBufferViewLEGetAndSetDouble...OK +DirectByteBufferViewLEGetAndSetAcquireShort...OK +DirectByteBufferViewLEGetAndSetAcquireChar...OK +DirectByteBufferViewLEGetAndSetAcquireInt...OK +DirectByteBufferViewLEGetAndSetAcquireLong...OK +DirectByteBufferViewLEGetAndSetAcquireFloat...OK +DirectByteBufferViewLEGetAndSetAcquireDouble...OK +DirectByteBufferViewLEGetAndSetReleaseShort...OK +DirectByteBufferViewLEGetAndSetReleaseChar...OK +DirectByteBufferViewLEGetAndSetReleaseInt...OK +DirectByteBufferViewLEGetAndSetReleaseLong...OK +DirectByteBufferViewLEGetAndSetReleaseFloat...OK +DirectByteBufferViewLEGetAndSetReleaseDouble...OK +DirectByteBufferViewLEGetAndAddShort...OK +DirectByteBufferViewLEGetAndAddChar...OK +DirectByteBufferViewLEGetAndAddInt...OK +DirectByteBufferViewLEGetAndAddLong...OK +DirectByteBufferViewLEGetAndAddFloat...OK +DirectByteBufferViewLEGetAndAddDouble...OK +DirectByteBufferViewLEGetAndAddAcquireShort...OK +DirectByteBufferViewLEGetAndAddAcquireChar...OK +DirectByteBufferViewLEGetAndAddAcquireInt...OK +DirectByteBufferViewLEGetAndAddAcquireLong...OK +DirectByteBufferViewLEGetAndAddAcquireFloat...OK +DirectByteBufferViewLEGetAndAddAcquireDouble...OK +DirectByteBufferViewLEGetAndAddReleaseShort...OK +DirectByteBufferViewLEGetAndAddReleaseChar...OK +DirectByteBufferViewLEGetAndAddReleaseInt...OK +DirectByteBufferViewLEGetAndAddReleaseLong...OK +DirectByteBufferViewLEGetAndAddReleaseFloat...OK +DirectByteBufferViewLEGetAndAddReleaseDouble...OK +DirectByteBufferViewLEGetAndBitwiseOrShort...OK +DirectByteBufferViewLEGetAndBitwiseOrChar...OK +DirectByteBufferViewLEGetAndBitwiseOrInt...OK +DirectByteBufferViewLEGetAndBitwiseOrLong...OK +DirectByteBufferViewLEGetAndBitwiseOrFloat...OK +DirectByteBufferViewLEGetAndBitwiseOrDouble...OK +DirectByteBufferViewLEGetAndBitwiseOrReleaseShort...OK +DirectByteBufferViewLEGetAndBitwiseOrReleaseChar...OK +DirectByteBufferViewLEGetAndBitwiseOrReleaseInt...OK +DirectByteBufferViewLEGetAndBitwiseOrReleaseLong...OK +DirectByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK +DirectByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK +DirectByteBufferViewLEGetAndBitwiseOrAcquireShort...OK +DirectByteBufferViewLEGetAndBitwiseOrAcquireChar...OK +DirectByteBufferViewLEGetAndBitwiseOrAcquireInt...OK +DirectByteBufferViewLEGetAndBitwiseOrAcquireLong...OK +DirectByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK +DirectByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK +DirectByteBufferViewLEGetAndBitwiseAndShort...OK +DirectByteBufferViewLEGetAndBitwiseAndChar...OK +DirectByteBufferViewLEGetAndBitwiseAndInt...OK +DirectByteBufferViewLEGetAndBitwiseAndLong...OK +DirectByteBufferViewLEGetAndBitwiseAndFloat...OK +DirectByteBufferViewLEGetAndBitwiseAndDouble...OK +DirectByteBufferViewLEGetAndBitwiseAndReleaseShort...OK +DirectByteBufferViewLEGetAndBitwiseAndReleaseChar...OK +DirectByteBufferViewLEGetAndBitwiseAndReleaseInt...OK +DirectByteBufferViewLEGetAndBitwiseAndReleaseLong...OK +DirectByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK +DirectByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK +DirectByteBufferViewLEGetAndBitwiseAndAcquireShort...OK +DirectByteBufferViewLEGetAndBitwiseAndAcquireChar...OK +DirectByteBufferViewLEGetAndBitwiseAndAcquireInt...OK +DirectByteBufferViewLEGetAndBitwiseAndAcquireLong...OK +DirectByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK +DirectByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK +DirectByteBufferViewLEGetAndBitwiseXorShort...OK +DirectByteBufferViewLEGetAndBitwiseXorChar...OK +DirectByteBufferViewLEGetAndBitwiseXorInt...OK +DirectByteBufferViewLEGetAndBitwiseXorLong...OK +DirectByteBufferViewLEGetAndBitwiseXorFloat...OK +DirectByteBufferViewLEGetAndBitwiseXorDouble...OK +DirectByteBufferViewLEGetAndBitwiseXorReleaseShort...OK +DirectByteBufferViewLEGetAndBitwiseXorReleaseChar...OK +DirectByteBufferViewLEGetAndBitwiseXorReleaseInt...OK +DirectByteBufferViewLEGetAndBitwiseXorReleaseLong...OK +DirectByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK +DirectByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK +DirectByteBufferViewLEGetAndBitwiseXorAcquireShort...OK +DirectByteBufferViewLEGetAndBitwiseXorAcquireChar...OK +DirectByteBufferViewLEGetAndBitwiseXorAcquireInt...OK +DirectByteBufferViewLEGetAndBitwiseXorAcquireLong...OK +DirectByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK +DirectByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK +DirectByteBufferViewBEGetShort...OK +DirectByteBufferViewBEGetChar...OK +DirectByteBufferViewBEGetInt...OK +DirectByteBufferViewBEGetLong...OK +DirectByteBufferViewBEGetFloat...OK +DirectByteBufferViewBEGetDouble...OK +DirectByteBufferViewBESetShort...OK +DirectByteBufferViewBESetChar...OK +DirectByteBufferViewBESetInt...OK +DirectByteBufferViewBESetLong...OK +DirectByteBufferViewBESetFloat...OK +DirectByteBufferViewBESetDouble...OK +DirectByteBufferViewBEGetVolatileShort...OK +DirectByteBufferViewBEGetVolatileChar...OK +DirectByteBufferViewBEGetVolatileInt...OK +DirectByteBufferViewBEGetVolatileLong...OK +DirectByteBufferViewBEGetVolatileFloat...OK +DirectByteBufferViewBEGetVolatileDouble...OK +DirectByteBufferViewBESetVolatileShort...OK +DirectByteBufferViewBESetVolatileChar...OK +DirectByteBufferViewBESetVolatileInt...OK +DirectByteBufferViewBESetVolatileLong...OK +DirectByteBufferViewBESetVolatileFloat...OK +DirectByteBufferViewBESetVolatileDouble...OK +DirectByteBufferViewBEGetAcquireShort...OK +DirectByteBufferViewBEGetAcquireChar...OK +DirectByteBufferViewBEGetAcquireInt...OK +DirectByteBufferViewBEGetAcquireLong...OK +DirectByteBufferViewBEGetAcquireFloat...OK +DirectByteBufferViewBEGetAcquireDouble...OK +DirectByteBufferViewBESetReleaseShort...OK +DirectByteBufferViewBESetReleaseChar...OK +DirectByteBufferViewBESetReleaseInt...OK +DirectByteBufferViewBESetReleaseLong...OK +DirectByteBufferViewBESetReleaseFloat...OK +DirectByteBufferViewBESetReleaseDouble...OK +DirectByteBufferViewBEGetOpaqueShort...OK +DirectByteBufferViewBEGetOpaqueChar...OK +DirectByteBufferViewBEGetOpaqueInt...OK +DirectByteBufferViewBEGetOpaqueLong...OK +DirectByteBufferViewBEGetOpaqueFloat...OK +DirectByteBufferViewBEGetOpaqueDouble...OK +DirectByteBufferViewBESetOpaqueShort...OK +DirectByteBufferViewBESetOpaqueChar...OK +DirectByteBufferViewBESetOpaqueInt...OK +DirectByteBufferViewBESetOpaqueLong...OK +DirectByteBufferViewBESetOpaqueFloat...OK +DirectByteBufferViewBESetOpaqueDouble...OK +DirectByteBufferViewBECompareAndSetShort...OK +DirectByteBufferViewBECompareAndSetChar...OK +DirectByteBufferViewBECompareAndSetInt...OK +DirectByteBufferViewBECompareAndSetLong...OK +DirectByteBufferViewBECompareAndSetFloat...OK +DirectByteBufferViewBECompareAndSetDouble...OK +DirectByteBufferViewBECompareAndExchangeShort...OK +DirectByteBufferViewBECompareAndExchangeChar...OK +DirectByteBufferViewBECompareAndExchangeInt...OK +DirectByteBufferViewBECompareAndExchangeLong...OK +DirectByteBufferViewBECompareAndExchangeFloat...OK +DirectByteBufferViewBECompareAndExchangeDouble...OK +DirectByteBufferViewBECompareAndExchangeAcquireShort...OK +DirectByteBufferViewBECompareAndExchangeAcquireChar...OK +DirectByteBufferViewBECompareAndExchangeAcquireInt...OK +DirectByteBufferViewBECompareAndExchangeAcquireLong...OK +DirectByteBufferViewBECompareAndExchangeAcquireFloat...OK +DirectByteBufferViewBECompareAndExchangeAcquireDouble...OK +DirectByteBufferViewBECompareAndExchangeReleaseShort...OK +DirectByteBufferViewBECompareAndExchangeReleaseChar...OK +DirectByteBufferViewBECompareAndExchangeReleaseInt...OK +DirectByteBufferViewBECompareAndExchangeReleaseLong...OK +DirectByteBufferViewBECompareAndExchangeReleaseFloat...OK +DirectByteBufferViewBECompareAndExchangeReleaseDouble...OK +DirectByteBufferViewBEWeakCompareAndSetPlainShort...OK +DirectByteBufferViewBEWeakCompareAndSetPlainChar...OK +DirectByteBufferViewBEWeakCompareAndSetPlainInt...OK +DirectByteBufferViewBEWeakCompareAndSetPlainLong...OK +DirectByteBufferViewBEWeakCompareAndSetPlainFloat...OK +DirectByteBufferViewBEWeakCompareAndSetPlainDouble...OK +DirectByteBufferViewBEWeakCompareAndSetShort...OK +DirectByteBufferViewBEWeakCompareAndSetChar...OK +DirectByteBufferViewBEWeakCompareAndSetInt...OK +DirectByteBufferViewBEWeakCompareAndSetLong...OK +DirectByteBufferViewBEWeakCompareAndSetFloat...OK +DirectByteBufferViewBEWeakCompareAndSetDouble...OK +DirectByteBufferViewBEWeakCompareAndSetAcquireShort...OK +DirectByteBufferViewBEWeakCompareAndSetAcquireChar...OK +DirectByteBufferViewBEWeakCompareAndSetAcquireInt...OK +DirectByteBufferViewBEWeakCompareAndSetAcquireLong...OK +DirectByteBufferViewBEWeakCompareAndSetAcquireFloat...OK +DirectByteBufferViewBEWeakCompareAndSetAcquireDouble...OK +DirectByteBufferViewBEWeakCompareAndSetReleaseShort...OK +DirectByteBufferViewBEWeakCompareAndSetReleaseChar...OK +DirectByteBufferViewBEWeakCompareAndSetReleaseInt...OK +DirectByteBufferViewBEWeakCompareAndSetReleaseLong...OK +DirectByteBufferViewBEWeakCompareAndSetReleaseFloat...OK +DirectByteBufferViewBEWeakCompareAndSetReleaseDouble...OK +DirectByteBufferViewBEGetAndSetShort...OK +DirectByteBufferViewBEGetAndSetChar...OK +DirectByteBufferViewBEGetAndSetInt...OK +DirectByteBufferViewBEGetAndSetLong...OK +DirectByteBufferViewBEGetAndSetFloat...OK +DirectByteBufferViewBEGetAndSetDouble...OK +DirectByteBufferViewBEGetAndSetAcquireShort...OK +DirectByteBufferViewBEGetAndSetAcquireChar...OK +DirectByteBufferViewBEGetAndSetAcquireInt...OK +DirectByteBufferViewBEGetAndSetAcquireLong...OK +DirectByteBufferViewBEGetAndSetAcquireFloat...OK +DirectByteBufferViewBEGetAndSetAcquireDouble...OK +DirectByteBufferViewBEGetAndSetReleaseShort...OK +DirectByteBufferViewBEGetAndSetReleaseChar...OK +DirectByteBufferViewBEGetAndSetReleaseInt...OK +DirectByteBufferViewBEGetAndSetReleaseLong...OK +DirectByteBufferViewBEGetAndSetReleaseFloat...OK +DirectByteBufferViewBEGetAndSetReleaseDouble...OK +DirectByteBufferViewBEGetAndAddShort...OK +DirectByteBufferViewBEGetAndAddChar...OK +DirectByteBufferViewBEGetAndAddInt...OK +DirectByteBufferViewBEGetAndAddLong...OK +DirectByteBufferViewBEGetAndAddFloat...OK +DirectByteBufferViewBEGetAndAddDouble...OK +DirectByteBufferViewBEGetAndAddAcquireShort...OK +DirectByteBufferViewBEGetAndAddAcquireChar...OK +DirectByteBufferViewBEGetAndAddAcquireInt...OK +DirectByteBufferViewBEGetAndAddAcquireLong...OK +DirectByteBufferViewBEGetAndAddAcquireFloat...OK +DirectByteBufferViewBEGetAndAddAcquireDouble...OK +DirectByteBufferViewBEGetAndAddReleaseShort...OK +DirectByteBufferViewBEGetAndAddReleaseChar...OK +DirectByteBufferViewBEGetAndAddReleaseInt...OK +DirectByteBufferViewBEGetAndAddReleaseLong...OK +DirectByteBufferViewBEGetAndAddReleaseFloat...OK +DirectByteBufferViewBEGetAndAddReleaseDouble...OK +DirectByteBufferViewBEGetAndBitwiseOrShort...OK +DirectByteBufferViewBEGetAndBitwiseOrChar...OK +DirectByteBufferViewBEGetAndBitwiseOrInt...OK +DirectByteBufferViewBEGetAndBitwiseOrLong...OK +DirectByteBufferViewBEGetAndBitwiseOrFloat...OK +DirectByteBufferViewBEGetAndBitwiseOrDouble...OK +DirectByteBufferViewBEGetAndBitwiseOrReleaseShort...OK +DirectByteBufferViewBEGetAndBitwiseOrReleaseChar...OK +DirectByteBufferViewBEGetAndBitwiseOrReleaseInt...OK +DirectByteBufferViewBEGetAndBitwiseOrReleaseLong...OK +DirectByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK +DirectByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK +DirectByteBufferViewBEGetAndBitwiseOrAcquireShort...OK +DirectByteBufferViewBEGetAndBitwiseOrAcquireChar...OK +DirectByteBufferViewBEGetAndBitwiseOrAcquireInt...OK +DirectByteBufferViewBEGetAndBitwiseOrAcquireLong...OK +DirectByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK +DirectByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK +DirectByteBufferViewBEGetAndBitwiseAndShort...OK +DirectByteBufferViewBEGetAndBitwiseAndChar...OK +DirectByteBufferViewBEGetAndBitwiseAndInt...OK +DirectByteBufferViewBEGetAndBitwiseAndLong...OK +DirectByteBufferViewBEGetAndBitwiseAndFloat...OK +DirectByteBufferViewBEGetAndBitwiseAndDouble...OK +DirectByteBufferViewBEGetAndBitwiseAndReleaseShort...OK +DirectByteBufferViewBEGetAndBitwiseAndReleaseChar...OK +DirectByteBufferViewBEGetAndBitwiseAndReleaseInt...OK +DirectByteBufferViewBEGetAndBitwiseAndReleaseLong...OK +DirectByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK +DirectByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK +DirectByteBufferViewBEGetAndBitwiseAndAcquireShort...OK +DirectByteBufferViewBEGetAndBitwiseAndAcquireChar...OK +DirectByteBufferViewBEGetAndBitwiseAndAcquireInt...OK +DirectByteBufferViewBEGetAndBitwiseAndAcquireLong...OK +DirectByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK +DirectByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK +DirectByteBufferViewBEGetAndBitwiseXorShort...OK +DirectByteBufferViewBEGetAndBitwiseXorChar...OK +DirectByteBufferViewBEGetAndBitwiseXorInt...OK +DirectByteBufferViewBEGetAndBitwiseXorLong...OK +DirectByteBufferViewBEGetAndBitwiseXorFloat...OK +DirectByteBufferViewBEGetAndBitwiseXorDouble...OK +DirectByteBufferViewBEGetAndBitwiseXorReleaseShort...OK +DirectByteBufferViewBEGetAndBitwiseXorReleaseChar...OK +DirectByteBufferViewBEGetAndBitwiseXorReleaseInt...OK +DirectByteBufferViewBEGetAndBitwiseXorReleaseLong...OK +DirectByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK +DirectByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK +DirectByteBufferViewBEGetAndBitwiseXorAcquireShort...OK +DirectByteBufferViewBEGetAndBitwiseXorAcquireChar...OK +DirectByteBufferViewBEGetAndBitwiseXorAcquireInt...OK +DirectByteBufferViewBEGetAndBitwiseXorAcquireLong...OK +DirectByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK +DirectByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK +HeapByteBufferViewLEGetShort...OK +HeapByteBufferViewLEGetChar...OK +HeapByteBufferViewLEGetInt...OK +HeapByteBufferViewLEGetLong...OK +HeapByteBufferViewLEGetFloat...OK +HeapByteBufferViewLEGetDouble...OK +HeapByteBufferViewLESetShort...OK +HeapByteBufferViewLESetChar...OK +HeapByteBufferViewLESetInt...OK +HeapByteBufferViewLESetLong...OK +HeapByteBufferViewLESetFloat...OK +HeapByteBufferViewLESetDouble...OK +HeapByteBufferViewLEGetVolatileShort...OK +HeapByteBufferViewLEGetVolatileChar...OK +HeapByteBufferViewLEGetVolatileInt...OK +HeapByteBufferViewLEGetVolatileLong...OK +HeapByteBufferViewLEGetVolatileFloat...OK +HeapByteBufferViewLEGetVolatileDouble...OK +HeapByteBufferViewLESetVolatileShort...OK +HeapByteBufferViewLESetVolatileChar...OK +HeapByteBufferViewLESetVolatileInt...OK +HeapByteBufferViewLESetVolatileLong...OK +HeapByteBufferViewLESetVolatileFloat...OK +HeapByteBufferViewLESetVolatileDouble...OK +HeapByteBufferViewLEGetAcquireShort...OK +HeapByteBufferViewLEGetAcquireChar...OK +HeapByteBufferViewLEGetAcquireInt...OK +HeapByteBufferViewLEGetAcquireLong...OK +HeapByteBufferViewLEGetAcquireFloat...OK +HeapByteBufferViewLEGetAcquireDouble...OK +HeapByteBufferViewLESetReleaseShort...OK +HeapByteBufferViewLESetReleaseChar...OK +HeapByteBufferViewLESetReleaseInt...OK +HeapByteBufferViewLESetReleaseLong...OK +HeapByteBufferViewLESetReleaseFloat...OK +HeapByteBufferViewLESetReleaseDouble...OK +HeapByteBufferViewLEGetOpaqueShort...OK +HeapByteBufferViewLEGetOpaqueChar...OK +HeapByteBufferViewLEGetOpaqueInt...OK +HeapByteBufferViewLEGetOpaqueLong...OK +HeapByteBufferViewLEGetOpaqueFloat...OK +HeapByteBufferViewLEGetOpaqueDouble...OK +HeapByteBufferViewLESetOpaqueShort...OK +HeapByteBufferViewLESetOpaqueChar...OK +HeapByteBufferViewLESetOpaqueInt...OK +HeapByteBufferViewLESetOpaqueLong...OK +HeapByteBufferViewLESetOpaqueFloat...OK +HeapByteBufferViewLESetOpaqueDouble...OK +HeapByteBufferViewLECompareAndSetShort...OK +HeapByteBufferViewLECompareAndSetChar...OK +HeapByteBufferViewLECompareAndSetInt...OK +HeapByteBufferViewLECompareAndSetLong...OK +HeapByteBufferViewLECompareAndSetFloat...OK +HeapByteBufferViewLECompareAndSetDouble...OK +HeapByteBufferViewLECompareAndExchangeShort...OK +HeapByteBufferViewLECompareAndExchangeChar...OK +HeapByteBufferViewLECompareAndExchangeInt...OK +HeapByteBufferViewLECompareAndExchangeLong...OK +HeapByteBufferViewLECompareAndExchangeFloat...OK +HeapByteBufferViewLECompareAndExchangeDouble...OK +HeapByteBufferViewLECompareAndExchangeAcquireShort...OK +HeapByteBufferViewLECompareAndExchangeAcquireChar...OK +HeapByteBufferViewLECompareAndExchangeAcquireInt...OK +HeapByteBufferViewLECompareAndExchangeAcquireLong...OK +HeapByteBufferViewLECompareAndExchangeAcquireFloat...OK +HeapByteBufferViewLECompareAndExchangeAcquireDouble...OK +HeapByteBufferViewLECompareAndExchangeReleaseShort...OK +HeapByteBufferViewLECompareAndExchangeReleaseChar...OK +HeapByteBufferViewLECompareAndExchangeReleaseInt...OK +HeapByteBufferViewLECompareAndExchangeReleaseLong...OK +HeapByteBufferViewLECompareAndExchangeReleaseFloat...OK +HeapByteBufferViewLECompareAndExchangeReleaseDouble...OK +HeapByteBufferViewLEWeakCompareAndSetPlainShort...OK +HeapByteBufferViewLEWeakCompareAndSetPlainChar...OK +HeapByteBufferViewLEWeakCompareAndSetPlainInt...OK +HeapByteBufferViewLEWeakCompareAndSetPlainLong...OK +HeapByteBufferViewLEWeakCompareAndSetPlainFloat...OK +HeapByteBufferViewLEWeakCompareAndSetPlainDouble...OK +HeapByteBufferViewLEWeakCompareAndSetShort...OK +HeapByteBufferViewLEWeakCompareAndSetChar...OK +HeapByteBufferViewLEWeakCompareAndSetInt...OK +HeapByteBufferViewLEWeakCompareAndSetLong...OK +HeapByteBufferViewLEWeakCompareAndSetFloat...OK +HeapByteBufferViewLEWeakCompareAndSetDouble...OK +HeapByteBufferViewLEWeakCompareAndSetAcquireShort...OK +HeapByteBufferViewLEWeakCompareAndSetAcquireChar...OK +HeapByteBufferViewLEWeakCompareAndSetAcquireInt...OK +HeapByteBufferViewLEWeakCompareAndSetAcquireLong...OK +HeapByteBufferViewLEWeakCompareAndSetAcquireFloat...OK +HeapByteBufferViewLEWeakCompareAndSetAcquireDouble...OK +HeapByteBufferViewLEWeakCompareAndSetReleaseShort...OK +HeapByteBufferViewLEWeakCompareAndSetReleaseChar...OK +HeapByteBufferViewLEWeakCompareAndSetReleaseInt...OK +HeapByteBufferViewLEWeakCompareAndSetReleaseLong...OK +HeapByteBufferViewLEWeakCompareAndSetReleaseFloat...OK +HeapByteBufferViewLEWeakCompareAndSetReleaseDouble...OK +HeapByteBufferViewLEGetAndSetShort...OK +HeapByteBufferViewLEGetAndSetChar...OK +HeapByteBufferViewLEGetAndSetInt...OK +HeapByteBufferViewLEGetAndSetLong...OK +HeapByteBufferViewLEGetAndSetFloat...OK +HeapByteBufferViewLEGetAndSetDouble...OK +HeapByteBufferViewLEGetAndSetAcquireShort...OK +HeapByteBufferViewLEGetAndSetAcquireChar...OK +HeapByteBufferViewLEGetAndSetAcquireInt...OK +HeapByteBufferViewLEGetAndSetAcquireLong...OK +HeapByteBufferViewLEGetAndSetAcquireFloat...OK +HeapByteBufferViewLEGetAndSetAcquireDouble...OK +HeapByteBufferViewLEGetAndSetReleaseShort...OK +HeapByteBufferViewLEGetAndSetReleaseChar...OK +HeapByteBufferViewLEGetAndSetReleaseInt...OK +HeapByteBufferViewLEGetAndSetReleaseLong...OK +HeapByteBufferViewLEGetAndSetReleaseFloat...OK +HeapByteBufferViewLEGetAndSetReleaseDouble...OK +HeapByteBufferViewLEGetAndAddShort...OK +HeapByteBufferViewLEGetAndAddChar...OK +HeapByteBufferViewLEGetAndAddInt...OK +HeapByteBufferViewLEGetAndAddLong...OK +HeapByteBufferViewLEGetAndAddFloat...OK +HeapByteBufferViewLEGetAndAddDouble...OK +HeapByteBufferViewLEGetAndAddAcquireShort...OK +HeapByteBufferViewLEGetAndAddAcquireChar...OK +HeapByteBufferViewLEGetAndAddAcquireInt...OK +HeapByteBufferViewLEGetAndAddAcquireLong...OK +HeapByteBufferViewLEGetAndAddAcquireFloat...OK +HeapByteBufferViewLEGetAndAddAcquireDouble...OK +HeapByteBufferViewLEGetAndAddReleaseShort...OK +HeapByteBufferViewLEGetAndAddReleaseChar...OK +HeapByteBufferViewLEGetAndAddReleaseInt...OK +HeapByteBufferViewLEGetAndAddReleaseLong...OK +HeapByteBufferViewLEGetAndAddReleaseFloat...OK +HeapByteBufferViewLEGetAndAddReleaseDouble...OK +HeapByteBufferViewLEGetAndBitwiseOrShort...OK +HeapByteBufferViewLEGetAndBitwiseOrChar...OK +HeapByteBufferViewLEGetAndBitwiseOrInt...OK +HeapByteBufferViewLEGetAndBitwiseOrLong...OK +HeapByteBufferViewLEGetAndBitwiseOrFloat...OK +HeapByteBufferViewLEGetAndBitwiseOrDouble...OK +HeapByteBufferViewLEGetAndBitwiseOrReleaseShort...OK +HeapByteBufferViewLEGetAndBitwiseOrReleaseChar...OK +HeapByteBufferViewLEGetAndBitwiseOrReleaseInt...OK +HeapByteBufferViewLEGetAndBitwiseOrReleaseLong...OK +HeapByteBufferViewLEGetAndBitwiseOrReleaseFloat...OK +HeapByteBufferViewLEGetAndBitwiseOrReleaseDouble...OK +HeapByteBufferViewLEGetAndBitwiseOrAcquireShort...OK +HeapByteBufferViewLEGetAndBitwiseOrAcquireChar...OK +HeapByteBufferViewLEGetAndBitwiseOrAcquireInt...OK +HeapByteBufferViewLEGetAndBitwiseOrAcquireLong...OK +HeapByteBufferViewLEGetAndBitwiseOrAcquireFloat...OK +HeapByteBufferViewLEGetAndBitwiseOrAcquireDouble...OK +HeapByteBufferViewLEGetAndBitwiseAndShort...OK +HeapByteBufferViewLEGetAndBitwiseAndChar...OK +HeapByteBufferViewLEGetAndBitwiseAndInt...OK +HeapByteBufferViewLEGetAndBitwiseAndLong...OK +HeapByteBufferViewLEGetAndBitwiseAndFloat...OK +HeapByteBufferViewLEGetAndBitwiseAndDouble...OK +HeapByteBufferViewLEGetAndBitwiseAndReleaseShort...OK +HeapByteBufferViewLEGetAndBitwiseAndReleaseChar...OK +HeapByteBufferViewLEGetAndBitwiseAndReleaseInt...OK +HeapByteBufferViewLEGetAndBitwiseAndReleaseLong...OK +HeapByteBufferViewLEGetAndBitwiseAndReleaseFloat...OK +HeapByteBufferViewLEGetAndBitwiseAndReleaseDouble...OK +HeapByteBufferViewLEGetAndBitwiseAndAcquireShort...OK +HeapByteBufferViewLEGetAndBitwiseAndAcquireChar...OK +HeapByteBufferViewLEGetAndBitwiseAndAcquireInt...OK +HeapByteBufferViewLEGetAndBitwiseAndAcquireLong...OK +HeapByteBufferViewLEGetAndBitwiseAndAcquireFloat...OK +HeapByteBufferViewLEGetAndBitwiseAndAcquireDouble...OK +HeapByteBufferViewLEGetAndBitwiseXorShort...OK +HeapByteBufferViewLEGetAndBitwiseXorChar...OK +HeapByteBufferViewLEGetAndBitwiseXorInt...OK +HeapByteBufferViewLEGetAndBitwiseXorLong...OK +HeapByteBufferViewLEGetAndBitwiseXorFloat...OK +HeapByteBufferViewLEGetAndBitwiseXorDouble...OK +HeapByteBufferViewLEGetAndBitwiseXorReleaseShort...OK +HeapByteBufferViewLEGetAndBitwiseXorReleaseChar...OK +HeapByteBufferViewLEGetAndBitwiseXorReleaseInt...OK +HeapByteBufferViewLEGetAndBitwiseXorReleaseLong...OK +HeapByteBufferViewLEGetAndBitwiseXorReleaseFloat...OK +HeapByteBufferViewLEGetAndBitwiseXorReleaseDouble...OK +HeapByteBufferViewLEGetAndBitwiseXorAcquireShort...OK +HeapByteBufferViewLEGetAndBitwiseXorAcquireChar...OK +HeapByteBufferViewLEGetAndBitwiseXorAcquireInt...OK +HeapByteBufferViewLEGetAndBitwiseXorAcquireLong...OK +HeapByteBufferViewLEGetAndBitwiseXorAcquireFloat...OK +HeapByteBufferViewLEGetAndBitwiseXorAcquireDouble...OK +HeapByteBufferViewBEGetShort...OK +HeapByteBufferViewBEGetChar...OK +HeapByteBufferViewBEGetInt...OK +HeapByteBufferViewBEGetLong...OK +HeapByteBufferViewBEGetFloat...OK +HeapByteBufferViewBEGetDouble...OK +HeapByteBufferViewBESetShort...OK +HeapByteBufferViewBESetChar...OK +HeapByteBufferViewBESetInt...OK +HeapByteBufferViewBESetLong...OK +HeapByteBufferViewBESetFloat...OK +HeapByteBufferViewBESetDouble...OK +HeapByteBufferViewBEGetVolatileShort...OK +HeapByteBufferViewBEGetVolatileChar...OK +HeapByteBufferViewBEGetVolatileInt...OK +HeapByteBufferViewBEGetVolatileLong...OK +HeapByteBufferViewBEGetVolatileFloat...OK +HeapByteBufferViewBEGetVolatileDouble...OK +HeapByteBufferViewBESetVolatileShort...OK +HeapByteBufferViewBESetVolatileChar...OK +HeapByteBufferViewBESetVolatileInt...OK +HeapByteBufferViewBESetVolatileLong...OK +HeapByteBufferViewBESetVolatileFloat...OK +HeapByteBufferViewBESetVolatileDouble...OK +HeapByteBufferViewBEGetAcquireShort...OK +HeapByteBufferViewBEGetAcquireChar...OK +HeapByteBufferViewBEGetAcquireInt...OK +HeapByteBufferViewBEGetAcquireLong...OK +HeapByteBufferViewBEGetAcquireFloat...OK +HeapByteBufferViewBEGetAcquireDouble...OK +HeapByteBufferViewBESetReleaseShort...OK +HeapByteBufferViewBESetReleaseChar...OK +HeapByteBufferViewBESetReleaseInt...OK +HeapByteBufferViewBESetReleaseLong...OK +HeapByteBufferViewBESetReleaseFloat...OK +HeapByteBufferViewBESetReleaseDouble...OK +HeapByteBufferViewBEGetOpaqueShort...OK +HeapByteBufferViewBEGetOpaqueChar...OK +HeapByteBufferViewBEGetOpaqueInt...OK +HeapByteBufferViewBEGetOpaqueLong...OK +HeapByteBufferViewBEGetOpaqueFloat...OK +HeapByteBufferViewBEGetOpaqueDouble...OK +HeapByteBufferViewBESetOpaqueShort...OK +HeapByteBufferViewBESetOpaqueChar...OK +HeapByteBufferViewBESetOpaqueInt...OK +HeapByteBufferViewBESetOpaqueLong...OK +HeapByteBufferViewBESetOpaqueFloat...OK +HeapByteBufferViewBESetOpaqueDouble...OK +HeapByteBufferViewBECompareAndSetShort...OK +HeapByteBufferViewBECompareAndSetChar...OK +HeapByteBufferViewBECompareAndSetInt...OK +HeapByteBufferViewBECompareAndSetLong...OK +HeapByteBufferViewBECompareAndSetFloat...OK +HeapByteBufferViewBECompareAndSetDouble...OK +HeapByteBufferViewBECompareAndExchangeShort...OK +HeapByteBufferViewBECompareAndExchangeChar...OK +HeapByteBufferViewBECompareAndExchangeInt...OK +HeapByteBufferViewBECompareAndExchangeLong...OK +HeapByteBufferViewBECompareAndExchangeFloat...OK +HeapByteBufferViewBECompareAndExchangeDouble...OK +HeapByteBufferViewBECompareAndExchangeAcquireShort...OK +HeapByteBufferViewBECompareAndExchangeAcquireChar...OK +HeapByteBufferViewBECompareAndExchangeAcquireInt...OK +HeapByteBufferViewBECompareAndExchangeAcquireLong...OK +HeapByteBufferViewBECompareAndExchangeAcquireFloat...OK +HeapByteBufferViewBECompareAndExchangeAcquireDouble...OK +HeapByteBufferViewBECompareAndExchangeReleaseShort...OK +HeapByteBufferViewBECompareAndExchangeReleaseChar...OK +HeapByteBufferViewBECompareAndExchangeReleaseInt...OK +HeapByteBufferViewBECompareAndExchangeReleaseLong...OK +HeapByteBufferViewBECompareAndExchangeReleaseFloat...OK +HeapByteBufferViewBECompareAndExchangeReleaseDouble...OK +HeapByteBufferViewBEWeakCompareAndSetPlainShort...OK +HeapByteBufferViewBEWeakCompareAndSetPlainChar...OK +HeapByteBufferViewBEWeakCompareAndSetPlainInt...OK +HeapByteBufferViewBEWeakCompareAndSetPlainLong...OK +HeapByteBufferViewBEWeakCompareAndSetPlainFloat...OK +HeapByteBufferViewBEWeakCompareAndSetPlainDouble...OK +HeapByteBufferViewBEWeakCompareAndSetShort...OK +HeapByteBufferViewBEWeakCompareAndSetChar...OK +HeapByteBufferViewBEWeakCompareAndSetInt...OK +HeapByteBufferViewBEWeakCompareAndSetLong...OK +HeapByteBufferViewBEWeakCompareAndSetFloat...OK +HeapByteBufferViewBEWeakCompareAndSetDouble...OK +HeapByteBufferViewBEWeakCompareAndSetAcquireShort...OK +HeapByteBufferViewBEWeakCompareAndSetAcquireChar...OK +HeapByteBufferViewBEWeakCompareAndSetAcquireInt...OK +HeapByteBufferViewBEWeakCompareAndSetAcquireLong...OK +HeapByteBufferViewBEWeakCompareAndSetAcquireFloat...OK +HeapByteBufferViewBEWeakCompareAndSetAcquireDouble...OK +HeapByteBufferViewBEWeakCompareAndSetReleaseShort...OK +HeapByteBufferViewBEWeakCompareAndSetReleaseChar...OK +HeapByteBufferViewBEWeakCompareAndSetReleaseInt...OK +HeapByteBufferViewBEWeakCompareAndSetReleaseLong...OK +HeapByteBufferViewBEWeakCompareAndSetReleaseFloat...OK +HeapByteBufferViewBEWeakCompareAndSetReleaseDouble...OK +HeapByteBufferViewBEGetAndSetShort...OK +HeapByteBufferViewBEGetAndSetChar...OK +HeapByteBufferViewBEGetAndSetInt...OK +HeapByteBufferViewBEGetAndSetLong...OK +HeapByteBufferViewBEGetAndSetFloat...OK +HeapByteBufferViewBEGetAndSetDouble...OK +HeapByteBufferViewBEGetAndSetAcquireShort...OK +HeapByteBufferViewBEGetAndSetAcquireChar...OK +HeapByteBufferViewBEGetAndSetAcquireInt...OK +HeapByteBufferViewBEGetAndSetAcquireLong...OK +HeapByteBufferViewBEGetAndSetAcquireFloat...OK +HeapByteBufferViewBEGetAndSetAcquireDouble...OK +HeapByteBufferViewBEGetAndSetReleaseShort...OK +HeapByteBufferViewBEGetAndSetReleaseChar...OK +HeapByteBufferViewBEGetAndSetReleaseInt...OK +HeapByteBufferViewBEGetAndSetReleaseLong...OK +HeapByteBufferViewBEGetAndSetReleaseFloat...OK +HeapByteBufferViewBEGetAndSetReleaseDouble...OK +HeapByteBufferViewBEGetAndAddShort...OK +HeapByteBufferViewBEGetAndAddChar...OK +HeapByteBufferViewBEGetAndAddInt...OK +HeapByteBufferViewBEGetAndAddLong...OK +HeapByteBufferViewBEGetAndAddFloat...OK +HeapByteBufferViewBEGetAndAddDouble...OK +HeapByteBufferViewBEGetAndAddAcquireShort...OK +HeapByteBufferViewBEGetAndAddAcquireChar...OK +HeapByteBufferViewBEGetAndAddAcquireInt...OK +HeapByteBufferViewBEGetAndAddAcquireLong...OK +HeapByteBufferViewBEGetAndAddAcquireFloat...OK +HeapByteBufferViewBEGetAndAddAcquireDouble...OK +HeapByteBufferViewBEGetAndAddReleaseShort...OK +HeapByteBufferViewBEGetAndAddReleaseChar...OK +HeapByteBufferViewBEGetAndAddReleaseInt...OK +HeapByteBufferViewBEGetAndAddReleaseLong...OK +HeapByteBufferViewBEGetAndAddReleaseFloat...OK +HeapByteBufferViewBEGetAndAddReleaseDouble...OK +HeapByteBufferViewBEGetAndBitwiseOrShort...OK +HeapByteBufferViewBEGetAndBitwiseOrChar...OK +HeapByteBufferViewBEGetAndBitwiseOrInt...OK +HeapByteBufferViewBEGetAndBitwiseOrLong...OK +HeapByteBufferViewBEGetAndBitwiseOrFloat...OK +HeapByteBufferViewBEGetAndBitwiseOrDouble...OK +HeapByteBufferViewBEGetAndBitwiseOrReleaseShort...OK +HeapByteBufferViewBEGetAndBitwiseOrReleaseChar...OK +HeapByteBufferViewBEGetAndBitwiseOrReleaseInt...OK +HeapByteBufferViewBEGetAndBitwiseOrReleaseLong...OK +HeapByteBufferViewBEGetAndBitwiseOrReleaseFloat...OK +HeapByteBufferViewBEGetAndBitwiseOrReleaseDouble...OK +HeapByteBufferViewBEGetAndBitwiseOrAcquireShort...OK +HeapByteBufferViewBEGetAndBitwiseOrAcquireChar...OK +HeapByteBufferViewBEGetAndBitwiseOrAcquireInt...OK +HeapByteBufferViewBEGetAndBitwiseOrAcquireLong...OK +HeapByteBufferViewBEGetAndBitwiseOrAcquireFloat...OK +HeapByteBufferViewBEGetAndBitwiseOrAcquireDouble...OK +HeapByteBufferViewBEGetAndBitwiseAndShort...OK +HeapByteBufferViewBEGetAndBitwiseAndChar...OK +HeapByteBufferViewBEGetAndBitwiseAndInt...OK +HeapByteBufferViewBEGetAndBitwiseAndLong...OK +HeapByteBufferViewBEGetAndBitwiseAndFloat...OK +HeapByteBufferViewBEGetAndBitwiseAndDouble...OK +HeapByteBufferViewBEGetAndBitwiseAndReleaseShort...OK +HeapByteBufferViewBEGetAndBitwiseAndReleaseChar...OK +HeapByteBufferViewBEGetAndBitwiseAndReleaseInt...OK +HeapByteBufferViewBEGetAndBitwiseAndReleaseLong...OK +HeapByteBufferViewBEGetAndBitwiseAndReleaseFloat...OK +HeapByteBufferViewBEGetAndBitwiseAndReleaseDouble...OK +HeapByteBufferViewBEGetAndBitwiseAndAcquireShort...OK +HeapByteBufferViewBEGetAndBitwiseAndAcquireChar...OK +HeapByteBufferViewBEGetAndBitwiseAndAcquireInt...OK +HeapByteBufferViewBEGetAndBitwiseAndAcquireLong...OK +HeapByteBufferViewBEGetAndBitwiseAndAcquireFloat...OK +HeapByteBufferViewBEGetAndBitwiseAndAcquireDouble...OK +HeapByteBufferViewBEGetAndBitwiseXorShort...OK +HeapByteBufferViewBEGetAndBitwiseXorChar...OK +HeapByteBufferViewBEGetAndBitwiseXorInt...OK +HeapByteBufferViewBEGetAndBitwiseXorLong...OK +HeapByteBufferViewBEGetAndBitwiseXorFloat...OK +HeapByteBufferViewBEGetAndBitwiseXorDouble...OK +HeapByteBufferViewBEGetAndBitwiseXorReleaseShort...OK +HeapByteBufferViewBEGetAndBitwiseXorReleaseChar...OK +HeapByteBufferViewBEGetAndBitwiseXorReleaseInt...OK +HeapByteBufferViewBEGetAndBitwiseXorReleaseLong...OK +HeapByteBufferViewBEGetAndBitwiseXorReleaseFloat...OK +HeapByteBufferViewBEGetAndBitwiseXorReleaseDouble...OK +HeapByteBufferViewBEGetAndBitwiseXorAcquireShort...OK +HeapByteBufferViewBEGetAndBitwiseXorAcquireChar...OK +HeapByteBufferViewBEGetAndBitwiseXorAcquireInt...OK +HeapByteBufferViewBEGetAndBitwiseXorAcquireLong...OK +HeapByteBufferViewBEGetAndBitwiseXorAcquireFloat...OK +HeapByteBufferViewBEGetAndBitwiseXorAcquireDouble...OK +HeapByteBufferReadOnlyViewLEGetShort...OK +HeapByteBufferReadOnlyViewLEGetChar...OK +HeapByteBufferReadOnlyViewLEGetInt...OK +HeapByteBufferReadOnlyViewLEGetLong...OK +HeapByteBufferReadOnlyViewLEGetFloat...OK +HeapByteBufferReadOnlyViewLEGetDouble...OK +HeapByteBufferReadOnlyViewLESetShort...OK +HeapByteBufferReadOnlyViewLESetChar...OK +HeapByteBufferReadOnlyViewLESetInt...OK +HeapByteBufferReadOnlyViewLESetLong...OK +HeapByteBufferReadOnlyViewLESetFloat...OK +HeapByteBufferReadOnlyViewLESetDouble...OK +HeapByteBufferReadOnlyViewLEGetVolatileShort...OK +HeapByteBufferReadOnlyViewLEGetVolatileChar...OK +HeapByteBufferReadOnlyViewLEGetVolatileInt...OK +HeapByteBufferReadOnlyViewLEGetVolatileLong...OK +HeapByteBufferReadOnlyViewLEGetVolatileFloat...OK +HeapByteBufferReadOnlyViewLEGetVolatileDouble...OK +HeapByteBufferReadOnlyViewLESetVolatileShort...OK +HeapByteBufferReadOnlyViewLESetVolatileChar...OK +HeapByteBufferReadOnlyViewLESetVolatileInt...OK +HeapByteBufferReadOnlyViewLESetVolatileLong...OK +HeapByteBufferReadOnlyViewLESetVolatileFloat...OK +HeapByteBufferReadOnlyViewLESetVolatileDouble...OK +HeapByteBufferReadOnlyViewLEGetAcquireShort...OK +HeapByteBufferReadOnlyViewLEGetAcquireChar...OK +HeapByteBufferReadOnlyViewLEGetAcquireInt...OK +HeapByteBufferReadOnlyViewLEGetAcquireLong...OK +HeapByteBufferReadOnlyViewLEGetAcquireFloat...OK +HeapByteBufferReadOnlyViewLEGetAcquireDouble...OK +HeapByteBufferReadOnlyViewLESetReleaseShort...OK +HeapByteBufferReadOnlyViewLESetReleaseChar...OK +HeapByteBufferReadOnlyViewLESetReleaseInt...OK +HeapByteBufferReadOnlyViewLESetReleaseLong...OK +HeapByteBufferReadOnlyViewLESetReleaseFloat...OK +HeapByteBufferReadOnlyViewLESetReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetOpaqueShort...OK +HeapByteBufferReadOnlyViewLEGetOpaqueChar...OK +HeapByteBufferReadOnlyViewLEGetOpaqueInt...OK +HeapByteBufferReadOnlyViewLEGetOpaqueLong...OK +HeapByteBufferReadOnlyViewLEGetOpaqueFloat...OK +HeapByteBufferReadOnlyViewLEGetOpaqueDouble...OK +HeapByteBufferReadOnlyViewLESetOpaqueShort...OK +HeapByteBufferReadOnlyViewLESetOpaqueChar...OK +HeapByteBufferReadOnlyViewLESetOpaqueInt...OK +HeapByteBufferReadOnlyViewLESetOpaqueLong...OK +HeapByteBufferReadOnlyViewLESetOpaqueFloat...OK +HeapByteBufferReadOnlyViewLESetOpaqueDouble...OK +HeapByteBufferReadOnlyViewLECompareAndSetShort...OK +HeapByteBufferReadOnlyViewLECompareAndSetChar...OK +HeapByteBufferReadOnlyViewLECompareAndSetInt...OK +HeapByteBufferReadOnlyViewLECompareAndSetLong...OK +HeapByteBufferReadOnlyViewLECompareAndSetFloat...OK +HeapByteBufferReadOnlyViewLECompareAndSetDouble...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeShort...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeChar...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeInt...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeLong...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeFloat...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeDouble...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireShort...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireChar...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireInt...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireLong...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireFloat...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeAcquireDouble...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseShort...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseChar...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseInt...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseLong...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseFloat...OK +HeapByteBufferReadOnlyViewLECompareAndExchangeReleaseDouble...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainShort...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainChar...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainInt...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainLong...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainFloat...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetPlainDouble...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetShort...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetChar...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetInt...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetLong...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetFloat...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetDouble...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireShort...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireChar...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireInt...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireLong...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireFloat...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetAcquireDouble...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseShort...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseChar...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseInt...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseLong...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseFloat...OK +HeapByteBufferReadOnlyViewLEWeakCompareAndSetReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetAndSetShort...OK +HeapByteBufferReadOnlyViewLEGetAndSetChar...OK +HeapByteBufferReadOnlyViewLEGetAndSetInt...OK +HeapByteBufferReadOnlyViewLEGetAndSetLong...OK +HeapByteBufferReadOnlyViewLEGetAndSetFloat...OK +HeapByteBufferReadOnlyViewLEGetAndSetDouble...OK +HeapByteBufferReadOnlyViewLEGetAndSetAcquireShort...OK +HeapByteBufferReadOnlyViewLEGetAndSetAcquireChar...OK +HeapByteBufferReadOnlyViewLEGetAndSetAcquireInt...OK +HeapByteBufferReadOnlyViewLEGetAndSetAcquireLong...OK +HeapByteBufferReadOnlyViewLEGetAndSetAcquireFloat...OK +HeapByteBufferReadOnlyViewLEGetAndSetAcquireDouble...OK +HeapByteBufferReadOnlyViewLEGetAndSetReleaseShort...OK +HeapByteBufferReadOnlyViewLEGetAndSetReleaseChar...OK +HeapByteBufferReadOnlyViewLEGetAndSetReleaseInt...OK +HeapByteBufferReadOnlyViewLEGetAndSetReleaseLong...OK +HeapByteBufferReadOnlyViewLEGetAndSetReleaseFloat...OK +HeapByteBufferReadOnlyViewLEGetAndSetReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetAndAddShort...OK +HeapByteBufferReadOnlyViewLEGetAndAddChar...OK +HeapByteBufferReadOnlyViewLEGetAndAddInt...OK +HeapByteBufferReadOnlyViewLEGetAndAddLong...OK +HeapByteBufferReadOnlyViewLEGetAndAddFloat...OK +HeapByteBufferReadOnlyViewLEGetAndAddDouble...OK +HeapByteBufferReadOnlyViewLEGetAndAddAcquireShort...OK +HeapByteBufferReadOnlyViewLEGetAndAddAcquireChar...OK +HeapByteBufferReadOnlyViewLEGetAndAddAcquireInt...OK +HeapByteBufferReadOnlyViewLEGetAndAddAcquireLong...OK +HeapByteBufferReadOnlyViewLEGetAndAddAcquireFloat...OK +HeapByteBufferReadOnlyViewLEGetAndAddAcquireDouble...OK +HeapByteBufferReadOnlyViewLEGetAndAddReleaseShort...OK +HeapByteBufferReadOnlyViewLEGetAndAddReleaseChar...OK +HeapByteBufferReadOnlyViewLEGetAndAddReleaseInt...OK +HeapByteBufferReadOnlyViewLEGetAndAddReleaseLong...OK +HeapByteBufferReadOnlyViewLEGetAndAddReleaseFloat...OK +HeapByteBufferReadOnlyViewLEGetAndAddReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseOrAcquireDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseAndAcquireDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorReleaseDouble...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireShort...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireChar...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireInt...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireLong...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireFloat...OK +HeapByteBufferReadOnlyViewLEGetAndBitwiseXorAcquireDouble...OK +HeapByteBufferReadOnlyViewBEGetShort...OK +HeapByteBufferReadOnlyViewBEGetChar...OK +HeapByteBufferReadOnlyViewBEGetInt...OK +HeapByteBufferReadOnlyViewBEGetLong...OK +HeapByteBufferReadOnlyViewBEGetFloat...OK +HeapByteBufferReadOnlyViewBEGetDouble...OK +HeapByteBufferReadOnlyViewBESetShort...OK +HeapByteBufferReadOnlyViewBESetChar...OK +HeapByteBufferReadOnlyViewBESetInt...OK +HeapByteBufferReadOnlyViewBESetLong...OK +HeapByteBufferReadOnlyViewBESetFloat...OK +HeapByteBufferReadOnlyViewBESetDouble...OK +HeapByteBufferReadOnlyViewBEGetVolatileShort...OK +HeapByteBufferReadOnlyViewBEGetVolatileChar...OK +HeapByteBufferReadOnlyViewBEGetVolatileInt...OK +HeapByteBufferReadOnlyViewBEGetVolatileLong...OK +HeapByteBufferReadOnlyViewBEGetVolatileFloat...OK +HeapByteBufferReadOnlyViewBEGetVolatileDouble...OK +HeapByteBufferReadOnlyViewBESetVolatileShort...OK +HeapByteBufferReadOnlyViewBESetVolatileChar...OK +HeapByteBufferReadOnlyViewBESetVolatileInt...OK +HeapByteBufferReadOnlyViewBESetVolatileLong...OK +HeapByteBufferReadOnlyViewBESetVolatileFloat...OK +HeapByteBufferReadOnlyViewBESetVolatileDouble...OK +HeapByteBufferReadOnlyViewBEGetAcquireShort...OK +HeapByteBufferReadOnlyViewBEGetAcquireChar...OK +HeapByteBufferReadOnlyViewBEGetAcquireInt...OK +HeapByteBufferReadOnlyViewBEGetAcquireLong...OK +HeapByteBufferReadOnlyViewBEGetAcquireFloat...OK +HeapByteBufferReadOnlyViewBEGetAcquireDouble...OK +HeapByteBufferReadOnlyViewBESetReleaseShort...OK +HeapByteBufferReadOnlyViewBESetReleaseChar...OK +HeapByteBufferReadOnlyViewBESetReleaseInt...OK +HeapByteBufferReadOnlyViewBESetReleaseLong...OK +HeapByteBufferReadOnlyViewBESetReleaseFloat...OK +HeapByteBufferReadOnlyViewBESetReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetOpaqueShort...OK +HeapByteBufferReadOnlyViewBEGetOpaqueChar...OK +HeapByteBufferReadOnlyViewBEGetOpaqueInt...OK +HeapByteBufferReadOnlyViewBEGetOpaqueLong...OK +HeapByteBufferReadOnlyViewBEGetOpaqueFloat...OK +HeapByteBufferReadOnlyViewBEGetOpaqueDouble...OK +HeapByteBufferReadOnlyViewBESetOpaqueShort...OK +HeapByteBufferReadOnlyViewBESetOpaqueChar...OK +HeapByteBufferReadOnlyViewBESetOpaqueInt...OK +HeapByteBufferReadOnlyViewBESetOpaqueLong...OK +HeapByteBufferReadOnlyViewBESetOpaqueFloat...OK +HeapByteBufferReadOnlyViewBESetOpaqueDouble...OK +HeapByteBufferReadOnlyViewBECompareAndSetShort...OK +HeapByteBufferReadOnlyViewBECompareAndSetChar...OK +HeapByteBufferReadOnlyViewBECompareAndSetInt...OK +HeapByteBufferReadOnlyViewBECompareAndSetLong...OK +HeapByteBufferReadOnlyViewBECompareAndSetFloat...OK +HeapByteBufferReadOnlyViewBECompareAndSetDouble...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeShort...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeChar...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeInt...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeLong...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeFloat...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeDouble...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireShort...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireChar...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireInt...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireLong...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireFloat...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeAcquireDouble...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseShort...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseChar...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseInt...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseLong...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseFloat...OK +HeapByteBufferReadOnlyViewBECompareAndExchangeReleaseDouble...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainShort...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainChar...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainInt...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainLong...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainFloat...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetPlainDouble...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetShort...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetChar...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetInt...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetLong...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetFloat...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetDouble...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireShort...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireChar...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireInt...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireLong...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireFloat...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetAcquireDouble...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseShort...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseChar...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseInt...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseLong...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseFloat...OK +HeapByteBufferReadOnlyViewBEWeakCompareAndSetReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetAndSetShort...OK +HeapByteBufferReadOnlyViewBEGetAndSetChar...OK +HeapByteBufferReadOnlyViewBEGetAndSetInt...OK +HeapByteBufferReadOnlyViewBEGetAndSetLong...OK +HeapByteBufferReadOnlyViewBEGetAndSetFloat...OK +HeapByteBufferReadOnlyViewBEGetAndSetDouble...OK +HeapByteBufferReadOnlyViewBEGetAndSetAcquireShort...OK +HeapByteBufferReadOnlyViewBEGetAndSetAcquireChar...OK +HeapByteBufferReadOnlyViewBEGetAndSetAcquireInt...OK +HeapByteBufferReadOnlyViewBEGetAndSetAcquireLong...OK +HeapByteBufferReadOnlyViewBEGetAndSetAcquireFloat...OK +HeapByteBufferReadOnlyViewBEGetAndSetAcquireDouble...OK +HeapByteBufferReadOnlyViewBEGetAndSetReleaseShort...OK +HeapByteBufferReadOnlyViewBEGetAndSetReleaseChar...OK +HeapByteBufferReadOnlyViewBEGetAndSetReleaseInt...OK +HeapByteBufferReadOnlyViewBEGetAndSetReleaseLong...OK +HeapByteBufferReadOnlyViewBEGetAndSetReleaseFloat...OK +HeapByteBufferReadOnlyViewBEGetAndSetReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetAndAddShort...OK +HeapByteBufferReadOnlyViewBEGetAndAddChar...OK +HeapByteBufferReadOnlyViewBEGetAndAddInt...OK +HeapByteBufferReadOnlyViewBEGetAndAddLong...OK +HeapByteBufferReadOnlyViewBEGetAndAddFloat...OK +HeapByteBufferReadOnlyViewBEGetAndAddDouble...OK +HeapByteBufferReadOnlyViewBEGetAndAddAcquireShort...OK +HeapByteBufferReadOnlyViewBEGetAndAddAcquireChar...OK +HeapByteBufferReadOnlyViewBEGetAndAddAcquireInt...OK +HeapByteBufferReadOnlyViewBEGetAndAddAcquireLong...OK +HeapByteBufferReadOnlyViewBEGetAndAddAcquireFloat...OK +HeapByteBufferReadOnlyViewBEGetAndAddAcquireDouble...OK +HeapByteBufferReadOnlyViewBEGetAndAddReleaseShort...OK +HeapByteBufferReadOnlyViewBEGetAndAddReleaseChar...OK +HeapByteBufferReadOnlyViewBEGetAndAddReleaseInt...OK +HeapByteBufferReadOnlyViewBEGetAndAddReleaseLong...OK +HeapByteBufferReadOnlyViewBEGetAndAddReleaseFloat...OK +HeapByteBufferReadOnlyViewBEGetAndAddReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseOrAcquireDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseAndAcquireDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorReleaseDouble...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireShort...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireChar...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireInt...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireLong...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireFloat...OK +HeapByteBufferReadOnlyViewBEGetAndBitwiseXorAcquireDouble...OK +FieldGetWidget...OK +FieldSetWidget...OK +FieldGetVolatileWidget...OK +FieldSetVolatileWidget...OK +FieldGetAcquireWidget...OK +FieldSetReleaseWidget...OK +FieldGetOpaqueWidget...OK +FieldSetOpaqueWidget...OK +FieldCompareAndSetWidget...OK +FieldCompareAndExchangeWidget...OK +FieldCompareAndExchangeAcquireWidget...OK +FieldCompareAndExchangeReleaseWidget...OK +FieldWeakCompareAndSetPlainWidget...OK +FieldWeakCompareAndSetWidget...OK +FieldWeakCompareAndSetAcquireWidget...OK +FieldWeakCompareAndSetReleaseWidget...OK +FieldGetAndSetWidget...OK +FieldGetAndSetAcquireWidget...OK +FieldGetAndSetReleaseWidget...OK +FieldGetAndAddWidget...OK +FieldGetAndAddAcquireWidget...OK +FieldGetAndAddReleaseWidget...OK +FieldGetAndBitwiseOrWidget...OK +FieldGetAndBitwiseOrReleaseWidget...OK +FieldGetAndBitwiseOrAcquireWidget...OK +FieldGetAndBitwiseAndWidget...OK +FieldGetAndBitwiseAndReleaseWidget...OK +FieldGetAndBitwiseAndAcquireWidget...OK +FieldGetAndBitwiseXorWidget...OK +FieldGetAndBitwiseXorReleaseWidget...OK +FieldGetAndBitwiseXorAcquireWidget...OK +FinalFieldGetWidget...OK +FinalFieldSetWidget...OK +FinalFieldGetVolatileWidget...OK +FinalFieldSetVolatileWidget...OK +FinalFieldGetAcquireWidget...OK +FinalFieldSetReleaseWidget...OK +FinalFieldGetOpaqueWidget...OK +FinalFieldSetOpaqueWidget...OK +FinalFieldCompareAndSetWidget...OK +FinalFieldCompareAndExchangeWidget...OK +FinalFieldCompareAndExchangeAcquireWidget...OK +FinalFieldCompareAndExchangeReleaseWidget...OK +FinalFieldWeakCompareAndSetPlainWidget...OK +FinalFieldWeakCompareAndSetWidget...OK +FinalFieldWeakCompareAndSetAcquireWidget...OK +FinalFieldWeakCompareAndSetReleaseWidget...OK +FinalFieldGetAndSetWidget...OK +FinalFieldGetAndSetAcquireWidget...OK +FinalFieldGetAndSetReleaseWidget...OK +FinalFieldGetAndAddWidget...OK +FinalFieldGetAndAddAcquireWidget...OK +FinalFieldGetAndAddReleaseWidget...OK +FinalFieldGetAndBitwiseOrWidget...OK +FinalFieldGetAndBitwiseOrReleaseWidget...OK +FinalFieldGetAndBitwiseOrAcquireWidget...OK +FinalFieldGetAndBitwiseAndWidget...OK +FinalFieldGetAndBitwiseAndReleaseWidget...OK +FinalFieldGetAndBitwiseAndAcquireWidget...OK +FinalFieldGetAndBitwiseXorWidget...OK +FinalFieldGetAndBitwiseXorReleaseWidget...OK +FinalFieldGetAndBitwiseXorAcquireWidget...OK +StaticFieldGetWidget...OK +StaticFieldSetWidget...OK +StaticFieldGetVolatileWidget...OK +StaticFieldSetVolatileWidget...OK +StaticFieldGetAcquireWidget...OK +StaticFieldSetReleaseWidget...OK +StaticFieldGetOpaqueWidget...OK +StaticFieldSetOpaqueWidget...OK +StaticFieldCompareAndSetWidget...OK +StaticFieldCompareAndExchangeWidget...OK +StaticFieldCompareAndExchangeAcquireWidget...OK +StaticFieldCompareAndExchangeReleaseWidget...OK +StaticFieldWeakCompareAndSetPlainWidget...OK +StaticFieldWeakCompareAndSetWidget...OK +StaticFieldWeakCompareAndSetAcquireWidget...OK +StaticFieldWeakCompareAndSetReleaseWidget...OK +StaticFieldGetAndSetWidget...OK +StaticFieldGetAndSetAcquireWidget...OK +StaticFieldGetAndSetReleaseWidget...OK +StaticFieldGetAndAddWidget...OK +StaticFieldGetAndAddAcquireWidget...OK +StaticFieldGetAndAddReleaseWidget...OK +StaticFieldGetAndBitwiseOrWidget...OK +StaticFieldGetAndBitwiseOrReleaseWidget...OK +StaticFieldGetAndBitwiseOrAcquireWidget...OK +StaticFieldGetAndBitwiseAndWidget...OK +StaticFieldGetAndBitwiseAndReleaseWidget...OK +StaticFieldGetAndBitwiseAndAcquireWidget...OK +StaticFieldGetAndBitwiseXorWidget...OK +StaticFieldGetAndBitwiseXorReleaseWidget...OK +StaticFieldGetAndBitwiseXorAcquireWidget...OK +StaticFinalFieldGetWidget...OK +StaticFinalFieldSetWidget...OK +StaticFinalFieldGetVolatileWidget...OK +StaticFinalFieldSetVolatileWidget...OK +StaticFinalFieldGetAcquireWidget...OK +StaticFinalFieldSetReleaseWidget...OK +StaticFinalFieldGetOpaqueWidget...OK +StaticFinalFieldSetOpaqueWidget...OK +StaticFinalFieldCompareAndSetWidget...OK +StaticFinalFieldCompareAndExchangeWidget...OK +StaticFinalFieldCompareAndExchangeAcquireWidget...OK +StaticFinalFieldCompareAndExchangeReleaseWidget...OK +StaticFinalFieldWeakCompareAndSetPlainWidget...OK +StaticFinalFieldWeakCompareAndSetWidget...OK +StaticFinalFieldWeakCompareAndSetAcquireWidget...OK +StaticFinalFieldWeakCompareAndSetReleaseWidget...OK +StaticFinalFieldGetAndSetWidget...OK +StaticFinalFieldGetAndSetAcquireWidget...OK +StaticFinalFieldGetAndSetReleaseWidget...OK +StaticFinalFieldGetAndAddWidget...OK +StaticFinalFieldGetAndAddAcquireWidget...OK +StaticFinalFieldGetAndAddReleaseWidget...OK +StaticFinalFieldGetAndBitwiseOrWidget...OK +StaticFinalFieldGetAndBitwiseOrReleaseWidget...OK +StaticFinalFieldGetAndBitwiseOrAcquireWidget...OK +StaticFinalFieldGetAndBitwiseAndWidget...OK +StaticFinalFieldGetAndBitwiseAndReleaseWidget...OK +StaticFinalFieldGetAndBitwiseAndAcquireWidget...OK +StaticFinalFieldGetAndBitwiseXorWidget...OK +StaticFinalFieldGetAndBitwiseXorReleaseWidget...OK +StaticFinalFieldGetAndBitwiseXorAcquireWidget...OK +ArrayElementGetWidget...OK +ArrayElementSetWidget...OK +ArrayElementGetVolatileWidget...OK +ArrayElementSetVolatileWidget...OK +ArrayElementGetAcquireWidget...OK +ArrayElementSetReleaseWidget...OK +ArrayElementGetOpaqueWidget...OK +ArrayElementSetOpaqueWidget...OK +ArrayElementCompareAndSetWidget...OK +ArrayElementCompareAndExchangeWidget...OK +ArrayElementCompareAndExchangeAcquireWidget...OK +ArrayElementCompareAndExchangeReleaseWidget...OK +ArrayElementWeakCompareAndSetPlainWidget...OK +ArrayElementWeakCompareAndSetWidget...OK +ArrayElementWeakCompareAndSetAcquireWidget...OK +ArrayElementWeakCompareAndSetReleaseWidget...OK +ArrayElementGetAndSetWidget...OK +ArrayElementGetAndSetAcquireWidget...OK +ArrayElementGetAndSetReleaseWidget...OK +ArrayElementGetAndAddWidget...OK +ArrayElementGetAndAddAcquireWidget...OK +ArrayElementGetAndAddReleaseWidget...OK +ArrayElementGetAndBitwiseOrWidget...OK +ArrayElementGetAndBitwiseOrReleaseWidget...OK +ArrayElementGetAndBitwiseOrAcquireWidget...OK +ArrayElementGetAndBitwiseAndWidget...OK +ArrayElementGetAndBitwiseAndReleaseWidget...OK +ArrayElementGetAndBitwiseAndAcquireWidget...OK +ArrayElementGetAndBitwiseXorWidget...OK +ArrayElementGetAndBitwiseXorReleaseWidget...OK +ArrayElementGetAndBitwiseXorAcquireWidget...OK +BoxingReturnGetBoolean...OK +BoxingSetBoolean...OK +BoxingReturnGetVolatileBoolean...OK +BoxingSetVolatileBoolean...OK +BoxingReturnGetAcquireBoolean...OK +BoxingSetReleaseBoolean...OK +BoxingReturnGetOpaqueBoolean...OK +BoxingSetOpaqueBoolean...OK +BoxingCompareAndSetBoolean...OK +BoxingCompareAndExchangeBoolean...OK +BoxingCompareAndExchangeAcquireBoolean...OK +BoxingCompareAndExchangeReleaseBoolean...OK +BoxingWeakCompareAndSetPlainBoolean...OK +BoxingWeakCompareAndSetBoolean...OK +BoxingWeakCompareAndSetAcquireBoolean...OK +BoxingWeakCompareAndSetReleaseBoolean...OK +BoxingGetAndSetBoolean...OK +BoxingGetAndSetAcquireBoolean...OK +BoxingGetAndSetReleaseBoolean...OK +BoxingGetAndAddBoolean...OK +BoxingGetAndAddAcquireBoolean...OK +BoxingGetAndAddReleaseBoolean...OK +BoxingGetAndBitwiseOrBoolean...OK +BoxingGetAndBitwiseOrReleaseBoolean...OK +BoxingGetAndBitwiseOrAcquireBoolean...OK +BoxingGetAndBitwiseAndBoolean...OK +BoxingGetAndBitwiseAndReleaseBoolean...OK +BoxingGetAndBitwiseAndAcquireBoolean...OK +BoxingGetAndBitwiseXorBoolean...OK +BoxingGetAndBitwiseXorReleaseBoolean...OK +BoxingGetAndBitwiseXorAcquireBoolean...OK +BoxingReturnGetByte...OK +BoxingSetByte...OK +BoxingReturnGetVolatileByte...OK +BoxingSetVolatileByte...OK +BoxingReturnGetAcquireByte...OK +BoxingSetReleaseByte...OK +BoxingReturnGetOpaqueByte...OK +BoxingSetOpaqueByte...OK +BoxingCompareAndSetByte...OK +BoxingCompareAndExchangeByte...OK +BoxingCompareAndExchangeAcquireByte...OK +BoxingCompareAndExchangeReleaseByte...OK +BoxingWeakCompareAndSetPlainByte...OK +BoxingWeakCompareAndSetByte...OK +BoxingWeakCompareAndSetAcquireByte...OK +BoxingWeakCompareAndSetReleaseByte...OK +BoxingGetAndSetByte...OK +BoxingGetAndSetAcquireByte...OK +BoxingGetAndSetReleaseByte...OK +BoxingGetAndAddByte...OK +BoxingGetAndAddAcquireByte...OK +BoxingGetAndAddReleaseByte...OK +BoxingGetAndBitwiseOrByte...OK +BoxingGetAndBitwiseOrReleaseByte...OK +BoxingGetAndBitwiseOrAcquireByte...OK +BoxingGetAndBitwiseAndByte...OK +BoxingGetAndBitwiseAndReleaseByte...OK +BoxingGetAndBitwiseAndAcquireByte...OK +BoxingGetAndBitwiseXorByte...OK +BoxingGetAndBitwiseXorReleaseByte...OK +BoxingGetAndBitwiseXorAcquireByte...OK +BoxingReturnGetShort...OK +BoxingSetShort...OK +BoxingReturnGetVolatileShort...OK +BoxingSetVolatileShort...OK +BoxingReturnGetAcquireShort...OK +BoxingSetReleaseShort...OK +BoxingReturnGetOpaqueShort...OK +BoxingSetOpaqueShort...OK +BoxingCompareAndSetShort...OK +BoxingCompareAndExchangeShort...OK +BoxingCompareAndExchangeAcquireShort...OK +BoxingCompareAndExchangeReleaseShort...OK +BoxingWeakCompareAndSetPlainShort...OK +BoxingWeakCompareAndSetShort...OK +BoxingWeakCompareAndSetAcquireShort...OK +BoxingWeakCompareAndSetReleaseShort...OK +BoxingGetAndSetShort...OK +BoxingGetAndSetAcquireShort...OK +BoxingGetAndSetReleaseShort...OK +BoxingGetAndAddShort...OK +BoxingGetAndAddAcquireShort...OK +BoxingGetAndAddReleaseShort...OK +BoxingGetAndBitwiseOrShort...OK +BoxingGetAndBitwiseOrReleaseShort...OK +BoxingGetAndBitwiseOrAcquireShort...OK +BoxingGetAndBitwiseAndShort...OK +BoxingGetAndBitwiseAndReleaseShort...OK +BoxingGetAndBitwiseAndAcquireShort...OK +BoxingGetAndBitwiseXorShort...OK +BoxingGetAndBitwiseXorReleaseShort...OK +BoxingGetAndBitwiseXorAcquireShort...OK +BoxingReturnGetChar...OK +BoxingSetChar...OK +BoxingReturnGetVolatileChar...OK +BoxingSetVolatileChar...OK +BoxingReturnGetAcquireChar...OK +BoxingSetReleaseChar...OK +BoxingReturnGetOpaqueChar...OK +BoxingSetOpaqueChar...OK +BoxingCompareAndSetChar...OK +BoxingCompareAndExchangeChar...OK +BoxingCompareAndExchangeAcquireChar...OK +BoxingCompareAndExchangeReleaseChar...OK +BoxingWeakCompareAndSetPlainChar...OK +BoxingWeakCompareAndSetChar...OK +BoxingWeakCompareAndSetAcquireChar...OK +BoxingWeakCompareAndSetReleaseChar...OK +BoxingGetAndSetChar...OK +BoxingGetAndSetAcquireChar...OK +BoxingGetAndSetReleaseChar...OK +BoxingGetAndAddChar...OK +BoxingGetAndAddAcquireChar...OK +BoxingGetAndAddReleaseChar...OK +BoxingGetAndBitwiseOrChar...OK +BoxingGetAndBitwiseOrReleaseChar...OK +BoxingGetAndBitwiseOrAcquireChar...OK +BoxingGetAndBitwiseAndChar...OK +BoxingGetAndBitwiseAndReleaseChar...OK +BoxingGetAndBitwiseAndAcquireChar...OK +BoxingGetAndBitwiseXorChar...OK +BoxingGetAndBitwiseXorReleaseChar...OK +BoxingGetAndBitwiseXorAcquireChar...OK +BoxingReturnGetInt...OK +BoxingSetInt...OK +BoxingReturnGetVolatileInt...OK +BoxingSetVolatileInt...OK +BoxingReturnGetAcquireInt...OK +BoxingSetReleaseInt...OK +BoxingReturnGetOpaqueInt...OK +BoxingSetOpaqueInt...OK +BoxingCompareAndSetInt...OK +BoxingCompareAndExchangeInt...OK +BoxingCompareAndExchangeAcquireInt...OK +BoxingCompareAndExchangeReleaseInt...OK +BoxingWeakCompareAndSetPlainInt...OK +BoxingWeakCompareAndSetInt...OK +BoxingWeakCompareAndSetAcquireInt...OK +BoxingWeakCompareAndSetReleaseInt...OK +BoxingGetAndSetInt...OK +BoxingGetAndSetAcquireInt...OK +BoxingGetAndSetReleaseInt...OK +BoxingGetAndAddInt...OK +BoxingGetAndAddAcquireInt...OK +BoxingGetAndAddReleaseInt...OK +BoxingGetAndBitwiseOrInt...OK +BoxingGetAndBitwiseOrReleaseInt...OK +BoxingGetAndBitwiseOrAcquireInt...OK +BoxingGetAndBitwiseAndInt...OK +BoxingGetAndBitwiseAndReleaseInt...OK +BoxingGetAndBitwiseAndAcquireInt...OK +BoxingGetAndBitwiseXorInt...OK +BoxingGetAndBitwiseXorReleaseInt...OK +BoxingGetAndBitwiseXorAcquireInt...OK +BoxingReturnGetLong...OK +BoxingSetLong...OK +BoxingReturnGetVolatileLong...OK +BoxingSetVolatileLong...OK +BoxingReturnGetAcquireLong...OK +BoxingSetReleaseLong...OK +BoxingReturnGetOpaqueLong...OK +BoxingSetOpaqueLong...OK +BoxingCompareAndSetLong...OK +BoxingCompareAndExchangeLong...OK +BoxingCompareAndExchangeAcquireLong...OK +BoxingCompareAndExchangeReleaseLong...OK +BoxingWeakCompareAndSetPlainLong...OK +BoxingWeakCompareAndSetLong...OK +BoxingWeakCompareAndSetAcquireLong...OK +BoxingWeakCompareAndSetReleaseLong...OK +BoxingGetAndSetLong...OK +BoxingGetAndSetAcquireLong...OK +BoxingGetAndSetReleaseLong...OK +BoxingGetAndAddLong...OK +BoxingGetAndAddAcquireLong...OK +BoxingGetAndAddReleaseLong...OK +BoxingGetAndBitwiseOrLong...OK +BoxingGetAndBitwiseOrReleaseLong...OK +BoxingGetAndBitwiseOrAcquireLong...OK +BoxingGetAndBitwiseAndLong...OK +BoxingGetAndBitwiseAndReleaseLong...OK +BoxingGetAndBitwiseAndAcquireLong...OK +BoxingGetAndBitwiseXorLong...OK +BoxingGetAndBitwiseXorReleaseLong...OK +BoxingGetAndBitwiseXorAcquireLong...OK +BoxingReturnGetFloat...OK +BoxingSetFloat...OK +BoxingReturnGetVolatileFloat...OK +BoxingSetVolatileFloat...OK +BoxingReturnGetAcquireFloat...OK +BoxingSetReleaseFloat...OK +BoxingReturnGetOpaqueFloat...OK +BoxingSetOpaqueFloat...OK +BoxingCompareAndSetFloat...OK +BoxingCompareAndExchangeFloat...OK +BoxingCompareAndExchangeAcquireFloat...OK +BoxingCompareAndExchangeReleaseFloat...OK +BoxingWeakCompareAndSetPlainFloat...OK +BoxingWeakCompareAndSetFloat...OK +BoxingWeakCompareAndSetAcquireFloat...OK +BoxingWeakCompareAndSetReleaseFloat...OK +BoxingGetAndSetFloat...OK +BoxingGetAndSetAcquireFloat...OK +BoxingGetAndSetReleaseFloat...OK +BoxingGetAndAddFloat...OK +BoxingGetAndAddAcquireFloat...OK +BoxingGetAndAddReleaseFloat...OK +BoxingGetAndBitwiseOrFloat...OK +BoxingGetAndBitwiseOrReleaseFloat...OK +BoxingGetAndBitwiseOrAcquireFloat...OK +BoxingGetAndBitwiseAndFloat...OK +BoxingGetAndBitwiseAndReleaseFloat...OK +BoxingGetAndBitwiseAndAcquireFloat...OK +BoxingGetAndBitwiseXorFloat...OK +BoxingGetAndBitwiseXorReleaseFloat...OK +BoxingGetAndBitwiseXorAcquireFloat...OK +BoxingReturnGetDouble...OK +BoxingSetDouble...OK +BoxingReturnGetVolatileDouble...OK +BoxingSetVolatileDouble...OK +BoxingReturnGetAcquireDouble...OK +BoxingSetReleaseDouble...OK +BoxingReturnGetOpaqueDouble...OK +BoxingSetOpaqueDouble...OK +BoxingCompareAndSetDouble...OK +BoxingCompareAndExchangeDouble...OK +BoxingCompareAndExchangeAcquireDouble...OK +BoxingCompareAndExchangeReleaseDouble...OK +BoxingWeakCompareAndSetPlainDouble...OK +BoxingWeakCompareAndSetDouble...OK +BoxingWeakCompareAndSetAcquireDouble...OK +BoxingWeakCompareAndSetReleaseDouble...OK +BoxingGetAndSetDouble...OK +BoxingGetAndSetAcquireDouble...OK +BoxingGetAndSetReleaseDouble...OK +BoxingGetAndAddDouble...OK +BoxingGetAndAddAcquireDouble...OK +BoxingGetAndAddReleaseDouble...OK +BoxingGetAndBitwiseOrDouble...OK +BoxingGetAndBitwiseOrReleaseDouble...OK +BoxingGetAndBitwiseOrAcquireDouble...OK +BoxingGetAndBitwiseAndDouble...OK +BoxingGetAndBitwiseAndReleaseDouble...OK +BoxingGetAndBitwiseAndAcquireDouble...OK +BoxingGetAndBitwiseXorDouble...OK +BoxingGetAndBitwiseXorReleaseDouble...OK +BoxingGetAndBitwiseXorAcquireDouble...OK +NullReceiverTest...OK +UnsupportedAccessModeTest...OK +WrongArgumentTypeCausingWrongMethodTypeTest...OK +TooManyArgumentsCausingWrongMethodTypeTest...OK +TooFewArgumentsCausingWrongMethodTypeTest...OK +ReturnTypeCausingWrongMethodTypeTest...OK +UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest...OK +FieldCoordinateTypeTest...OK +ArrayElementOutOfBoundsIndexTest...OK +ArrayElementBadIndexTypeTest...OK +ArrayElementNullArrayTest...OK +ArrayElementWrongArrayTypeTest...OK +ArrayElementMissingIndexTest...OK +ByteArrayViewOutOfBoundsIndexTest...OK +ByteArrayViewUnalignedAccessesIndexTest...OK +ByteArrayViewBadIndexTypeTest...OK +ByteArrayViewMissingIndexTest...OK +ByteArrayViewBadByteArrayTest...OK +ByteBufferViewOutOfBoundsIndexTest...OK +ByteBufferViewUnalignedAccessesIndexTest...OK +ByteBufferViewBadIndexTypeTest...OK +ByteBufferViewMissingIndexTest...OK +ByteBufferViewBadByteBufferTest...OK +VoidReturnTypeTest...OK +BoxedNullBooleanThrowsNPETest...OK +BoxedNullByteThrowsNPETest...OK +BoxedNullCharacterThrowsNPETest...OK +BoxedNullShortThrowsNPETest...OK +BoxedNullIntegerThrowsNPETest...OK +BoxedNullLongThrowsNPETest...OK +BoxedNullFloatThrowsNPETest...OK +BoxedNullDoubleThrowsNPETest...OK +WideningBooleanArgumentTest...OK +WideningByteArgumentTest...OK +WideningCharacterArgumentTest...OK +WideningShortArgumentTest...OK +WideningIntegerArgumentTest...OK +WideningLongArgumentTest...OK +WideningFloatArgumentTest...OK +WideningDoubleArgumentTest...OK +WideningBooleanReturnValueTest...OK +WideningByteReturnValueTest...OK +WideningCharacterReturnValueTest...OK +WideningShortReturnValueTest...OK +WideningIntegerReturnValueTest...OK +WideningLongReturnValueTest...OK +WideningFloatReturnValueTest...OK +WideningDoubleReturnValueTest...OK +SubtypeTest...OK +SupertypeTest...OK +ImplicitBoxingIntegerTest...OK +3182 successes, 0 skips, 0 failures. diff --git a/test/712-varhandle-invocations/info.txt b/test/712-varhandle-invocations/info.txt new file mode 100644 index 0000000000..e2de024d8e --- /dev/null +++ b/test/712-varhandle-invocations/info.txt @@ -0,0 +1 @@ +Generates and runs tests that invoke VarHandle accessor methods. diff --git a/test/712-varhandle-invocations/src/SimpleTests.java b/test/712-varhandle-invocations/src/SimpleTests.java new file mode 100644 index 0000000000..6e62bff4b4 --- /dev/null +++ b/test/712-varhandle-invocations/src/SimpleTests.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 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. + */ + +public class SimpleTests { + public static class TestGuardSkips extends VarHandleUnitTest { + public boolean checkGuard() { + return false; + } + + @Override + protected void doTest() { + throw new IllegalStateException("Not reachable"); + } + + public static void main(String[] args) { + new TestGuardSkips().run(); + } + } + + public static class TestEqualsOK extends VarHandleUnitTest { + @Override + protected void doTest() { + assertEquals(true, true); + } + } + + public static class TestEqualsOK2 extends VarHandleUnitTest { + @Override + protected void doTest() { + assertEquals(true, false); + } + } + + public static class TestExceptionsFail extends VarHandleUnitTest { + @Override + protected void doTest() { + throw new NullPointerException(); + } + } + + public static void main(String[] args) { + new TestGuardSkips().run(); + new TestEqualsOK().run(); + new TestEqualsOK2().run(); + new TestExceptionsFail().run(); + VarHandleUnitTest.DEFAULT_COLLECTOR.printSummary(); + } +} diff --git a/test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java b/test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java new file mode 100644 index 0000000000..4c9013b14d --- /dev/null +++ b/test/712-varhandle-invocations/src/VarHandleAccessorExceptionTests.java @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2018 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. + */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.lang.invoke.WrongMethodTypeException; + +// These tests cover DoVarHandleInvokeCommon in interpreter_common.cc. + +public class VarHandleAccessorExceptionTests { + public static class NullReceiverTest extends VarHandleUnitTest { + private static final VarHandle vh = null; + + @Override + protected void doTest() { + try { + vh.set(3); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new NullReceiverTest().run(); + } + } + + public static class UnsupportedAccessModeTest extends VarHandleUnitTest { + private static final boolean b = true; + private static final VarHandle vh; + + static { + try { + Class<?> cls = UnsupportedAccessModeTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "b", boolean.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + // A final field should not support an VarHandle access modes which can update it + boolean isSupported = + vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND); + assertFalse(isSupported); + try { + vh.getAndBitwiseAnd(true); + failUnreachable(); + } catch (UnsupportedOperationException ex) { + } + } + + public static void main(String[] args) { + new UnsupportedAccessModeTest().run(); + } + } + + public static class WrongArgumentTypeCausingWrongMethodTypeTest extends VarHandleUnitTest { + private short s; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WrongArgumentTypeCausingWrongMethodTypeTest.class; + vh = MethodHandles.lookup().findVarHandle(cls, "s", short.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + vh.set(this, (short) 0xcafe); + try { + vh.setVolatile(this, System.out); // System.out is a PrintStream, not short! + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WrongArgumentTypeCausingWrongMethodTypeTest().run(); + } + } + + // Too many arguments causing WMTE + public static class TooManyArgumentsCausingWrongMethodTypeTest extends VarHandleUnitTest { + private int i; + private static final VarHandle vh; + + static { + try { + Class<?> cls = TooManyArgumentsCausingWrongMethodTypeTest.class; + vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + vh.set(this, 0x12345678); + try { + vh.setVolatile(this, 0x5a5a55aa, 0xc3c30f0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new TooManyArgumentsCausingWrongMethodTypeTest().run(); + } + } + + public static class TooFewArgumentsCausingWrongMethodTypeTest extends VarHandleUnitTest { + private int i; + private static final VarHandle vh; + + static { + try { + Class<?> cls = TooFewArgumentsCausingWrongMethodTypeTest.class; + vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + i = 33; + vh.compareAndSet(this, 33, 44); + boolean updated = false; + try { + updated = (boolean) vh.compareAndSet(this, 44); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + assertFalse(updated); // Should have failed too few arguments + } + + public static void main(String[] args) { + new TooFewArgumentsCausingWrongMethodTypeTest().run(); + } + } + + public static class ReturnTypeCausingWrongMethodTypeTest extends VarHandleUnitTest { + private int i; + private static final VarHandle vh; + + static { + try { + Class<?> cls = ReturnTypeCausingWrongMethodTypeTest.class; + vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + i = 33; + vh.getAndSet(this, 44); + Runtime runtime = null; + try { + runtime = (Runtime) vh.getAndSet(this, 44); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + assertEquals(null, runtime); + } + + public static void main(String[] args) { + new ReturnTypeCausingWrongMethodTypeTest().run(); + } + } + + public static class UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest + extends VarHandleUnitTest { + private static final boolean b = true; + private static final VarHandle vh; + + static { + try { + Class<?> cls = UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "b", boolean.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + // A final field should not support an VarHandle access modes which can update it + boolean supported = vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND); + assertFalse(supported); + try { + // The following is both unsupported and a wrong method type... + vh.getAndBitwiseAnd(System.out); + failUnreachable(); + } catch (UnsupportedOperationException ex) { + } + } + + public static void main(String[] args) { + new UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest().run(); + } + } + + public static void main(String[] args) { + NullReceiverTest.main(args); + UnsupportedAccessModeTest.main(args); + WrongArgumentTypeCausingWrongMethodTypeTest.main(args); + TooManyArgumentsCausingWrongMethodTypeTest.main(args); + TooFewArgumentsCausingWrongMethodTypeTest.main(args); + ReturnTypeCausingWrongMethodTypeTest.main(args); + UnsupportedAccessModePreemptsWrongMethodTypeExceptionTest.main(args); + } +} diff --git a/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java b/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java new file mode 100644 index 0000000000..8f81c94a89 --- /dev/null +++ b/test/712-varhandle-invocations/src/VarHandleBadCoordinateTests.java @@ -0,0 +1,948 @@ +/* + * Copyright (C) 2018 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. + */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.lang.invoke.WrongMethodTypeException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class VarHandleBadCoordinateTests { + public static class FieldCoordinateTypeTest extends VarHandleUnitTest { + private static final VarHandle vh; + + public static class A { + public byte field; + } + + public static class B extends A { + private byte other_field; + } + + public static class C {} + + static { + try { + vh = MethodHandles.lookup().findVarHandle(A.class, "field", byte.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + vh.compareAndSet(new A(), (byte) 0, (byte) 3); + vh.compareAndSet(new B(), (byte) 0, (byte) 3); + try { + vh.compareAndSet(new C(), (byte) 0, (byte) 3); + failUnreachable(); + } catch (ClassCastException ex) { + } + try { + vh.compareAndSet(0xbad0bad0, (byte) 0, (byte) 3); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.compareAndSet(0xbad0bad0, (byte) 0, Integer.MAX_VALUE); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.compareAndSet(0xbad0bad0, (byte) 0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.compareAndSet(new A(), (byte) 0, Integer.MAX_VALUE); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.compareAndSet((A) null, (byte) 0, (byte) 3); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new FieldCoordinateTypeTest().run(); + } + } + + public static class ArrayElementOutOfBoundsIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.arrayElementVarHandle(long[].class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + long[] values = new long[33]; + try { + vh.get(values, -1); + failUnreachable(); + } catch (ArrayIndexOutOfBoundsException ex) { + } + try { + vh.get(values, values.length); + failUnreachable(); + } catch (ArrayIndexOutOfBoundsException ex) { + } + try { + vh.get(values, Integer.MAX_VALUE - 1); + failUnreachable(); + } catch (ArrayIndexOutOfBoundsException ex) { + } + } + + public static void main(String[] args) { + new ArrayElementOutOfBoundsIndexTest().run(); + } + } + + public static class ArrayElementBadIndexTypeTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.arrayElementVarHandle(long[].class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + long[] values = new long[33]; + vh.set(values, Integer.valueOf(3), Long.MIN_VALUE); + vh.set(values, Byte.valueOf((byte) 0), Long.MIN_VALUE); + try { + vh.set(values, 3.3f, Long.MAX_VALUE); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new ArrayElementBadIndexTypeTest().run(); + } + } + + public static class ArrayElementNullArrayTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.arrayElementVarHandle(long[].class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + long[] values = null; + try { + vh.get(values); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new ArrayElementNullArrayTest().run(); + } + } + + public static class ArrayElementWrongArrayTypeTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.arrayElementVarHandle(long[].class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.get(new char[10], 0); + failUnreachable(); + } catch (ClassCastException ex) { + } + } + + public static void main(String[] args) { + new ArrayElementWrongArrayTypeTest().run(); + } + } + + public static class ArrayElementMissingIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.arrayElementVarHandle(long[].class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + long[] values = new long[33]; + try { + vh.get(values); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new ArrayElementMissingIndexTest().run(); + } + } + + public static class ByteArrayViewOutOfBoundsIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[16]; + try { + vh.get(bytes, -1); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + try { + vh.get(bytes, bytes.length); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + try { + vh.get(bytes, Integer.MAX_VALUE - 1); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + try { + vh.get(bytes, bytes.length - Integer.SIZE / 8 + 1); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + vh.get(bytes, bytes.length - Integer.SIZE / 8); + } + + public static void main(String[] args) { + new ByteArrayViewOutOfBoundsIndexTest().run(); + } + } + + public static class ByteArrayViewUnalignedAccessesIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[33]; + + int alignedIndex = VarHandleUnitTestHelpers.alignedOffset_int(bytes, 0); + for (int i = alignedIndex; i < Integer.SIZE / 8; ++i) { + // No exceptions are expected for GET and SET + // accessors irrespective of the access alignment. + vh.set(bytes, i, 380); + vh.get(bytes, i); + // Other accessors raise an IllegalStateException if + // the access is unaligned. + try { + vh.compareAndExchange(bytes, i, 777, 320); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.compareAndExchangeAcquire(bytes, i, 320, 767); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.compareAndExchangeRelease(bytes, i, 767, 321); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.compareAndSet(bytes, i, 767, 321); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAcquire(bytes, i); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndAdd(bytes, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndAddAcquire(bytes, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndAddRelease(bytes, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseAnd(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseAndAcquire(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseAndRelease(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseOr(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseOrAcquire(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseOrRelease(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseXor(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseXorAcquire(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseXorRelease(bytes, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndSet(bytes, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndSetAcquire(bytes, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndSetRelease(bytes, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getOpaque(bytes, i); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getVolatile(bytes, i); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.setOpaque(bytes, i, 777); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.setRelease(bytes, i, 319); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.setVolatile(bytes, i, 787); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSet(bytes, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSetAcquire(bytes, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSetPlain(bytes, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSetRelease(bytes, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + } + } + + public static void main(String[] args) { + new ByteArrayViewUnalignedAccessesIndexTest().run(); + } + } + + public static class ByteArrayViewBadIndexTypeTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[16]; + // Boxed index goes through argument conversion so no exception expected. + vh.get(bytes, Integer.valueOf(3)); + vh.get(bytes, Short.valueOf((short) 3)); + + try { + vh.get(bytes, System.out); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new ByteArrayViewBadIndexTypeTest().run(); + } + } + + public static class ByteArrayViewMissingIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[16]; + try { + vh.get(bytes); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new ByteArrayViewMissingIndexTest().run(); + } + } + + public static class ByteArrayViewBadByteArrayTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = null; + try { + vh.get(bytes, Integer.valueOf(3)); + failUnreachable(); + } catch (NullPointerException ex) { + } + try { + vh.get(System.err, Integer.valueOf(3)); + failUnreachable(); + } catch (ClassCastException ex) { + } + } + + public static void main(String[] args) { + new ByteArrayViewBadByteArrayTest().run(); + } + } + + public static class ByteBufferViewOutOfBoundsIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + ByteBuffer[] buffers = + new ByteBuffer[] { + ByteBuffer.allocateDirect(16), + ByteBuffer.allocate(37), + ByteBuffer.wrap(new byte[27], 3, 27 - 3) + }; + for (ByteBuffer buffer : buffers) { + try { + vh.get(buffer, -1); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + try { + vh.get(buffer, buffer.limit()); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + try { + vh.get(buffer, Integer.MAX_VALUE - 1); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + try { + vh.get(buffer, buffer.limit() - Integer.SIZE / 8 + 1); + failUnreachable(); + } catch (IndexOutOfBoundsException ex) { + } + vh.get(buffer, buffer.limit() - Integer.SIZE / 8); + } + } + + public static void main(String[] args) { + new ByteBufferViewOutOfBoundsIndexTest().run(); + } + } + + public static class ByteBufferViewUnalignedAccessesIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + ByteBuffer[] buffers = + new ByteBuffer[] { + ByteBuffer.allocateDirect(16), + ByteBuffer.allocate(37), + ByteBuffer.wrap(new byte[27], 3, 27 - 3) + }; + + for (ByteBuffer buffer : buffers) { + int alignedIndex = VarHandleUnitTestHelpers.alignedOffset_int(buffer, 0); + for (int i = alignedIndex; i < Integer.SIZE / 8; ++i) { + // No exceptions are expected for GET and SET + // accessors irrespective of the access alignment. + vh.set(buffer, i, 380); + vh.get(buffer, i); + // Other accessors raise an IllegalStateException if + // the access is unaligned. + try { + vh.compareAndExchange(buffer, i, 777, 320); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.compareAndExchangeAcquire(buffer, i, 320, 767); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.compareAndExchangeRelease(buffer, i, 767, 321); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.compareAndSet(buffer, i, 767, 321); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAcquire(buffer, i); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndAdd(buffer, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndAddAcquire(buffer, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndAddRelease(buffer, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseAnd(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseAndAcquire(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseAndRelease(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseOr(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseOrAcquire(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseOrRelease(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseXor(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseXorAcquire(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndBitwiseXorRelease(buffer, i, 118); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndSet(buffer, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndSetAcquire(buffer, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getAndSetRelease(buffer, i, 117); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getOpaque(buffer, i); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.getVolatile(buffer, i); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.setOpaque(buffer, i, 777); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.setRelease(buffer, i, 319); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.setVolatile(buffer, i, 787); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSet(buffer, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSetAcquire(buffer, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSetPlain(buffer, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + try { + vh.weakCompareAndSetRelease(buffer, i, 787, 340); + assertTrue(i == alignedIndex); + } catch (IllegalStateException ex) { + assertFalse(i == alignedIndex); + } + } + } + } + + public static void main(String[] args) { + new ByteBufferViewUnalignedAccessesIndexTest().run(); + } + } + + public static class ByteBufferViewBadIndexTypeTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + ByteBuffer[] buffers = + new ByteBuffer[] { + ByteBuffer.allocateDirect(16), + ByteBuffer.allocate(16), + ByteBuffer.wrap(new byte[32], 4, 32 - 4) + }; + + for (ByteBuffer buffer : buffers) { + // Boxed index goes through argument conversion so no exception expected. + vh.get(buffer, Integer.valueOf(3)); + vh.get(buffer, Short.valueOf((short) 3)); + vh.get(buffer, Byte.valueOf((byte) 7)); + try { + vh.get(buffer, System.out); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + } + + public static void main(String[] args) { + new ByteBufferViewBadIndexTypeTest().run(); + } + } + + public static class ByteBufferViewMissingIndexTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + ByteBuffer[] buffers = + new ByteBuffer[] { + ByteBuffer.allocateDirect(16), + ByteBuffer.allocate(16), + ByteBuffer.wrap(new byte[32], 4, 32 - 4) + }; + for (ByteBuffer buffer : buffers) { + try { + vh.get(buffer); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + } + + public static void main(String[] args) { + new ByteBufferViewMissingIndexTest().run(); + } + } + + public static class ByteBufferViewBadByteBufferTest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteBufferViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + if (VarHandleUnitTestHelpers.isRunningOnAndroid()) { + ByteBuffer buffer = null; + // The RI does not like this test + try { + vh.get(buffer, 3); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + try { + vh.get(System.err, 3); + failUnreachable(); + } catch (ClassCastException ex) { + } + } + + public static void main(String[] args) { + new ByteBufferViewBadByteBufferTest().run(); + } + } + + public static void main(String[] args) { + FieldCoordinateTypeTest.main(args); + + ArrayElementOutOfBoundsIndexTest.main(args); + ArrayElementBadIndexTypeTest.main(args); + ArrayElementNullArrayTest.main(args); + ArrayElementWrongArrayTypeTest.main(args); + ArrayElementMissingIndexTest.main(args); + + ByteArrayViewOutOfBoundsIndexTest.main(args); + ByteArrayViewUnalignedAccessesIndexTest.main(args); + ByteArrayViewBadIndexTypeTest.main(args); + ByteArrayViewMissingIndexTest.main(args); + ByteArrayViewBadByteArrayTest.main(args); + + ByteBufferViewOutOfBoundsIndexTest.main(args); + ByteBufferViewUnalignedAccessesIndexTest.main(args); + ByteBufferViewBadIndexTypeTest.main(args); + ByteBufferViewMissingIndexTest.main(args); + ByteBufferViewBadByteBufferTest.main(args); + } +} diff --git a/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java b/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java new file mode 100644 index 0000000000..c0fbd492b2 --- /dev/null +++ b/test/712-varhandle-invocations/src/VarHandleTypeConversionTests.java @@ -0,0 +1,1343 @@ +/* + * Copyright (C) 2018 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. + */ + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.lang.invoke.WrongMethodTypeException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class VarHandleTypeConversionTests { + public static class VoidReturnTypeTest extends VarHandleUnitTest { + private int i; + private static final VarHandle vh; + + static { + try { + Class<?> cls = VoidReturnTypeTest.class; + vh = MethodHandles.lookup().findVarHandle(cls, "i", int.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + // Void is always okay for a return type. + vh.setVolatile(this, 33); + vh.get(this); + vh.compareAndSet(this, 33, 44); + vh.compareAndSet(this, 27, 16); + vh.weakCompareAndSet(this, 17, 19); + vh.getAndSet(this, 200000); + vh.getAndBitwiseXor(this, 0x5a5a5a5a); + vh.getAndAdd(this, 99); + } + + public static void main(String[] args) { + new VoidReturnTypeTest().run(); + } + } + + // + // Tests that a null reference as a boxed primitive type argument + // throws a NullPointerException. These vary the VarHandle type + // with each primitive for coverage. + // + + public static class BoxedNullBooleanThrowsNPETest extends VarHandleUnitTest { + private static boolean z; + private static final VarHandle vh; + + static { + try { + Class<?> cls = BoxedNullBooleanThrowsNPETest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "z", boolean.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + Boolean newValue = null; + try { + vh.getAndSet(newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullBooleanThrowsNPETest().run(); + } + } + + public static class BoxedNullByteThrowsNPETest extends VarHandleUnitTest { + private byte b; + private static final VarHandle vh; + + static { + try { + Class<?> cls = BoxedNullByteThrowsNPETest.class; + vh = MethodHandles.lookup().findVarHandle(cls, "b", byte.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + Byte newValue = null; + try { + vh.getAndSet(this, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullByteThrowsNPETest().run(); + } + } + + public static class BoxedNullCharacterThrowsNPETest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.arrayElementVarHandle(char[].class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + char[] values = new char[3]; + Character newValue = null; + try { + vh.getAndSet(values, 0, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullCharacterThrowsNPETest().run(); + } + } + + public static class BoxedNullShortThrowsNPETest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + Class<?> cls = BoxedNullShortThrowsNPETest.class; + vh = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[2 * Short.SIZE]; + int index = VarHandleUnitTestHelpers.alignedOffset_short(bytes, 0); + Short newValue = null; + try { + vh.set(bytes, index, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullShortThrowsNPETest().run(); + } + } + + public static class BoxedNullIntegerThrowsNPETest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[2 * Integer.SIZE]; + int index = VarHandleUnitTestHelpers.alignedOffset_int(bytes, 0); + Integer newValue = null; + try { + vh.setVolatile(bytes, index, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullIntegerThrowsNPETest().run(); + } + } + + public static class BoxedNullLongThrowsNPETest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + Class<?> cls = BoxedNullLongThrowsNPETest.class; + vh = MethodHandles.byteBufferViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + ByteBuffer bb = ByteBuffer.allocateDirect(2 * Long.SIZE); + int index = VarHandleUnitTestHelpers.alignedOffset_long(bb, 0); + Long newValue = null; + try { + vh.getAndAdd(bb, index, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullLongThrowsNPETest().run(); + } + } + + public static class BoxedNullFloatThrowsNPETest extends VarHandleUnitTest { + private static final VarHandle vh; + + static { + try { + Class<?> cls = BoxedNullFloatThrowsNPETest.class; + vh = MethodHandles.byteBufferViewVarHandle(float[].class, ByteOrder.BIG_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + ByteBuffer bb = ByteBuffer.allocate(2 * Float.SIZE); + int index = VarHandleUnitTestHelpers.alignedOffset_float(bb, 0); + Float newValue = null; + try { + vh.set(bb, index, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullFloatThrowsNPETest().run(); + } + } + + public static class BoxedNullDoubleThrowsNPETest extends VarHandleUnitTest { + private double d; + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.byteBufferViewVarHandle(double[].class, ByteOrder.LITTLE_ENDIAN); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + byte[] bytes = new byte[3 * Double.SIZE]; + int offset = 1; + ByteBuffer bb = ByteBuffer.wrap(bytes, offset, bytes.length - offset); + int index = VarHandleUnitTestHelpers.alignedOffset_double(bb, 0); + Double newValue = null; + try { + vh.set(bb, index, newValue); + failUnreachable(); + } catch (NullPointerException ex) { + } + } + + public static void main(String[] args) { + new BoxedNullDoubleThrowsNPETest().run(); + } + } + + public static class WideningBooleanArgumentTest extends VarHandleUnitTest { + private static boolean v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningBooleanArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", boolean.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + vh.set(true); + try { + vh.set((byte) 3); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set('c'); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((short) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((int) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((long) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((float) 1.0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningBooleanArgumentTest().run(); + } + } + + public static class WideningByteArgumentTest extends VarHandleUnitTest { + private static byte v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningByteArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", byte.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((byte) 3); + try { + vh.set('c'); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((short) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((int) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((long) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((float) 1.0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningByteArgumentTest().run(); + } + } + + public static class WideningCharacterArgumentTest extends VarHandleUnitTest { + private static char v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningCharacterArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", char.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((byte) 3); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set('c'); + try { + vh.set((short) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((int) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((long) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((float) 1.0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningCharacterArgumentTest().run(); + } + } + + public static class WideningShortArgumentTest extends VarHandleUnitTest { + private static short v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningShortArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", short.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((byte) 3); + try { + vh.set('c'); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((short) 1); + try { + vh.set((int) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((long) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((float) 1.0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningShortArgumentTest().run(); + } + } + + public static class WideningIntegerArgumentTest extends VarHandleUnitTest { + private static int v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningIntegerArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", int.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((byte) 3); + vh.set('c'); + vh.set((char) 0x8fff); + assertEquals(0x8fff, v); + vh.set((short) 1); + vh.set((int) 1); + try { + vh.set((long) 1); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((float) 1.0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningIntegerArgumentTest().run(); + } + } + + public static class WideningLongArgumentTest extends VarHandleUnitTest { + private static long v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningLongArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", long.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((byte) 3); + vh.set('c'); + vh.set((short) 1); + vh.set((int) 1); + vh.set((long) 1); + try { + vh.set((float) 1.0f); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningLongArgumentTest().run(); + } + } + + public static class WideningFloatArgumentTest extends VarHandleUnitTest { + private static float v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningFloatArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", float.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((byte) 3); + vh.set('c'); + vh.set((short) 1); + vh.set((int) 1); + vh.set((long) 1); + vh.set((float) 1.0f); + try { + vh.set((double) 1.0); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningFloatArgumentTest().run(); + } + } + + public static class WideningDoubleArgumentTest extends VarHandleUnitTest { + private static double v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningDoubleArgumentTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", double.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + vh.set((byte) 3); + vh.set('c'); + vh.set((short) 1); + vh.set((int) 1); + vh.set((long) 1); + vh.set((double) 1.0f); + vh.set((double) 1.0); + } + + public static void main(String[] args) { + new WideningDoubleArgumentTest().run(); + } + } + + public static class WideningBooleanReturnValueTest extends VarHandleUnitTest { + private static boolean v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningBooleanReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", boolean.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + vh.set(true); + vh.get(); + boolean z = (boolean) vh.get(); + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + short s = (short) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + int i = (int) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + long j = (long) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + float f = (float) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + double d = (double) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + } + + public static void main(String[] args) { + new WideningBooleanReturnValueTest().run(); + } + } + + public static class WideningByteReturnValueTest extends VarHandleUnitTest { + private static byte v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningByteReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", byte.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + protected void doTest() { + vh.set((byte) 3); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + + byte b = (byte) vh.get(); + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + short s = (short) vh.get(); + int i = (int) vh.get(); + long j = (long) vh.get(); + float f = (float) vh.get(); + double d = (double) vh.get(); + } + + public static void main(String[] args) { + new WideningByteReturnValueTest().run(); + } + } + + public static class WideningCharacterReturnValueTest extends VarHandleUnitTest { + private static char v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningCharacterReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", char.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new WideningCharacterReturnValueTest().run(); + } + + @Override + protected void doTest() { + vh.set('c'); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + char c = (char) vh.get(); + try { + short s = (short) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + int i = (int) vh.get(); + long j = (long) vh.get(); + float f = (float) vh.get(); + double d = (double) vh.get(); + } + } + + public static class WideningShortReturnValueTest extends VarHandleUnitTest { + private static short v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningShortReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", short.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new WideningShortReturnValueTest().run(); + } + + @Override + protected void doTest() { + vh.set((short) 8888); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + short s = (short) vh.get(); + int i = (int) vh.get(); + long j = (long) vh.get(); + float f = (float) vh.get(); + double d = (double) vh.get(); + } + } + + public static class WideningIntegerReturnValueTest extends VarHandleUnitTest { + private static int v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningIntegerReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", int.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new WideningIntegerReturnValueTest().run(); + } + + @Override + protected void doTest() { + vh.set(0x1234fedc); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + short s = (short) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + int i = (int) vh.get(); + long j = (long) vh.get(); + float f = (float) vh.get(); + double d = (double) vh.get(); + } + } + + public static class WideningLongReturnValueTest extends VarHandleUnitTest { + private static long v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningLongReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", long.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new WideningLongReturnValueTest().run(); + } + + @Override + protected void doTest() { + vh.set(0xfedcba987654321l); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + short s = (short) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + int i = (int) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + long j = (long) vh.get(); + float f = (float) vh.get(); + double d = (double) vh.get(); + } + } + + public static class WideningFloatReturnValueTest extends VarHandleUnitTest { + private static float v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningFloatReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", float.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new WideningFloatReturnValueTest().run(); + } + + @Override + protected void doTest() { + vh.set(7.77e20f); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + short s = (short) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + int i = (int) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + long j = (long) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + float f = (float) vh.get(); + double d = (double) vh.get(); + } + } + + public static class WideningDoubleReturnValueTest extends VarHandleUnitTest { + private static double v; + private static final VarHandle vh; + + static { + try { + Class<?> cls = WideningDoubleReturnValueTest.class; + vh = MethodHandles.lookup().findStaticVarHandle(cls, "v", double.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new WideningDoubleReturnValueTest().run(); + } + + @Override + protected void doTest() { + vh.set(Math.E); + vh.get(); + try { + boolean z = (boolean) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + byte b = (byte) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + char c = (char) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + short s = (short) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + int i = (int) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + long j = (long) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + try { + float f = (float) vh.get(); + failUnreachable(); + } catch (WrongMethodTypeException ex) { + } + double d = (double) vh.get(); + } + } + + public static class SubtypeTest extends VarHandleUnitTest { + private static final Widget INITIAL_VALUE = Widget.ONE; + private static final VarHandle vh; + private Widget w = INITIAL_VALUE; + + static { + try { + vh = MethodHandles.lookup().findVarHandle(SubtypeTest.class, "w", Widget.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new SubtypeTest().run(); + } + + // A sub-type of the Widget class + public static class WidgetChild extends Widget { + private int weight; + + public WidgetChild(int requistionNumber, int weight) { + super(requistionNumber); + this.weight = weight; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof WidgetChild == false) { + return false; + } + WidgetChild wc = (WidgetChild) o; + return (requisitionNumber == wc.requisitionNumber && weight == wc.weight); + } + + public static final WidgetChild ONE = new WidgetChild(1, 100); + public static final WidgetChild TWO = new WidgetChild(2, 2000); + } + + @Override + public void doTest() { + assertEquals(INITIAL_VALUE, vh.getVolatile(this)); + vh.setVolatile(this, null); + Widget rw = (Widget) vh.compareAndExchange(this, null, WidgetChild.ONE); + assertEquals(null, rw); + assertEquals(WidgetChild.ONE, this.w); + WidgetChild rwc = + (WidgetChild) + vh.compareAndExchangeRelease(this, WidgetChild.ONE, WidgetChild.TWO); + assertEquals(WidgetChild.TWO, w); + rwc = (WidgetChild) vh.compareAndExchangeAcquire(this, WidgetChild.TWO, Widget.ONE); + assertEquals(Widget.ONE, w); + assertEquals(false, (boolean) vh.compareAndSet(this, null, null)); + assertEquals(true, vh.compareAndSet(this, Widget.ONE, Widget.TWO)); + assertEquals(Widget.TWO, w); + vh.set(this, null); + assertEquals(null, (Widget) vh.get(this)); + vh.setRelease(this, WidgetChild.ONE); + assertEquals(WidgetChild.ONE, (WidgetChild) vh.getAcquire(this)); + assertEquals(WidgetChild.ONE, w); + vh.setOpaque(this, WidgetChild.TWO); + assertEquals(WidgetChild.TWO, vh.getOpaque(this)); + assertEquals(WidgetChild.TWO, w); + vh.setVolatile(this, null); + assertEquals(null, (Widget) vh.getVolatile(this)); + assertEquals(null, w); + assertEquals(null, (WidgetChild) vh.getAndSet(this, WidgetChild.ONE)); + assertEquals(WidgetChild.ONE, w); + assertEquals(WidgetChild.ONE, (WidgetChild) vh.getAndSetRelease(this, WidgetChild.TWO)); + assertEquals(WidgetChild.TWO, (WidgetChild) vh.getAndSetAcquire(this, WidgetChild.ONE)); + try { + WidgetChild result = (WidgetChild) vh.getAndAdd(this, WidgetChild.ONE); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndAddAcquire(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndAddRelease(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseAnd(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseAndAcquire(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseAndRelease(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseOr(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseOrAcquire(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseOrRelease(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseXor(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseXorAcquire(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + try { + WidgetChild result = (WidgetChild) vh.getAndBitwiseXorRelease(this, 1); + failUnreachable(); + } catch (UnsupportedOperationException e) { + } + } + } + + public static class SupertypeTest extends VarHandleUnitTest { + private Widget w = null; + private static final VarHandle vh; + + static { + try { + vh = MethodHandles.lookup().findVarHandle(SupertypeTest.class, "w", Widget.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new SupertypeTest().run(); + } + + @Override + public void doTest() { + assertEquals(null, (Object) vh.get(this)); + vh.set(this, Widget.ONE); + assertEquals(Widget.ONE, vh.getVolatile(this)); + try { + vh.setVolatile(this, new Object()); + } catch (ClassCastException e) { + } + } + } + + public static class ImplicitBoxingIntegerTest extends VarHandleUnitTest { + private static Integer field; + private static final VarHandle vh; + + static { + try { + vh = + MethodHandles.lookup() + .findStaticVarHandle( + ImplicitBoxingIntegerTest.class, "field", Integer.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) { + new ImplicitBoxingIntegerTest().run(); + } + + @Override + public void doTest() { + try { + vh.set(true); + failUnreachable(); + } catch (WrongMethodTypeException e) { + } + try { + vh.set((byte) 0); + failUnreachable(); + } catch (WrongMethodTypeException e) { + } + try { + vh.set((short) 1); + failUnreachable(); + } catch (WrongMethodTypeException e) { + } + try { + vh.set('A'); + failUnreachable(); + } catch (WrongMethodTypeException e) { + } + vh.set(2); + try { + vh.setRelease(Long.MAX_VALUE); + } catch (WrongMethodTypeException e) { + } + try { + vh.setRelease(Float.MAX_VALUE); + } catch (WrongMethodTypeException e) { + } + try { + vh.setRelease(Double.MAX_VALUE); + } catch (WrongMethodTypeException e) { + } + vh.set(null); + vh.set(Integer.valueOf(Integer.MAX_VALUE)); + } + } + + public static void main(String[] args) { + VoidReturnTypeTest.main(args); + + BoxedNullBooleanThrowsNPETest.main(args); + BoxedNullByteThrowsNPETest.main(args); + BoxedNullCharacterThrowsNPETest.main(args); + BoxedNullShortThrowsNPETest.main(args); + BoxedNullIntegerThrowsNPETest.main(args); + BoxedNullLongThrowsNPETest.main(args); + BoxedNullFloatThrowsNPETest.main(args); + BoxedNullDoubleThrowsNPETest.main(args); + + WideningBooleanArgumentTest.main(args); + WideningByteArgumentTest.main(args); + WideningCharacterArgumentTest.main(args); + WideningShortArgumentTest.main(args); + WideningIntegerArgumentTest.main(args); + WideningLongArgumentTest.main(args); + WideningFloatArgumentTest.main(args); + WideningDoubleArgumentTest.main(args); + + WideningBooleanReturnValueTest.main(args); + WideningByteReturnValueTest.main(args); + WideningCharacterReturnValueTest.main(args); + WideningShortReturnValueTest.main(args); + WideningIntegerReturnValueTest.main(args); + WideningLongReturnValueTest.main(args); + WideningFloatReturnValueTest.main(args); + WideningDoubleReturnValueTest.main(args); + + SubtypeTest.main(args); + SupertypeTest.main(args); + + ImplicitBoxingIntegerTest.main(args); + } +} diff --git a/test/712-varhandle-invocations/src/VarHandleUnitTest.java b/test/712-varhandle-invocations/src/VarHandleUnitTest.java new file mode 100644 index 0000000000..601d470950 --- /dev/null +++ b/test/712-varhandle-invocations/src/VarHandleUnitTest.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2018 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. + */ + +// Base class for VarHandle unit tests for accessor operations +public abstract class VarHandleUnitTest { + public static VarHandleUnitTestCollector DEFAULT_COLLECTOR = new VarHandleUnitTestCollector(); + + // Error log (lazily initialized on failure). + private StringBuilder lazyErrorLog = null; + + // Tracker of test events (starts, skips, ends) + private final VarHandleUnitTestCollector collector; + + public VarHandleUnitTest(VarHandleUnitTestCollector collector) { + this.collector = collector; + } + + public VarHandleUnitTest() { + this.collector = DEFAULT_COLLECTOR; + } + + // Method that can be overloaded to signify that a test should be + // run or skipped. Returns true if the test should be run and + // false if the test should be skipped. + public boolean checkGuard() { + return true; + } + + // Method that implementations should use to perform a specific test. + protected abstract void doTest() throws Exception; + + public final void assertTrue(boolean value) { + assertEquals(true, value); + } + + public final void assertFalse(boolean value) { + assertEquals(false, value); + } + + public final void assertEquals(boolean expected, boolean actual) { + assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual)); + } + + public final void assertEquals(byte expected, byte actual) { + assertEquals(Byte.valueOf(expected), Byte.valueOf(actual)); + } + + public final void assertEquals(char expected, char actual) { + assertEquals(Character.valueOf(expected), Character.valueOf(actual)); + } + + public final void assertEquals(short expected, short actual) { + assertEquals(Short.valueOf(expected), Short.valueOf(actual)); + } + + public final void assertEquals(int expected, int actual) { + assertEquals(Integer.valueOf(expected), Integer.valueOf(actual)); + } + + public final void assertEquals(long expected, long actual) { + assertEquals(Long.valueOf(expected), Long.valueOf(actual)); + } + + public final void assertEquals(float expected, float actual) { + assertEquals(Float.valueOf(expected), Float.valueOf(actual)); + } + + public final void assertEquals(double expected, double actual) { + assertEquals(Double.valueOf(expected), Double.valueOf(actual)); + } + + public final void assertEquals(Object expected, Object actual) { + if (expected == null) { + if (actual == null) { + return; + } + } else if (expected.equals(actual)) { + return; + } + failNotEquals("Failed assertion (expected != actual)", expected, actual); + } + + public final void failUnreachable() { + fail("Unreachable code"); + } + + public final void run() { + collector.start(getClass().getSimpleName()); + if (!checkGuard()) { + collector.skip(); + return; + } + + try { + doTest(); + } catch (Exception e) { + fail("Unexpected exception", e); + } finally { + if (lazyErrorLog == null) { + collector.success(); + } else { + collector.fail(lazyErrorLog.toString()); + } + } + } + + private void failNotEquals(String message, Object expected, Object actual) { + errorLog() + .append(message) + .append(": ") + .append(expected) + .append(" != ") + .append(actual) + .append(" in ") + .append(getSourceInfo()) + .append('\n'); + } + + private void fail(String message) { + errorLog().append(message).append(" in ").append(getSourceInfo()).append('\n'); + } + + private void fail(String message, String detail) { + errorLog() + .append(message) + .append(": ") + .append(detail) + .append(" in ") + .append(getSourceInfo()) + .append('\n'); + } + + private void fail(String message, Exception e) { + errorLog() + .append(message) + .append(": ") + .append(e.toString()) + .append(" in ") + .append(getSourceInfo(e)) + .append('\n'); + } + + private String getSourceInfo(Exception e) { + // Unit test has thrown an exception. Stack likely looks like + // runtime frames then unit test frames then + // VarHandleUnitFrames. + StackTraceElement[] stackTraceElements = e.getStackTrace(); + int index = 1; + for (int i = 1; i < stackTraceElements.length; ++i) { + if ("VarHandleUnitTest".equals(stackTraceElements[i].getClassName())) { + return stackTraceElements[i - 1].toString(); + } + } + return "Unknown"; + } + + private String getSourceInfo() { + // Gets source info for a failure such as an assertion. The + // test has called a method on VarHandleUnitTest so the stack + // looks like some frames in VarHandleUnitTest methods and then + // a frame in the test itself. + StackTraceElement[] stackTraceElements = new Exception().getStackTrace(); + for (StackTraceElement stackTraceElement : stackTraceElements) { + if (!"VarHandleUnitTest".equals(stackTraceElement.getClassName())) { + return stackTraceElement.toString(); + } + } + return "Unknown"; + } + + private StringBuilder errorLog() { + if (lazyErrorLog == null) { + lazyErrorLog = new StringBuilder(); + } + return lazyErrorLog; + } +} diff --git a/test/712-varhandle-invocations/src/VarHandleUnitTestCollector.java b/test/712-varhandle-invocations/src/VarHandleUnitTestCollector.java new file mode 100644 index 0000000000..bc64c0c8b1 --- /dev/null +++ b/test/712-varhandle-invocations/src/VarHandleUnitTestCollector.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 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. + */ + +import java.io.PrintStream; + +// Results collector for VarHandle Unit tests +public final class VarHandleUnitTestCollector { + private final PrintStream out = System.out; + + private int numberOfSuccesses; + private int numberOfSkips; + private int numberOfFailures; + + public void start(String testName) { + out.print(testName); + out.print("..."); + } + + public void skip() { + numberOfSkips += 1; + out.println("SKIP"); + } + + public void success() { + numberOfSuccesses += 1; + out.println("OK"); + } + + public void fail(String errorMessage) { + numberOfFailures += 1; + out.println("FAIL"); + out.print(errorMessage); + } + + public void printSummary() { + out.append(Integer.toString(numberOfSuccesses)) + .append(" successes, ") + .append(Integer.toString(numberOfSkips)) + .append(" skips, ") + .append(Integer.toString(numberOfFailures)) + .append(" failures."); + out.println(); + } + + boolean failuresOccurred() { + return numberOfFailures != 0; + } +} diff --git a/test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java b/test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java new file mode 100644 index 0000000000..6f72e9962f --- /dev/null +++ b/test/712-varhandle-invocations/src/VarHandleUnitTestHelpers.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2018 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. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.VarHandle; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class VarHandleUnitTestHelpers { + public static boolean isRunningOnAndroid() { + return System.getProperty("java.vm.vendor").contains("Android"); + } + + public static boolean is64Bit() { + // The behaviour of certain accessors depends on the ISA word size. + if (isRunningOnAndroid()) { + try { + Class<?> runtimeClass = Class.forName("dalvik.system.VMRuntime"); + MethodHandle getRuntimeMH = + MethodHandles.lookup() + .findStatic( + runtimeClass, + "getRuntime", + MethodType.methodType(runtimeClass)); + Object runtime = getRuntimeMH.invoke(); + MethodHandle is64BitMH = + MethodHandles.lookup() + .findVirtual( + runtimeClass, + "is64Bit", + MethodType.methodType(boolean.class)); + return (boolean) is64BitMH.invoke(runtime); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } else { + return System.getProperty("sun.arch.data.model").equals("64"); + } + } + + public static boolean getBytesAs_boolean(byte[] array, int index, ByteOrder order) { + return getBytesAs_boolean(ByteBuffer.wrap(array), index, order); + } + + public static byte getBytesAs_byte(byte[] array, int index, ByteOrder order) { + return getBytesAs_byte(ByteBuffer.wrap(array), index, order); + } + + public static char getBytesAs_char(byte[] array, int index, ByteOrder order) { + return getBytesAs_char(ByteBuffer.wrap(array), index, order); + } + + public static short getBytesAs_short(byte[] array, int index, ByteOrder order) { + return getBytesAs_short(ByteBuffer.wrap(array), index, order); + } + + public static int getBytesAs_int(byte[] array, int index, ByteOrder order) { + return getBytesAs_int(ByteBuffer.wrap(array), index, order); + } + + public static long getBytesAs_long(byte[] array, int index, ByteOrder order) { + return getBytesAs_long(ByteBuffer.wrap(array), index, order); + } + + public static float getBytesAs_float(byte[] array, int index, ByteOrder order) { + return getBytesAs_float(ByteBuffer.wrap(array), index, order); + } + + public static double getBytesAs_double(byte[] array, int index, ByteOrder order) { + return getBytesAs_double(ByteBuffer.wrap(array), index, order); + } + + public static boolean getBytesAs_boolean(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).get(index) != 0; + } + + public static byte getBytesAs_byte(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).get(index); + } + + public static char getBytesAs_char(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).getChar(index); + } + + public static short getBytesAs_short(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).getShort(index); + } + + public static int getBytesAs_int(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).getInt(index); + } + + public static long getBytesAs_long(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).getLong(index); + } + + public static float getBytesAs_float(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).getFloat(index); + } + + public static double getBytesAs_double(ByteBuffer buffer, int index, ByteOrder order) { + return buffer.order(order).getDouble(index); + } + + public static void setBytesAs_boolean(byte[] array, int index, boolean value, ByteOrder order) { + setBytesAs_boolean(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_byte(byte[] array, int index, byte value, ByteOrder order) { + setBytesAs_byte(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_char(byte[] array, int index, char value, ByteOrder order) { + setBytesAs_char(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_short(byte[] array, int index, short value, ByteOrder order) { + setBytesAs_short(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_int(byte[] array, int index, int value, ByteOrder order) { + setBytesAs_int(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_long(byte[] array, int index, long value, ByteOrder order) { + setBytesAs_long(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_float(byte[] array, int index, float value, ByteOrder order) { + setBytesAs_float(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_double(byte[] array, int index, double value, ByteOrder order) { + setBytesAs_double(ByteBuffer.wrap(array), index, value, order); + } + + public static void setBytesAs_boolean( + ByteBuffer buffer, int index, boolean value, ByteOrder order) { + buffer.order(order).put(index, value ? (byte) 1 : (byte) 0); + } + + public static void setBytesAs_byte(ByteBuffer buffer, int index, byte value, ByteOrder order) { + buffer.order(order).put(index, value); + } + + public static void setBytesAs_char(ByteBuffer buffer, int index, char value, ByteOrder order) { + buffer.order(order).putChar(index, value); + } + + public static void setBytesAs_short( + ByteBuffer buffer, int index, short value, ByteOrder order) { + buffer.order(order).putShort(index, value); + } + + public static void setBytesAs_int(ByteBuffer buffer, int index, int value, ByteOrder order) { + buffer.order(order).putInt(index, value); + } + + public static void setBytesAs_long(ByteBuffer buffer, int index, long value, ByteOrder order) { + buffer.order(order).putLong(index, value); + } + + public static void setBytesAs_float( + ByteBuffer buffer, int index, float value, ByteOrder order) { + buffer.order(order).putFloat(index, value); + } + + public static void setBytesAs_double( + ByteBuffer buffer, int index, double value, ByteOrder order) { + buffer.order(order).putDouble(index, value); + } + + // Until ART is running on an OpenJDK9 based runtime, there are no + // calls to help with alignment. OpenJDK9 introduces + // ByteBuffer.alignedSlice() and ByteBuffer.alignmentOffset(). RI + // and ART have different data structure alignments which may make + // porting code interesting. + + public static int alignedOffset_char(ByteBuffer buffer, int start) { + return alignedOffset_short(buffer, start); + } + + public static int alignedOffset_short(ByteBuffer buffer, int start) { + for (int i = 0; i < Short.SIZE; ++i) { + try { + vh_probe_short.getVolatile(buffer, start + i); + return start + i; + } catch (IllegalStateException e) { + // Unaligned access. + } + } + return start; + } + + public static int alignedOffset_int(ByteBuffer buffer, int start) { + for (int i = 0; i < Integer.SIZE; ++i) { + try { + vh_probe_int.getVolatile(buffer, start + i); + return start + i; + } catch (IllegalStateException e) { + // Unaligned access. + } catch (Exception e) { + break; + } + } + return start; + } + + public static int alignedOffset_long(ByteBuffer buffer, int start) { + for (int i = 0; i < Long.SIZE; ++i) { + try { + vh_probe_long.getVolatile(buffer, start + i); + return start + i; + } catch (IllegalStateException e) { + // Unaligned access. + } catch (UnsupportedOperationException e) { + // 64-bit operation is not supported irrespective of alignment. + break; + } + } + return start; + } + + public static int alignedOffset_float(ByteBuffer buffer, int start) { + return alignedOffset_int(buffer, start); + } + + public static int alignedOffset_double(ByteBuffer buffer, int start) { + return alignedOffset_long(buffer, start); + } + + public static int alignedOffset_char(byte[] array, int start) { + return alignedOffset_char(ByteBuffer.wrap(array), start); + } + + public static int alignedOffset_short(byte[] array, int start) { + return alignedOffset_short(ByteBuffer.wrap(array), start); + } + + public static int alignedOffset_int(byte[] array, int start) { + return alignedOffset_int(ByteBuffer.wrap(array), start); + } + + public static int alignedOffset_long(byte[] array, int start) { + return alignedOffset_long(ByteBuffer.wrap(array), start); + } + + public static int alignedOffset_float(byte[] array, int start) { + return alignedOffset_float(ByteBuffer.wrap(array), start); + } + + public static int alignedOffset_double(byte[] array, int start) { + return alignedOffset_double(ByteBuffer.wrap(array), start); + } + + static { + ByteOrder order = ByteOrder.LITTLE_ENDIAN; + vh_probe_short = MethodHandles.byteBufferViewVarHandle(short[].class, order); + vh_probe_int = MethodHandles.byteBufferViewVarHandle(int[].class, order); + vh_probe_long = MethodHandles.byteBufferViewVarHandle(long[].class, order); + } + + private static final VarHandle vh_probe_short; + private static final VarHandle vh_probe_int; + private static final VarHandle vh_probe_long; +} diff --git a/test/712-varhandle-invocations/src/Widget.java b/test/712-varhandle-invocations/src/Widget.java new file mode 100644 index 0000000000..0282ff8d64 --- /dev/null +++ b/test/712-varhandle-invocations/src/Widget.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 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. + */ + +// Widget class for reference type accessor tests. +public class Widget { + protected int requisitionNumber; + + public Widget(int requisitionNumber) { + this.requisitionNumber = requisitionNumber; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Widget)) { + return false; + } + Widget wo = (Widget) o; + return requisitionNumber == wo.requisitionNumber; + } + + public static final Widget ONE = new Widget(1); + public static final Widget TWO = new Widget(2); +} diff --git a/test/712-varhandle-invocations/util-src/generate_java.py b/test/712-varhandle-invocations/util-src/generate_java.py new file mode 100644 index 0000000000..9520b53844 --- /dev/null +++ b/test/712-varhandle-invocations/util-src/generate_java.py @@ -0,0 +1,876 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2018 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. + +""" +Generate java test files for 712-varhandle-invocations +""" + +from enum import Enum +from pathlib import Path +from random import Random +from string import Template + +import io +import re +import sys + +class JavaType(object): + def __init__(self, name, examples, supports_bitwise=False, supports_numeric=False): + self.name=name + self.examples=examples + self.supports_bitwise=supports_bitwise + self.supports_numeric=supports_numeric + + def is_value_type(self): + return False + + def __repr__(self): + return self.name + + def __str__(self): + return self.name + +class ValueType(JavaType): + def __init__(self, name, boxed_type, examples, ordinal=-1, width=-1, supports_bitwise=True, supports_numeric=True): + JavaType.__init__(self, name, examples, supports_bitwise, supports_numeric) + self.ordinal=ordinal + self.width=width + self.boxed_type=boxed_type + + def boxing_method(self): + return self.boxed_type + ".valueOf" + + def unboxing_method(self): + return self.name + "Value" + + def is_value_type(self): + return True + + def __eq__(self, other): + return self.ordinal == other.ordinal + + def __hash__(self): + return self.ordinal + + def __le__(self, other): + return self.ordinal < other.ordinal + + def __repr__(self): + return self.name + + def __str__(self): + return self.name + +BOOLEAN_TYPE = ValueType("boolean", "Boolean", [ "true", "false" ], ordinal = 0, width = 1, supports_numeric=False) +BYTE_TYPE=ValueType("byte", "Byte", [ "(byte) -128", "(byte) -61", "(byte) 7", "(byte) 127", "(byte) 33" ], ordinal=1, width=1) +SHORT_TYPE=ValueType("short", "Short", [ "(short) -32768", "(short) -384", "(short) 32767", "(short) 0xaa55" ], ordinal=2, width=2) +CHAR_TYPE=ValueType("char", "Character", [ r"'A'", r"'#'", r"'$'", r"'Z'", r"'t'", r"'c'" ], ordinal=3, width=2) +INT_TYPE=ValueType("int", "Integer", [ "-0x01234567", "0x7f6e5d4c", "0x12345678", "0x10215220", "42" ], ordinal=4, width=4) +LONG_TYPE=ValueType("long", "Long", [ "-0x0123456789abcdefl", "0x789abcdef0123456l", "0xfedcba9876543210l" ], ordinal=5, width=8) +FLOAT_TYPE=ValueType("float", "Float", [ "-7.77e23f", "1.234e-17f", "3.40e36f", "-8.888e3f", "4.442e11f" ], ordinal=6, width=4, supports_bitwise=False) +DOUBLE_TYPE=ValueType("double", "Double", [ "-1.0e-200", "1.11e200", "3.141", "1.1111", "6.022e23", "6.626e-34" ], ordinal=7, width=4, supports_bitwise=False) + +VALUE_TYPES = { BOOLEAN_TYPE, BYTE_TYPE, SHORT_TYPE, CHAR_TYPE, INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE } + +WIDENING_CONVERSIONS = { + BOOLEAN_TYPE : set(), + BYTE_TYPE : { SHORT_TYPE, INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, + SHORT_TYPE : { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, + CHAR_TYPE : { INT_TYPE, LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, + INT_TYPE : { LONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE }, + LONG_TYPE : { FLOAT_TYPE, DOUBLE_TYPE }, + FLOAT_TYPE : { DOUBLE_TYPE }, + DOUBLE_TYPE : set() +} + +def types_that_widen_to(var_type): + types_that_widen = { var_type } + for src_type in WIDENING_CONVERSIONS: + if var_type in WIDENING_CONVERSIONS[src_type]: + types_that_widen.add(src_type) + return types_that_widen + +class VarHandleKind(object): + ALL_SUPPORTED_TYPES = VALUE_TYPES + VIEW_SUPPORTED_TYPES = list(filter(lambda x : x.width >= 2, ALL_SUPPORTED_TYPES)) + + def __init__(self, name, imports=[], declarations=[], lookup='', coordinates=[], get_value='', may_throw_read_only=False): + self.name = name + self.imports = imports + self.declarations = declarations + self.lookup = lookup + self.coordinates = coordinates + self.get_value_ = get_value + self.may_throw_read_only = may_throw_read_only + + def get_name(self): + return self.name + + def get_coordinates(self): + return self.coordinates + + def get_field_declarations(self, dictionary): + return list(map(lambda d: Template(d).safe_substitute(dictionary), self.declarations)) + + def get_imports(self): + return self.imports + + def get_lookup(self, dictionary): + return Template(self.lookup).safe_substitute(dictionary) + + def get_supported_types(self): + return VarHandleKind.VIEW_SUPPORTED_TYPES if self.is_view() else VarHandleKind.ALL_SUPPORTED_TYPES + + def is_view(self): + return "View" in self.name + + def get_value(self, dictionary): + return Template(self.get_value_).safe_substitute(dictionary) + +FIELD_VAR_HANDLE = VarHandleKind("Field", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle' + ], + [ + "${var_type} field = ${initial_value}" + ], + 'MethodHandles.lookup().findVarHandle(${test_class}.class, "field", ${var_type}.class)', + [ + 'this' + ], + 'field', + may_throw_read_only = False) + +FINAL_FIELD_VAR_HANDLE = VarHandleKind("FinalField", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle' + ], + [ + "${var_type} field = ${initial_value}" + ], + 'MethodHandles.lookup().findVarHandle(${test_class}.class, "field", ${var_type}.class)', + [ + 'this' + ], + 'field', + may_throw_read_only = False) + +STATIC_FIELD_VAR_HANDLE = VarHandleKind("StaticField", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle' + ], + [ + "static ${var_type} field = ${initial_value}" + ], + 'MethodHandles.lookup().findStaticVarHandle(${test_class}.class, "field", ${var_type}.class)', + [], + 'field', + may_throw_read_only = False) + +STATIC_FINAL_FIELD_VAR_HANDLE = VarHandleKind("StaticFinalField", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle' + ], + [ + "static ${var_type} field = ${initial_value}" + ], + 'MethodHandles.lookup().findStaticVarHandle(${test_class}.class, "field", ${var_type}.class)', + [], + 'field', + may_throw_read_only = False) + +ARRAY_ELEMENT_VAR_HANDLE = VarHandleKind("ArrayElement", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle' + ], + [ + "${var_type}[] array = new ${var_type}[11]", + "int index = 3", + "{ array[index] = ${initial_value}; }" + ], + 'MethodHandles.arrayElementVarHandle(${var_type}[].class)', + [ 'array', 'index'], + 'array[index]', + may_throw_read_only = False) + +BYTE_ARRAY_LE_VIEW_VAR_HANDLE = VarHandleKind("ByteArrayViewLE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteOrder' + ], + [ + "byte[] array = new byte[27]", + "int index = 8", + "{" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" + "}" + ], + 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', + [ + 'array', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.LITTLE_ENDIAN)', + may_throw_read_only = False) + +BYTE_ARRAY_BE_VIEW_VAR_HANDLE = VarHandleKind("ByteArrayViewBE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteOrder' + ], + [ + "byte[] array = new byte[27]", + "int index = 8", + "{" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(array, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" + "}" + ], + 'MethodHandles.byteArrayViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', + [ + 'array', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(array, index, ByteOrder.BIG_ENDIAN)', + may_throw_read_only = False) + +DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("DirectByteBufferViewLE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteBuffer', + 'java.nio.ByteOrder' + ], + [ + "ByteBuffer bb = ByteBuffer.allocateDirect(31)", + "int index = 8", + "{" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" + "}" + ], + 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', + [ + 'bb', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', + may_throw_read_only = False) + +DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("DirectByteBufferViewBE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteBuffer', + 'java.nio.ByteOrder' + ], + [ + "ByteBuffer bb = ByteBuffer.allocateDirect(31)", + "int index = 8", + "{" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" + "}" + ], + 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', + [ + 'bb', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', + may_throw_read_only = False) + +HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferViewLE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteBuffer', + 'java.nio.ByteOrder' + ], + [ + "byte[] array = new byte[36]", + "int offset = 8", + "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)", + "int index = 8", + "{" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" + "}" + ], + 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', + [ + 'bb', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', + may_throw_read_only = False) + +HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferViewBE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteBuffer', + 'java.nio.ByteOrder' + ], + [ + "byte[] array = new byte[47]", + "int offset = 8", + "ByteBuffer bb = ByteBuffer.wrap(array, offset, array.length - offset)", + "int index = 8", + "{" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(bb, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" + "}" + ], + 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', + [ + 'bb', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', + may_throw_read_only = False) + +HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferReadOnlyViewLE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteBuffer', + 'java.nio.ByteOrder', + 'java.nio.ReadOnlyBufferException' + ], + [ + "byte[] array = new byte[43]", + "int index = 8", + "ByteBuffer bb", + "{" + " bb = ByteBuffer.wrap(array).asReadOnlyBuffer();" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, index);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.LITTLE_ENDIAN);" + " bb = bb.asReadOnlyBuffer();" + + "}" + ], + 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.LITTLE_ENDIAN)', + [ + 'bb', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.LITTLE_ENDIAN)', + may_throw_read_only = True) + +HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE = VarHandleKind("HeapByteBufferReadOnlyViewBE", + [ + 'java.lang.invoke.MethodHandles', + 'java.lang.invoke.VarHandle', + 'java.nio.ByteBuffer', + 'java.nio.ByteOrder', + 'java.nio.ReadOnlyBufferException' + ], + [ + "byte[] array = new byte[29]", + "int index", + "ByteBuffer bb", + "{" + " bb = ByteBuffer.wrap(array);" + " index = VarHandleUnitTestHelpers.alignedOffset_${var_type}(bb, 8);" + " VarHandleUnitTestHelpers.setBytesAs_${var_type}(array, index, ${initial_value}, ByteOrder.BIG_ENDIAN);" + " bb = bb.asReadOnlyBuffer();" + "}" + ], + 'MethodHandles.byteBufferViewVarHandle(${var_type}[].class, ByteOrder.BIG_ENDIAN)', + [ + 'bb', + 'index' + ], + 'VarHandleUnitTestHelpers.getBytesAs_${var_type}(bb, index, ByteOrder.BIG_ENDIAN)', + may_throw_read_only = True) + +ALL_FIELD_VAR_HANDLE_KINDS = [ + FIELD_VAR_HANDLE, + FINAL_FIELD_VAR_HANDLE, + STATIC_FIELD_VAR_HANDLE, + STATIC_FINAL_FIELD_VAR_HANDLE +] + +ALL_BYTE_VIEW_VAR_HANDLE_KINDS = [ + BYTE_ARRAY_LE_VIEW_VAR_HANDLE, + BYTE_ARRAY_BE_VIEW_VAR_HANDLE, + DIRECT_BYTE_BUFFER_LE_VIEW_VAR_HANDLE, + DIRECT_BYTE_BUFFER_BE_VIEW_VAR_HANDLE, + HEAP_BYTE_BUFFER_LE_VIEW_VAR_HANDLE, + HEAP_BYTE_BUFFER_BE_VIEW_VAR_HANDLE, + HEAP_BYTE_BUFFER_RO_LE_VIEW_VAR_HANDLE, + HEAP_BYTE_BUFFER_RO_BE_VIEW_VAR_HANDLE +] + +ALL_VAR_HANDLE_KINDS = ALL_FIELD_VAR_HANDLE_KINDS + [ ARRAY_ELEMENT_VAR_HANDLE ] + ALL_BYTE_VIEW_VAR_HANDLE_KINDS + +class AccessModeForm(Enum): + GET = 0 + SET = 1 + STRONG_COMPARE_AND_SET = 2 + WEAK_COMPARE_AND_SET = 3 + COMPARE_AND_EXCHANGE = 4 + GET_AND_SET = 5 + GET_AND_UPDATE_BITWISE = 6 + GET_AND_UPDATE_NUMERIC = 7 + +class VarHandleAccessor: + def __init__(self, method_name): + self.method_name = method_name + self.access_mode = self.get_access_mode(method_name) + self.access_mode_form = self.get_access_mode_form(method_name) + + def get_return_type(self, var_type): + if self.access_mode_form == AccessModeForm.SET: + return None + elif (self.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET or + self.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET): + return BOOLEAN_TYPE + else: + return var_type + + def get_number_of_var_type_arguments(self): + if self.access_mode_form == AccessModeForm.GET: + return 0 + elif (self.access_mode_form == AccessModeForm.SET or + self.access_mode_form == AccessModeForm.GET_AND_SET or + self.access_mode_form == AccessModeForm.GET_AND_UPDATE_BITWISE or + self.access_mode_form == AccessModeForm.GET_AND_UPDATE_NUMERIC): + return 1 + elif (self.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET or + self.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET or + self.access_mode_form == AccessModeForm.COMPARE_AND_EXCHANGE): + return 2 + else: + raise ValueError(self.access_mode_form) + + def is_read_only(self): + return self.access_mode_form == AccessModeForm.GET + + def get_java_bitwise_operator(self): + if "BitwiseAnd" in self.method_name: + return "&" + elif "BitwiseOr" in self.method_name: + return "|" + elif "BitwiseXor" in self.method_name: + return "^" + raise ValueError(self.method_name) + + def get_java_numeric_operator(self): + if "Add" in self.method_name: + return "+" + raise ValueError(self.method_name) + + @staticmethod + def get_access_mode(accessor_method): + """Converts an access method name to AccessMode value. For example, getAndSet becomes GET_AND_SET""" + return re.sub('([A-Z])', r'_\1', accessor_method).upper() + + @staticmethod + def get_access_mode_form(accessor_method): + prefix_mode_list = [ + ('getAndAdd', AccessModeForm.GET_AND_UPDATE_NUMERIC), + ('getAndBitwise', AccessModeForm.GET_AND_UPDATE_BITWISE), + ('getAndSet', AccessModeForm.GET_AND_SET), + ('get', AccessModeForm.GET), + ('set', AccessModeForm.SET), + ('compareAndSet', AccessModeForm.STRONG_COMPARE_AND_SET), + ('weakCompareAndSet', AccessModeForm.WEAK_COMPARE_AND_SET), + ('compareAndExchange', AccessModeForm.COMPARE_AND_EXCHANGE)] + for prefix, mode in prefix_mode_list: + if accessor_method.startswith(prefix): + return mode + raise ValueError(accessor_method) + +VAR_HANDLE_ACCESSORS = [ + VarHandleAccessor('get'), + VarHandleAccessor('set'), + VarHandleAccessor('getVolatile'), + VarHandleAccessor('setVolatile'), + VarHandleAccessor('getAcquire'), + VarHandleAccessor('setRelease'), + VarHandleAccessor('getOpaque'), + VarHandleAccessor('setOpaque'), + VarHandleAccessor('compareAndSet'), + VarHandleAccessor('compareAndExchange'), + VarHandleAccessor('compareAndExchangeAcquire'), + VarHandleAccessor('compareAndExchangeRelease'), + VarHandleAccessor('weakCompareAndSetPlain'), + VarHandleAccessor('weakCompareAndSet'), + VarHandleAccessor('weakCompareAndSetAcquire'), + VarHandleAccessor('weakCompareAndSetRelease'), + VarHandleAccessor('getAndSet'), + VarHandleAccessor('getAndSetAcquire'), + VarHandleAccessor('getAndSetRelease'), + VarHandleAccessor('getAndAdd'), + VarHandleAccessor('getAndAddAcquire'), + VarHandleAccessor('getAndAddRelease'), + VarHandleAccessor('getAndBitwiseOr'), + VarHandleAccessor('getAndBitwiseOrRelease'), + VarHandleAccessor('getAndBitwiseOrAcquire'), + VarHandleAccessor('getAndBitwiseAnd'), + VarHandleAccessor('getAndBitwiseAndRelease'), + VarHandleAccessor('getAndBitwiseAndAcquire'), + VarHandleAccessor('getAndBitwiseXor'), + VarHandleAccessor('getAndBitwiseXorRelease'), + VarHandleAccessor('getAndBitwiseXorAcquire') +] + +# Pseudo-RNG used for arbitrary decisions +RANDOM = Random(0) + +BANNER = '// This file is generated by util-src/generate_java.py do not directly modify!' + +# List of generated test classes +GENERATED_TEST_CLASSES = [] + +def java_file_for_class(class_name): + return class_name + ".java" + +def capitalize_first(word): + return word[0].upper() + word[1:] + +def indent_code(code): + """Applies rudimentary indentation to code""" + return code + +def build_template_dictionary(test_class, var_handle_kind, accessor, var_type): + initial_value = RANDOM.choice(var_type.examples) + updated_value = RANDOM.choice(list(filter(lambda v : v != initial_value, var_type.examples))) + coordinates = ", ".join(var_handle_kind.get_coordinates()) + if accessor.get_number_of_var_type_arguments() != 0 and coordinates != "": + coordinates += ", " + dictionary = { + 'accessor_method' : accessor.method_name, + 'access_mode' : accessor.access_mode, + 'banner' : BANNER, + 'coordinates' : coordinates, + 'initial_value' : initial_value, + 'test_class' : test_class, + 'updated_value' : updated_value, + 'var_type' : var_type, + } + dictionary['imports'] = ";\n".join(list(map(lambda x: "import " + x, var_handle_kind.get_imports()))) + dictionary['lookup'] = var_handle_kind.get_lookup(dictionary) + dictionary['field_declarations'] = ";\n".join(var_handle_kind.get_field_declarations(dictionary)) + dictionary['read_value'] = var_handle_kind.get_value(dictionary) + return dictionary + +def emit_accessor_test(var_handle_kind, accessor, var_type, output_path): + test_class = var_handle_kind.get_name() + capitalize_first(accessor.method_name) + capitalize_first(var_type.name) + GENERATED_TEST_CLASSES.append(test_class) + src_file_path = output_path / java_file_for_class(test_class) + expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type) + # Compute test operation + if accessor.access_mode_form == AccessModeForm.GET: + test_template = Template(""" + ${var_type} value = (${var_type}) vh.${accessor_method}(${coordinates}); + assertEquals(${initial_value}, value);""") + elif accessor.access_mode_form == AccessModeForm.SET: + test_template = Template(""" + vh.${accessor_method}(${coordinates}${updated_value}); + assertEquals(${updated_value}, ${read_value});""") + elif accessor.access_mode_form == AccessModeForm.STRONG_COMPARE_AND_SET: + test_template = Template(""" + assertEquals(${initial_value}, ${read_value}); + // Test an update that should succeed. + boolean applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); + assertEquals(${updated_value}, ${read_value}); + assertTrue(applied); + // Test an update that should fail. + applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value}); + assertFalse(applied); + assertEquals(${updated_value}, ${read_value});""") + elif accessor.access_mode_form == AccessModeForm.WEAK_COMPARE_AND_SET: + test_template = Template(""" + assertEquals(${initial_value}, ${read_value}); + // Test an update that should succeed. + int attempts = 10000; + boolean applied; + do { + applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); + } while (applied == false && attempts-- > 0); + assertEquals(${updated_value}, ${read_value}); + assertTrue(attempts > 0); + // Test an update that should fail. + applied = (boolean) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value}); + assertFalse(applied); + assertEquals(${updated_value}, ${read_value});""") + elif accessor.access_mode_form == AccessModeForm.COMPARE_AND_EXCHANGE: + test_template = Template(""" + // This update should succeed. + ${var_type} witness_value = (${var_type}) vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); + assertEquals(${initial_value}, witness_value); + assertEquals(${updated_value}, ${read_value}); + // This update should fail. + witness_value = (${var_type}) vh.${accessor_method}(${coordinates}${initial_value}, ${initial_value}); + assertEquals(${updated_value}, witness_value); + assertEquals(${updated_value}, ${read_value});""") + elif accessor.access_mode_form == AccessModeForm.GET_AND_SET: + test_template = Template(""" + ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value}); + assertEquals(${initial_value}, old_value); + assertEquals(${updated_value}, ${read_value});""") + elif accessor.access_mode_form == AccessModeForm.GET_AND_UPDATE_BITWISE: + if var_type.supports_bitwise == True: + expansions['binop'] = accessor.get_java_bitwise_operator() + test_template = Template(""" + ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value}); + assertEquals(${initial_value}, old_value); + assertEquals(${initial_value} ${binop} ${updated_value}, ${read_value});""") + else: + test_template = Template(""" + vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); + failUnreachable();""") + elif accessor.access_mode_form == AccessModeForm.GET_AND_UPDATE_NUMERIC: + if var_type.supports_numeric == True: + expansions['binop'] = accessor.get_java_numeric_operator() + test_template = Template(""" + ${var_type} old_value = (${var_type}) vh.${accessor_method}(${coordinates}${updated_value}); + assertEquals(${initial_value}, old_value); + ${var_type} expected_value = (${var_type}) (${initial_value} ${binop} ${updated_value}); + assertEquals(expected_value, ${read_value});""") + else: + test_template = Template(""" + vh.${accessor_method}(${coordinates}${initial_value}, ${updated_value}); + failUnreachable();""") + else: + raise ValueError(accessor.access_mode_form) + + if var_handle_kind.may_throw_read_only and not accessor.is_read_only(): + # ByteBufferViews can be read-only and dynamically raise ReadOnlyBufferException. + expansions['try_statement'] = "try {" + expansions['catch_statement'] = "failUnreachable();\n} catch (ReadOnlyBufferException ex) {}" + else: + expansions['try_statement'] = "" + expansions['catch_statement'] = "" + + expansions['test_body'] = test_template.safe_substitute(expansions) + + s = Template("""${banner} + +${imports}; + +class ${test_class} extends VarHandleUnitTest { + ${field_declarations}; + static final VarHandle vh; + static { + try { + vh = ${lookup}; + } catch (Exception e) { + throw new RuntimeException("Unexpected initialization exception", e); + } + } + + @Override + public void doTest() throws Exception { + if (!vh.isAccessModeSupported(VarHandle.AccessMode.${access_mode})) { + try { + ${test_body} + failUnreachable(); + } catch (UnsupportedOperationException ex) {} + } else { + ${try_statement} + ${test_body} + ${catch_statement} + } + } + + public static void main(String[] args) { + new ${test_class}().run(); + } +} +""").safe_substitute(expansions) + with src_file_path.open("w") as src_file: + print(s, file=src_file) + +def emit_value_type_accessor_tests(output_path): + for var_handle_kind in ALL_VAR_HANDLE_KINDS: + for accessor in VAR_HANDLE_ACCESSORS: + for var_type in var_handle_kind.get_supported_types(): + emit_accessor_test(var_handle_kind, accessor, var_type, output_path) + +def emit_reference_accessor_tests(output_path): + ref_type = JavaType("Widget", [ "Widget.ONE", "Widget.TWO", "null" ]) + for var_handle_kind in ALL_VAR_HANDLE_KINDS: + if var_handle_kind.is_view(): + # Views as reference type arrays are not supported. They + # fail instantiation. This is tested in 710-varhandle-creation. + continue + for accessor in VAR_HANDLE_ACCESSORS: + emit_accessor_test(var_handle_kind, accessor, ref_type, output_path) + +def emit_boxing_value_type_accessor_test(accessor, var_type, output_path): + test_class = "Boxing" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name) + GENERATED_TEST_CLASSES.append(test_class) + src_file_path = output_path / java_file_for_class(test_class) + var_handle_kind = FIELD_VAR_HANDLE + expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type) + template = Template(""" +${banner} + +${imports}; +import java.lang.invoke.WrongMethodTypeException; + +public class ${test_class} extends VarHandleUnitTest { + ${field_declarations}; + private static final VarHandle vh; + static { + try { + vh = ${lookup}; + } catch (Exception e) { + throw new RuntimeException("Unexpected initialization exception", e); + } + } + + @Override + public void doTest() throws Exception { + ${body} + } + + public static void main(String[] args) { + new ${test_class}().run(); + } +} +""") + with io.StringIO() as body_text: + compatible_types = types_that_widen_to(var_type) + for value_type in VALUE_TYPES: + print("try {", file=body_text) + return_type = accessor.get_return_type(var_type) + if return_type: + print("{0} result = ({0}) ".format(return_type), end="", file=body_text) + print("vh.{0}(this".format(accessor.method_name), end="", file=body_text) + num_args = accessor.get_number_of_var_type_arguments() + for i in range(0, num_args): + print(", {0}({1})".format(value_type.boxing_method(), value_type.examples[i]), end="", file=body_text) + print(");", file=body_text) + if value_type in compatible_types: + print(" assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), + file=body_text) + else: + print("failUnreachable();", file=body_text) + print("} catch (WrongMethodTypeException e) {", file=body_text) + print("} catch (UnsupportedOperationException e) {", file=body_text) + print(" assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), + file=body_text) + print("}", file=body_text) + expansions['body'] = body_text.getvalue(); + with src_file_path.open("w") as src_file: + print(template.safe_substitute(expansions), file=src_file) + +def emit_boxing_return_value_type_test(accessor, var_type, output_path): + test_class = "BoxingReturn" + capitalize_first(accessor.method_name) + capitalize_first(var_type.name) + GENERATED_TEST_CLASSES.append(test_class) + src_file_path = output_path / java_file_for_class(test_class) + var_handle_kind = FIELD_VAR_HANDLE + expansions = build_template_dictionary(test_class, var_handle_kind, accessor, var_type) + template = Template(""" +${banner} + +${imports}; +import java.lang.invoke.WrongMethodTypeException; + +public class ${test_class} extends VarHandleUnitTest { + ${field_declarations}; + private static final VarHandle vh; + static { + try { + vh = ${lookup}; + } catch (Exception e) { + throw new RuntimeException("Unexpected initialization exception", e); + } + } + + @Override + public void doTest() throws Exception { + ${body} + } + + public static void main(String[] args) { + new ${test_class}().run(); + } +} +""") + with io.StringIO() as body_text: + return_type = accessor.get_return_type(var_type) + compatible_types = { return_type } + for value_type in VALUE_TYPES: + print("try {", file=body_text) + print("{0} result = ({0}) ".format(value_type.boxed_type), end="", file=body_text) + print("vh.{0}(this".format(accessor.method_name), end="", file=body_text) + num_args = accessor.get_number_of_var_type_arguments() + for i in range(0, num_args): + print(", {0})".format(var_type.examples[i]), end="", file=body_text) + print(");", file=body_text) + if value_type in compatible_types: + print(" assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), + file=body_text) + else: + print("failUnreachable();", file=body_text) + print("} catch (WrongMethodTypeException e) {", file=body_text) + print("} catch (UnsupportedOperationException e) {", file=body_text) + print(" assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.{0}));".format(accessor.access_mode), + file=body_text) + print("}", file=body_text) + expansions['body'] = body_text.getvalue(); + with src_file_path.open("w") as src_file: + print(template.safe_substitute(expansions), file=src_file) + +def emit_boxing_value_type_accessor_tests(output_path): + for var_type in VALUE_TYPES: + for accessor in VAR_HANDLE_ACCESSORS: + if accessor.get_number_of_var_type_arguments() > 0: + emit_boxing_value_type_accessor_test(accessor, var_type, output_path) + else: + emit_boxing_return_value_type_test(accessor, var_type, output_path) + +def emit_main(output_path, manual_test_classes): + main_file_path = output_path / "Main.java" + all_test_classes = GENERATED_TEST_CLASSES + manual_test_classes + with main_file_path.open("w") as main_file: + print("// " + BANNER, file=main_file) + print(""" +public class Main { + public static void main(String[] args) { +""", file=main_file) + for cls in all_test_classes: + print(" " + cls + ".main(args);", file=main_file) + print(" VarHandleUnitTest.DEFAULT_COLLECTOR.printSummary();", file=main_file) + print(" System.exit(VarHandleUnitTest.DEFAULT_COLLECTOR.failuresOccurred() ? 1 : 0);", file=main_file) + print(" }\n}", file=main_file) + +def main(argv): + final_java_dir = Path(argv[1]) + if not final_java_dir.exists() or not final_java_dir.is_dir(): + print("{} is not a valid java dir".format(final_java_dir), file=sys.stderr) + sys.exit(1) + emit_value_type_accessor_tests(final_java_dir) + emit_reference_accessor_tests(final_java_dir) + emit_boxing_value_type_accessor_tests(final_java_dir) + emit_main(final_java_dir, argv[2:]) + +if __name__ == '__main__': + main(sys.argv) diff --git a/test/etc/default-build b/test/etc/default-build index 4dc2393c54..6040f7d910 100755 --- a/test/etc/default-build +++ b/test/etc/default-build @@ -124,18 +124,20 @@ JACK_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-D jack.java.source.version=1.8 - declare -A SMALI_EXPERIMENTAL_ARGS SMALI_EXPERIMENTAL_ARGS["default-methods"]="--api 24" SMALI_EXPERIMENTAL_ARGS["method-handles"]="--api 26" +SMALI_EXPERIMENTAL_ARGS["var-handles"]="--api 26" SMALI_EXPERIMENTAL_ARGS["agents"]="--api 26" declare -A JAVAC_EXPERIMENTAL_ARGS JAVAC_EXPERIMENTAL_ARGS["default-methods"]="-source 1.8 -target 1.8" JAVAC_EXPERIMENTAL_ARGS["lambdas"]="-source 1.8 -target 1.8" JAVAC_EXPERIMENTAL_ARGS["method-handles"]="-source 1.8 -target 1.8" -# We need to leave javac at default 1.7 so that dx will continue to work +JAVAC_EXPERIMENTAL_ARGS["var-handles"]="-source 1.8 -target 1.8" JAVAC_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-source 1.8 -target 1.8" JAVAC_EXPERIMENTAL_ARGS["agents"]="-source 1.8 -target 1.8" declare -A DX_EXPERIMENTAL_ARGS DX_EXPERIMENTAL_ARGS["method-handles"]="--min-sdk-version=26" +DX_EXPERIMENTAL_ARGS["var-handles"]="--min-sdk-version=26" while true; do if [ "x$1" = "x--dx-option" ]; then @@ -441,7 +443,7 @@ else if [ "${HAS_SRC2}" = "true" ]; then mkdir -p classes - ${JAVAC} ${JAVAC_ARGS} -d classes `find src2 -name '*.java'` + ${JAVAC} ${JAVAC_ARGS} -classpath classes -d classes `find src2 -name '*.java'` fi if [[ "${HAS_SRC}" == "true" || "${HAS_SRC2}" == "true" || "${HAS_SRC_ART}" == "true" ]]; then |