mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-24 20:38:14 +00:00
Merge
This commit is contained in:
commit
9f3b6be989
@ -33,6 +33,7 @@ include GensrcCharsetMapping.gmk
|
||||
include GensrcCharsetCoder.gmk
|
||||
include GensrcBuffer.gmk
|
||||
include GensrcExceptions.gmk
|
||||
include GensrcVarHandles.gmk
|
||||
include GensrcModuleLoaderMap.gmk
|
||||
|
||||
################################################################################
|
||||
|
||||
162
jdk/make/gensrc/GensrcVarHandles.gmk
Normal file
162
jdk/make/gensrc/GensrcVarHandles.gmk
Normal file
@ -0,0 +1,162 @@
|
||||
#
|
||||
# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
GENSRC_VARHANDLES :=
|
||||
|
||||
VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
|
||||
VARHANDLES_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/invoke
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a VarHandle java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
define GenerateVarHandle
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Object Int Long), )
|
||||
$1_ARGS += -KCAS
|
||||
endif
|
||||
|
||||
ifneq ($$(findstring $$($1_Type), Int Long), )
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
|
||||
ifeq ($$($1_Type), Object)
|
||||
$$(eval $1_type := $$($1_Type))
|
||||
else
|
||||
$$(eval $1_type := $$$$(shell $(TR) '[:upper:]' '[:lower:]' <<< $$$$($1_Type)))
|
||||
endif
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(TOOL_SPP) -nel -K$$($1_type) -Dtype=$$($1_type) -DType=$$($1_Type) \
|
||||
$$($1_ARGS) < $$< > $$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# Setup a rule for generating a VarHandleByteArray java class
|
||||
# Param 1 - Variable declaration prefix
|
||||
# Param 2 - Type with first letter capitalized
|
||||
define GenerateVarHandleByteArray
|
||||
|
||||
$1_Type := $2
|
||||
|
||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleByteArrayAs$$($1_Type)s.java
|
||||
|
||||
ifeq ($$($1_Type), Short)
|
||||
$1_type := short
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Char)
|
||||
$1_type := char
|
||||
$1_BoxType := Character
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Int)
|
||||
$1_type := int
|
||||
$1_BoxType := Integer
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Long)
|
||||
$1_type := long
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := $$($1_type)
|
||||
$1_RawType := $$($1_Type)
|
||||
$1_RawBoxType := $$($1_BoxType)
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KAtomicAdd
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Float)
|
||||
$1_type := float
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := int
|
||||
$1_RawType := Int
|
||||
$1_RawBoxType := Integer
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
ifeq ($$($1_Type), Double)
|
||||
$1_type := double
|
||||
$1_BoxType := $$($1_Type)
|
||||
|
||||
$1_rawType := long
|
||||
$1_RawType := Long
|
||||
$1_RawBoxType := Long
|
||||
|
||||
$1_ARGS += -KCAS
|
||||
$1_ARGS += -KfloatingPoint
|
||||
endif
|
||||
|
||||
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleByteArrayView.java.template $(BUILD_TOOLS_JDK)
|
||||
$$(call MakeDir, $$(@D))
|
||||
$(TOOL_SPP) -nel -K$$($1_type) \
|
||||
-Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
|
||||
-DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
|
||||
$$($1_ARGS) < $$< > $$@
|
||||
|
||||
GENSRC_VARHANDLES += $$($1_FILENAME)
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_TYPES := Boolean Byte Short Char Int Long Float Double Object
|
||||
$(foreach t, $(VARHANDLES_TYPES), \
|
||||
$(eval $(call GenerateVarHandle,VAR_HANDLE_$t,$t)))
|
||||
|
||||
# List the types to generate source for, with capitalized first letter
|
||||
VARHANDLES_BYTE_ARRAY_TYPES := Short Char Int Long Float Double
|
||||
$(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
|
||||
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
|
||||
|
||||
GENSRC_JAVA_BASE += $(GENSRC_VARHANDLES)
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -146,7 +146,7 @@ class StringCoding {
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
private static boolean hasNegatives(byte[] ba, int off, int len) {
|
||||
public static boolean hasNegatives(byte[] ba, int off, int len) {
|
||||
for (int i = off; i < off + len; i++) {
|
||||
if (ba[i] < 0) {
|
||||
return true;
|
||||
|
||||
@ -41,7 +41,7 @@ class InfoFromMemberName implements MethodHandleInfo {
|
||||
private final int referenceKind;
|
||||
|
||||
InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
|
||||
assert(member.isResolved() || member.isMethodHandleInvoke());
|
||||
assert(member.isResolved() || member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke());
|
||||
assert(member.referenceKindIsConsistentWith(referenceKind));
|
||||
this.member = member;
|
||||
this.referenceKind = referenceKind;
|
||||
@ -79,7 +79,8 @@ class InfoFromMemberName implements MethodHandleInfo {
|
||||
|
||||
@Override
|
||||
public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
|
||||
if (member.isMethodHandleInvoke() && !member.isVarargs()) {
|
||||
if ((member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke())
|
||||
&& !member.isVarargs()) {
|
||||
// This member is an instance of a signature-polymorphic method, which cannot be reflected
|
||||
// A method handle invoker can come in either of two forms:
|
||||
// A generic placeholder (present in the source code, and varargs)
|
||||
|
||||
@ -93,6 +93,16 @@ class Invokers {
|
||||
return setCachedInvoker(INV_BASIC, invoker);
|
||||
}
|
||||
|
||||
/*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
|
||||
// TODO cache invoker
|
||||
return makeVarHandleMethodInvoker(ak);
|
||||
}
|
||||
|
||||
/*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
|
||||
// TODO cache invoker
|
||||
return makeVarHandleMethodExactInvoker(ak);
|
||||
}
|
||||
|
||||
private MethodHandle cachedInvoker(int idx) {
|
||||
return invokers[idx];
|
||||
}
|
||||
@ -117,6 +127,36 @@ class Invokers {
|
||||
return invoker;
|
||||
}
|
||||
|
||||
private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
|
||||
MethodType mtype = targetType;
|
||||
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
|
||||
|
||||
LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.name(), mtype);
|
||||
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
|
||||
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
|
||||
|
||||
invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
|
||||
assert(checkVarHandleInvoker(invoker));
|
||||
|
||||
maybeCompileToBytecode(invoker);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
|
||||
MethodType mtype = targetType;
|
||||
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
|
||||
|
||||
LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.name(), mtype);
|
||||
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
|
||||
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
|
||||
|
||||
invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
|
||||
assert(checkVarHandleInvoker(invoker));
|
||||
|
||||
maybeCompileToBytecode(invoker);
|
||||
return invoker;
|
||||
}
|
||||
|
||||
/** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
|
||||
private void maybeCompileToBytecode(MethodHandle invoker) {
|
||||
final int EAGER_COMPILE_ARITY_LIMIT = 10;
|
||||
@ -146,6 +186,16 @@ class Invokers {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkVarHandleInvoker(MethodHandle invoker) {
|
||||
MethodType invokerType = targetType.insertParameterTypes(0, VarHandle.class);
|
||||
assert(invokerType.equals(invoker.type()))
|
||||
: java.util.Arrays.asList(targetType, invokerType, invoker);
|
||||
assert(invoker.internalMemberName() == null ||
|
||||
invoker.internalMemberName().getMethodType().equals(targetType));
|
||||
assert(!invoker.isVarargsCollector());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find or create an invoker which passes unchanged a given number of arguments
|
||||
* and spreads the rest from a trailing array argument.
|
||||
@ -193,9 +243,9 @@ class Invokers {
|
||||
Object[] appendixResult) {
|
||||
int which;
|
||||
switch (name) {
|
||||
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
|
||||
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
|
||||
default: throw new InternalError("not invoker: "+name);
|
||||
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
|
||||
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
|
||||
default: throw new InternalError("not invoker: "+name);
|
||||
}
|
||||
LambdaForm lform;
|
||||
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
|
||||
@ -296,6 +346,199 @@ class Invokers {
|
||||
return lform;
|
||||
}
|
||||
|
||||
|
||||
static MemberName varHandleInvokeLinkerMethod(String name,
|
||||
MethodType mtype) {
|
||||
LambdaForm lform;
|
||||
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
|
||||
lform = varHandleMethodGenericLinkerHandleForm(name, mtype);
|
||||
} else {
|
||||
// TODO
|
||||
throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount());
|
||||
}
|
||||
return lform.vmentry;
|
||||
}
|
||||
|
||||
private static LambdaForm varHandleMethodGenericLinkerHandleForm(String name, MethodType mtype) {
|
||||
// TODO Cache form?
|
||||
|
||||
final int THIS_VH = 0;
|
||||
final int ARG_BASE = THIS_VH + 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int VAD_ARG = nameCursor++;
|
||||
final int CHECK_TYPE = nameCursor++;
|
||||
final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
|
||||
Name[] names = new Name[LINKER_CALL + 1];
|
||||
names[THIS_VH] = argument(THIS_VH, BasicType.basicType(Object.class));
|
||||
for (int i = 0; i < mtype.parameterCount(); i++) {
|
||||
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
|
||||
}
|
||||
names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.basicType(Object.class));
|
||||
|
||||
names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[THIS_VH], names[VAD_ARG]);
|
||||
|
||||
Object[] outArgs = new Object[ARG_LIMIT + 1];
|
||||
outArgs[0] = names[CHECK_TYPE];
|
||||
for (int i = 0; i < ARG_LIMIT; i++) {
|
||||
outArgs[i + 1] = names[i];
|
||||
}
|
||||
|
||||
if (CHECK_CUSTOM != -1) {
|
||||
names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
|
||||
}
|
||||
|
||||
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
|
||||
.basicType();
|
||||
names[LINKER_CALL] = new Name(outCallType, outArgs);
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT + 1, names);
|
||||
|
||||
lform.prepare();
|
||||
return lform;
|
||||
}
|
||||
|
||||
private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
|
||||
// TODO Cache form?
|
||||
|
||||
final int THIS_MH = 0;
|
||||
final int CALL_VH = THIS_MH + 1;
|
||||
final int ARG_BASE = CALL_VH + 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int VAD_ARG = nameCursor++;
|
||||
final int CHECK_TYPE = nameCursor++;
|
||||
final int GET_MEMBER = nameCursor++;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
|
||||
MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
|
||||
.basicType()
|
||||
.appendParameterTypes(MemberName.class);
|
||||
|
||||
MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
|
||||
try {
|
||||
linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw newInternalError(ex);
|
||||
}
|
||||
|
||||
Name[] names = new Name[LINKER_CALL + 1];
|
||||
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
|
||||
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
|
||||
for (int i = 0; i < mtype.parameterCount(); i++) {
|
||||
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
|
||||
}
|
||||
|
||||
BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
|
||||
names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
|
||||
|
||||
NamedFunction getter = speciesData.getterFunction(0);
|
||||
names[VAD_ARG] = new Name(getter, names[THIS_MH]);
|
||||
|
||||
Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
|
||||
|
||||
names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
|
||||
|
||||
names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
|
||||
outArgs[outArgs.length - 1] = names[GET_MEMBER];
|
||||
|
||||
names[LINKER_CALL] = new Name(linker, outArgs);
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT, names);
|
||||
|
||||
lform.prepare();
|
||||
return lform;
|
||||
}
|
||||
|
||||
private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
|
||||
// TODO Cache form?
|
||||
|
||||
final int THIS_MH = 0;
|
||||
final int CALL_VH = THIS_MH + 1;
|
||||
final int ARG_BASE = CALL_VH + 1;
|
||||
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
|
||||
int nameCursor = ARG_LIMIT;
|
||||
final int VAD_ARG = nameCursor++;
|
||||
final int CHECK_TYPE = nameCursor++;
|
||||
final int LINKER_CALL = nameCursor++;
|
||||
|
||||
Name[] names = new Name[LINKER_CALL + 1];
|
||||
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
|
||||
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
|
||||
for (int i = 0; i < mtype.parameterCount(); i++) {
|
||||
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
|
||||
}
|
||||
|
||||
BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
|
||||
names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
|
||||
|
||||
NamedFunction getter = speciesData.getterFunction(0);
|
||||
names[VAD_ARG] = new Name(getter, names[THIS_MH]);
|
||||
|
||||
names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
|
||||
|
||||
Object[] outArgs = new Object[ARG_LIMIT];
|
||||
outArgs[0] = names[CHECK_TYPE];
|
||||
for (int i = 1; i < ARG_LIMIT; i++) {
|
||||
outArgs[i] = names[i];
|
||||
}
|
||||
|
||||
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
|
||||
.basicType();
|
||||
names[LINKER_CALL] = new Name(outCallType, outArgs);
|
||||
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
|
||||
ARG_LIMIT, names);
|
||||
|
||||
lform.prepare();
|
||||
return lform;
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
if (mn == null)
|
||||
throw vh.unsupported();
|
||||
// TODO the following MH is not constant, cache in stable field array
|
||||
// on VarForm?
|
||||
MethodHandle mh = DirectMethodHandle.make(mn);
|
||||
if (actual == expected) {
|
||||
return mh;
|
||||
}
|
||||
else {
|
||||
// Adapt to the actual (which should never fail since mh's method
|
||||
// type is in the basic form), then to the expected (which my fail
|
||||
// if the symbolic type descriptor does not match)
|
||||
// TODO optimize for the case of actual.erased() == expected.erased()
|
||||
return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
|
||||
asType(expected.insertParameterTypes(0, VarHandle.class));
|
||||
}
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MethodType expected = vad.symbolicMethodType;
|
||||
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
|
||||
if (actual != expected)
|
||||
throw newWrongMethodTypeException(expected, actual);
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
@ForceInline
|
||||
MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
|
||||
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
|
||||
if (mn == null) {
|
||||
throw vh.unsupported();
|
||||
}
|
||||
return mn;
|
||||
}
|
||||
|
||||
/*non-public*/ static
|
||||
WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
|
||||
// FIXME: merge with JVM logic for throwing WMTE
|
||||
@ -415,7 +658,10 @@ class Invokers {
|
||||
NF_checkExactType,
|
||||
NF_checkGenericType,
|
||||
NF_getCallSiteTarget,
|
||||
NF_checkCustomized;
|
||||
NF_checkCustomized,
|
||||
NF_checkVarHandleGenericType,
|
||||
NF_checkVarHandleExactType,
|
||||
NF_getVarHandleMemberName;
|
||||
static {
|
||||
try {
|
||||
NamedFunction nfs[] = {
|
||||
@ -426,7 +672,13 @@ class Invokers {
|
||||
NF_getCallSiteTarget = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("getCallSiteTarget", CallSite.class)),
|
||||
NF_checkCustomized = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("checkCustomized", MethodHandle.class))
|
||||
.getDeclaredMethod("checkCustomized", MethodHandle.class)),
|
||||
NF_checkVarHandleGenericType = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
|
||||
NF_checkVarHandleExactType = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
|
||||
NF_getVarHandleMemberName = new NamedFunction(Invokers.class
|
||||
.getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
|
||||
};
|
||||
// Each nf must be statically invocable or we get tied up in our bootstraps.
|
||||
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
|
||||
|
||||
@ -363,6 +363,23 @@ import java.util.Objects;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean isVarHandleMethodInvoke() {
|
||||
final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
|
||||
final int negs = Modifier.STATIC;
|
||||
if (testFlags(bits | negs, bits) &&
|
||||
clazz == VarHandle.class) {
|
||||
return isVarHandleMethodInvokeName(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean isVarHandleMethodInvokeName(String name) {
|
||||
try {
|
||||
VarHandle.AccessMode.valueOf(name);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
|
||||
|
||||
/** Utility method to query the modifier flags of this member. */
|
||||
@ -538,6 +555,17 @@ import java.util.Objects;
|
||||
if (isMethodHandleInvoke())
|
||||
return;
|
||||
}
|
||||
if (m.getDeclaringClass() == VarHandle.class &&
|
||||
isVarHandleMethodInvokeName(m.getName())) {
|
||||
// The JVM did not reify this signature-polymorphic instance.
|
||||
// Need a special case here.
|
||||
// See comments on MethodHandleNatives.linkMethod.
|
||||
MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
|
||||
int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
|
||||
init(VarHandle.class, m.getName(), type, flags);
|
||||
if (isVarHandleMethodInvoke())
|
||||
return;
|
||||
}
|
||||
throw new LinkageError(m.toString());
|
||||
}
|
||||
assert(isResolved() && this.clazz != null);
|
||||
@ -666,6 +694,16 @@ import java.util.Objects;
|
||||
return mem;
|
||||
}
|
||||
|
||||
static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
|
||||
return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
|
||||
}
|
||||
static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
|
||||
MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
|
||||
mem.flags |= mods; // it's not resolved, but add these modifiers anyway
|
||||
assert(mem.isVarHandleMethodInvoke()) : mem;
|
||||
return mem;
|
||||
}
|
||||
|
||||
// bare-bones constructor; the JVM will fill it in
|
||||
MemberName() { }
|
||||
|
||||
|
||||
@ -26,9 +26,11 @@
|
||||
package java.lang.invoke;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
|
||||
/**
|
||||
@ -92,14 +94,16 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* and {@code invoke} compile to an {@code invokevirtual} instruction.
|
||||
* More unusually, the compiler must record the actual argument types,
|
||||
* and may not perform method invocation conversions on the arguments.
|
||||
* Instead, it must push them on the stack according to their own unconverted types.
|
||||
* The method handle object itself is pushed on the stack before the arguments.
|
||||
* The compiler then calls the method handle with a symbolic type descriptor which
|
||||
* describes the argument and return types.
|
||||
* Instead, it must generate instructions that push them on the stack according
|
||||
* to their own unconverted types. The method handle object itself is pushed on
|
||||
* the stack before the arguments.
|
||||
* The compiler then generates an {@code invokevirtual} instruction that invokes
|
||||
* the method handle with a symbolic type descriptor which describes the argument
|
||||
* and return types.
|
||||
* <p>
|
||||
* To issue a complete symbolic type descriptor, the compiler must also determine
|
||||
* the return type. This is based on a cast on the method invocation expression,
|
||||
* if there is one, or else {@code Object} if the invocation is an expression
|
||||
* if there is one, or else {@code Object} if the invocation is an expression,
|
||||
* or else {@code void} if the invocation is a statement.
|
||||
* The cast may be to a primitive type (but not {@code void}).
|
||||
* <p>
|
||||
@ -109,12 +113,12 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* {@code Void} except the null reference.
|
||||
*
|
||||
* <h1>Method handle invocation</h1>
|
||||
* The first time a {@code invokevirtual} instruction is executed
|
||||
* it is linked, by symbolically resolving the names in the instruction
|
||||
* The first time an {@code invokevirtual} instruction is executed
|
||||
* it is linked by symbolically resolving the names in the instruction
|
||||
* and verifying that the method call is statically legal.
|
||||
* This is true of calls to {@code invokeExact} and {@code invoke}.
|
||||
* This also holds for calls to {@code invokeExact} and {@code invoke}.
|
||||
* In this case, the symbolic type descriptor emitted by the compiler is checked for
|
||||
* correct syntax and names it contains are resolved.
|
||||
* correct syntax, and names it contains are resolved.
|
||||
* Thus, an {@code invokevirtual} instruction which invokes
|
||||
* a method handle will always link, as long
|
||||
* as the symbolic type descriptor is syntactically well-formed
|
||||
@ -163,7 +167,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* in a program which uses method handles.
|
||||
* <p>
|
||||
* Because method types contain "live" {@code Class} objects,
|
||||
* method type matching takes into account both types names and class loaders.
|
||||
* method type matching takes into account both type names and class loaders.
|
||||
* Thus, even if a method handle {@code M} is created in one
|
||||
* class loader {@code L1} and used in another {@code L2},
|
||||
* method handle calls are type-safe, because the caller's symbolic type
|
||||
@ -174,7 +178,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* and its type is assigned, while the resolution in {@code L2} happens
|
||||
* when the {@code invokevirtual} instruction is linked.
|
||||
* <p>
|
||||
* Apart from the checking of type descriptors,
|
||||
* Apart from type descriptor checks,
|
||||
* a method handle's capability to call its underlying method is unrestricted.
|
||||
* If a method handle is formed on a non-public method by a class
|
||||
* that has access to that method, the resulting handle can be used
|
||||
@ -196,7 +200,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
|
||||
* Java code can create a method handle that directly accesses
|
||||
* any method, constructor, or field that is accessible to that code.
|
||||
* This is done via a reflective, capability-based API called
|
||||
* {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
|
||||
* {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}.
|
||||
* For example, a static method handle can be obtained
|
||||
* from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
|
||||
* There are also conversion methods from Core Reflection API objects,
|
||||
|
||||
@ -1060,6 +1060,19 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
|
||||
return mh;
|
||||
}
|
||||
static MethodHandle fakeVarHandleInvoke(MemberName method) {
|
||||
// TODO caching, is it necessary?
|
||||
MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
|
||||
VarHandle.class, Object[].class);
|
||||
MethodHandle mh = throwException(type);
|
||||
mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
|
||||
if (!method.getInvocationType().equals(mh.type()))
|
||||
throw new InternalError(method.toString());
|
||||
mh = mh.withInternalMemberName(method, false);
|
||||
mh = mh.asVarargsCollector(Object[].class);
|
||||
assert(method.isVarargs());
|
||||
return mh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an alias for the method handle which, when called,
|
||||
|
||||
@ -25,12 +25,15 @@
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import sun.invoke.util.Wrapper;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
|
||||
/**
|
||||
* The JVM interface for the method handles package is all here.
|
||||
@ -367,8 +370,14 @@ class MethodHandleNatives {
|
||||
Class<?> defc, String name, Object type,
|
||||
Object[] appendixResult) {
|
||||
try {
|
||||
if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
|
||||
return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
|
||||
if (refKind == REF_invokeVirtual) {
|
||||
if (defc == MethodHandle.class) {
|
||||
return Invokers.methodHandleInvokeLinkerMethod(
|
||||
name, fixMethodType(callerClass, type), appendixResult);
|
||||
} else if (defc == VarHandle.class) {
|
||||
return varHandleOperationLinkerMethod(
|
||||
name, fixMethodType(callerClass, type), appendixResult);
|
||||
}
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
if (ex instanceof LinkageError)
|
||||
@ -400,6 +409,80 @@ class MethodHandleNatives {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the method to link to the VarHandle operation.
|
||||
* This method is located here and not in Invokers to avoid
|
||||
* intializing that and other classes early on in VM bootup.
|
||||
*/
|
||||
private static MemberName varHandleOperationLinkerMethod(String name,
|
||||
MethodType mtype,
|
||||
Object[] appendixResult) {
|
||||
// Get the signature method type
|
||||
MethodType sigType = mtype.basicType();
|
||||
|
||||
// Get the access kind from the method name
|
||||
VarHandle.AccessMode ak;
|
||||
try {
|
||||
ak = VarHandle.AccessMode.valueOf(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw MethodHandleStatics.newInternalError(e);
|
||||
}
|
||||
|
||||
// If not polymorphic in the return type, such as the compareAndSet
|
||||
// methods that return boolean
|
||||
if (ak.isPolyMorphicInReturnType) {
|
||||
if (ak.returnType != mtype.returnType()) {
|
||||
// The caller contains a different return type than that
|
||||
// defined by the method
|
||||
throw newNoSuchMethodErrorOnVarHandle(name, mtype);
|
||||
}
|
||||
// Adjust the return type of the signature method type
|
||||
sigType = sigType.changeReturnType(ak.returnType);
|
||||
}
|
||||
|
||||
// Get the guard method type for linking
|
||||
MethodType guardType = sigType
|
||||
// VarHandle at start
|
||||
.insertParameterTypes(0, VarHandle.class)
|
||||
// Access descriptor at end
|
||||
.appendParameterTypes(VarHandle.AccessDescriptor.class);
|
||||
|
||||
// Create the appendix descriptor constant
|
||||
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
|
||||
appendixResult[0] = ad;
|
||||
|
||||
if (MethodHandleStatics.VAR_HANDLE_GUARDS) {
|
||||
MemberName linker = new MemberName(
|
||||
VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
|
||||
guardType, REF_invokeStatic);
|
||||
try {
|
||||
return MemberName.getFactory().resolveOrFail(
|
||||
REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
// Fall back to lambda form linkage if guard method is not available
|
||||
// TODO Optionally log fallback ?
|
||||
}
|
||||
}
|
||||
return Invokers.varHandleInvokeLinkerMethod(name, mtype);
|
||||
}
|
||||
static String getVarHandleMethodSignature(MethodType mt) {
|
||||
StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
|
||||
|
||||
for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
Class<?> pt = mt.parameterType(i);
|
||||
sb.append(getCharType(pt));
|
||||
}
|
||||
|
||||
sb.append('_').append(getCharType(mt.returnType()));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
static char getCharType(Class<?> pt) {
|
||||
return Wrapper.forBasicType(pt).basicTypeChar();
|
||||
}
|
||||
static NoSuchMethodError newNoSuchMethodErrorOnVarHandle(String name, MethodType mtype) {
|
||||
return new NoSuchMethodError("VarHandle." + name + mtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
|
||||
|
||||
@ -50,9 +50,10 @@ import jdk.internal.misc.Unsafe;
|
||||
static final int PROFILE_LEVEL;
|
||||
static final boolean PROFILE_GWT;
|
||||
static final int CUSTOMIZE_THRESHOLD;
|
||||
static final boolean VAR_HANDLE_GUARDS;
|
||||
|
||||
static {
|
||||
final Object[] values = new Object[9];
|
||||
final Object[] values = new Object[10];
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public Void run() {
|
||||
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
|
||||
@ -64,6 +65,7 @@ import jdk.internal.misc.Unsafe;
|
||||
values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
|
||||
values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
|
||||
values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
|
||||
values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -76,6 +78,7 @@ import jdk.internal.misc.Unsafe;
|
||||
PROFILE_LEVEL = (Integer) values[6];
|
||||
PROFILE_GWT = (Boolean) values[7];
|
||||
CUSTOMIZE_THRESHOLD = (Integer) values[8];
|
||||
VAR_HANDLE_GUARDS = (Boolean) values[9];
|
||||
|
||||
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
|
||||
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
|
||||
|
||||
@ -53,6 +53,10 @@ import java.util.stream.Stream;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
|
||||
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.*;
|
||||
import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* This class consists exclusively of static methods that operate on or return
|
||||
* method handles. They fall into several categories:
|
||||
@ -873,7 +877,14 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
|
||||
* {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
|
||||
* {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
|
||||
* with the same {@code type} argument.
|
||||
*
|
||||
* <p>
|
||||
* If the class is {@code VarHandle} and the name string corresponds to
|
||||
* the name of a signature-polymorphic access mode method, the resulting
|
||||
* method handle is equivalent to one produced by
|
||||
* {@link java.lang.invoke.MethodHandles#varHandleInvoker} with
|
||||
* the access mode corresponding to the name string and with the same
|
||||
* {@code type} arguments.
|
||||
* <p>
|
||||
* <b>Example:</b>
|
||||
* <blockquote><pre>{@code
|
||||
import static java.lang.invoke.MethodHandles.*;
|
||||
@ -920,6 +931,9 @@ assertEquals("", (String) MH_newString.invokeExact());
|
||||
if (refc == MethodHandle.class) {
|
||||
MethodHandle mh = findVirtualForMH(name, type);
|
||||
if (mh != null) return mh;
|
||||
} else if (refc == VarHandle.class) {
|
||||
MethodHandle mh = findVirtualForVH(name, type);
|
||||
if (mh != null) return mh;
|
||||
}
|
||||
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
|
||||
MemberName method = resolveOrFail(refKind, refc, name, type);
|
||||
@ -936,6 +950,13 @@ assertEquals("", (String) MH_newString.invokeExact());
|
||||
assert(!MemberName.isMethodHandleInvokeName(name));
|
||||
return null;
|
||||
}
|
||||
private MethodHandle findVirtualForVH(String name, MethodType type) {
|
||||
try {
|
||||
return varHandleInvoker(VarHandle.AccessMode.valueOf(name), type);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a method handle which creates an object and initializes it, using
|
||||
@ -1135,6 +1156,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @see #findVarHandle(Class, String, Class)
|
||||
*/
|
||||
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName field = resolveOrFail(REF_getField, refc, name, type);
|
||||
@ -1157,12 +1179,60 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @see #findVarHandle(Class, String, Class)
|
||||
*/
|
||||
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName field = resolveOrFail(REF_putField, refc, name, type);
|
||||
return getDirectField(REF_putField, refc, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to non-static fields of type
|
||||
* {@code T} declared by a receiver class of type {@code R}, supporting
|
||||
* shape {@code (R : T)}.
|
||||
* <p>
|
||||
* Access checking is performed immediately on behalf of the lookup
|
||||
* class.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the field is declared {@code final}, then the write, atomic
|
||||
* update, and numeric atomic update access modes are unsupported.
|
||||
* <li>if the field type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the field type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the field is declared {@code volatile} then the returned VarHandle
|
||||
* will override access to the field (effectively ignore the
|
||||
* {@code volatile} declaration) in accordance to it's specified
|
||||
* access modes.
|
||||
* @param recv the receiver class, of type {@code R}, that declares the
|
||||
* non-static field
|
||||
* @param name the field's name
|
||||
* @param type the field's type, of type {@code T}
|
||||
* @return a VarHandle giving access to non-static fields.
|
||||
* @throws NoSuchFieldException if the field does not exist
|
||||
* @throws IllegalAccessException if access checking fails, or if the field is {@code static}
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @since 9
|
||||
*/
|
||||
public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName getField = resolveOrFail(REF_getField, recv, name, type);
|
||||
MemberName putField = resolveOrFail(REF_putField, recv, name, type);
|
||||
return getFieldVarHandle(REF_getField, REF_putField, recv, getField, putField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a method handle giving read access to a static field.
|
||||
* The type of the method handle will have a return type of the field's
|
||||
@ -1211,6 +1281,55 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
|
||||
return getDirectField(REF_putStatic, refc, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to a static field of type
|
||||
* {@code T} declared by a given declaring class, supporting shape
|
||||
* {@code ((empty) : T)}.
|
||||
* <p>
|
||||
* Access checking is performed immediately on behalf of the lookup
|
||||
* class.
|
||||
* <p>
|
||||
* If the returned VarHandle is operated on, the declaring class will be
|
||||
* initialized, if it has not already been initialized.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the field is declared {@code final}, then the write, atomic
|
||||
* update, and numeric atomic update access modes are unsupported.
|
||||
* <li>if the field type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the field type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the field is declared {@code volatile} then the returned VarHandle
|
||||
* will override access to the field (effectively ignore the
|
||||
* {@code volatile} declaration) in accordance to it's specified
|
||||
* access modes.
|
||||
* @param decl the class that declares the static field
|
||||
* @param name the field's name
|
||||
* @param type the field's type, of type {@code T}
|
||||
* @return a VarHandle giving access to a static field
|
||||
* @throws NoSuchFieldException if the field does not exist
|
||||
* @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
|
||||
* @exception SecurityException if a security manager is present and it
|
||||
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
|
||||
* @throws NullPointerException if any argument is null
|
||||
* @since 9
|
||||
*/
|
||||
public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
|
||||
MemberName getField = resolveOrFail(REF_getStatic, decl, name, type);
|
||||
MemberName putField = resolveOrFail(REF_putStatic, decl, name, type);
|
||||
return getFieldVarHandle(REF_getStatic, REF_putStatic, decl, getField, putField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces an early-bound method handle for a non-static method.
|
||||
* The receiver must have a supertype {@code defc} in which a method
|
||||
@ -1297,6 +1416,10 @@ return mh1;
|
||||
MethodHandle mh = unreflectForMH(m);
|
||||
if (mh != null) return mh;
|
||||
}
|
||||
if (m.getDeclaringClass() == VarHandle.class) {
|
||||
MethodHandle mh = unreflectForVH(m);
|
||||
if (mh != null) return mh;
|
||||
}
|
||||
MemberName method = new MemberName(m);
|
||||
byte refKind = method.getReferenceKind();
|
||||
if (refKind == REF_invokeSpecial)
|
||||
@ -1311,6 +1434,12 @@ return mh1;
|
||||
return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
|
||||
return null;
|
||||
}
|
||||
private MethodHandle unreflectForVH(Method m) {
|
||||
// these names require special lookups because they throw UnsupportedOperationException
|
||||
if (MemberName.isVarHandleMethodInvokeName(m.getName()))
|
||||
return MethodHandleImpl.fakeVarHandleInvoke(new MemberName(m));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a method handle for a reflected method.
|
||||
@ -1434,6 +1563,57 @@ return mh1;
|
||||
return unreflectField(f, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle that accesses fields of type {@code T} declared
|
||||
* by a class of type {@code R}, as described by the given reflected
|
||||
* field.
|
||||
* If the field is non-static the VarHandle supports a shape of
|
||||
* {@code (R : T)}, otherwise supports a shape of {@code ((empty) : T)}.
|
||||
* <p>
|
||||
* Access checking is performed immediately on behalf of the lookup
|
||||
* class, regardless of the value of the field's {@code accessible}
|
||||
* flag.
|
||||
* <p>
|
||||
* If the field is static, and if the returned VarHandle is operated
|
||||
* on, the field's declaring class will be initialized, if it has not
|
||||
* already been initialized.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the field is declared {@code final}, then the write, atomic
|
||||
* update, and numeric atomic update access modes are unsupported.
|
||||
* <li>if the field type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the field type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* If the field is declared {@code volatile} then the returned VarHandle
|
||||
* will override access to the field (effectively ignore the
|
||||
* {@code volatile} declaration) in accordance to it's specified
|
||||
* access modes.
|
||||
* @param f the reflected field, with a field of type {@code T}, and
|
||||
* a declaring class of type {@code R}
|
||||
* @return a VarHandle giving access to non-static fields or a static
|
||||
* field
|
||||
* @throws IllegalAccessException if access checking fails
|
||||
* @throws NullPointerException if the argument is null
|
||||
* @since 9
|
||||
*/
|
||||
public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException {
|
||||
MemberName getField = new MemberName(f, false);
|
||||
MemberName putField = new MemberName(f, true);
|
||||
return getFieldVarHandleNoSecurityManager(getField.getReferenceKind(), putField.getReferenceKind(),
|
||||
f.getDeclaringClass(), getField, putField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
|
||||
* created by this lookup object or a similar one.
|
||||
@ -1454,7 +1634,9 @@ return mh1;
|
||||
*/
|
||||
public MethodHandleInfo revealDirect(MethodHandle target) {
|
||||
MemberName member = target.internalMemberName();
|
||||
if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
|
||||
if (member == null || (!member.isResolved() &&
|
||||
!member.isMethodHandleInvoke() &&
|
||||
!member.isVarHandleMethodInvoke()))
|
||||
throw newIllegalArgumentException("not a direct method handle");
|
||||
Class<?> defc = member.getDeclaringClass();
|
||||
byte refKind = member.getReferenceKind();
|
||||
@ -1829,6 +2011,52 @@ return mh1;
|
||||
return restrictReceiver(field, dmh, lookupClass());
|
||||
return dmh;
|
||||
}
|
||||
private VarHandle getFieldVarHandle(byte getRefKind, byte putRefKind,
|
||||
Class<?> refc, MemberName getField, MemberName putField)
|
||||
throws IllegalAccessException {
|
||||
final boolean checkSecurity = true;
|
||||
return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
|
||||
}
|
||||
private VarHandle getFieldVarHandleNoSecurityManager(byte getRefKind, byte putRefKind,
|
||||
Class<?> refc, MemberName getField, MemberName putField)
|
||||
throws IllegalAccessException {
|
||||
final boolean checkSecurity = false;
|
||||
return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
|
||||
}
|
||||
private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind,
|
||||
Class<?> refc, MemberName getField, MemberName putField,
|
||||
boolean checkSecurity) throws IllegalAccessException {
|
||||
assert getField.isStatic() == putField.isStatic();
|
||||
assert getField.isGetter() && putField.isSetter();
|
||||
assert MethodHandleNatives.refKindIsStatic(getRefKind) == MethodHandleNatives.refKindIsStatic(putRefKind);
|
||||
assert MethodHandleNatives.refKindIsGetter(getRefKind) && MethodHandleNatives.refKindIsSetter(putRefKind);
|
||||
|
||||
checkField(getRefKind, refc, getField);
|
||||
if (checkSecurity)
|
||||
checkSecurityManager(refc, getField);
|
||||
|
||||
if (!putField.isFinal()) {
|
||||
// A VarHandle does not support updates to final fields, any
|
||||
// such VarHandle to a final field will be read-only and
|
||||
// therefore the following write-based accessibility checks are
|
||||
// only required for non-final fields
|
||||
checkField(putRefKind, refc, putField);
|
||||
if (checkSecurity)
|
||||
checkSecurityManager(refc, putField);
|
||||
}
|
||||
|
||||
boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
|
||||
restrictProtectedReceiver(getField));
|
||||
if (doRestrict) {
|
||||
assert !getField.isStatic();
|
||||
// receiver type of VarHandle is too wide; narrow to caller
|
||||
if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
|
||||
throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
|
||||
}
|
||||
refc = lookupClass();
|
||||
}
|
||||
return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), this.allowedModes == TRUSTED);
|
||||
}
|
||||
/** Check access and get the requested constructor. */
|
||||
private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
|
||||
final boolean checkSecurity = true;
|
||||
@ -2018,6 +2246,205 @@ return mh1;
|
||||
return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Produces a VarHandle giving access to elements of an array type
|
||||
* {@code T[]}, supporting shape {@code (T[], int : T)}.
|
||||
* <p>
|
||||
* Certain access modes of the returned VarHandle are unsupported under
|
||||
* the following conditions:
|
||||
* <ul>
|
||||
* <li>if the component type is anything other than {@code int},
|
||||
* {@code long} or a reference type, then atomic update access modes
|
||||
* are unsupported. (Future major platform releases of the JDK may
|
||||
* support additional types for certain currently unsupported access
|
||||
* modes.)
|
||||
* <li>if the component type is anything other than {@code int} or
|
||||
* {@code long}, then numeric atomic update access modes are
|
||||
* unsupported. (Future major platform releases of the JDK may
|
||||
* support additional numeric types for certain currently
|
||||
* unsupported access modes.)
|
||||
* </ul>
|
||||
* @param arrayClass the class of an array, of type {@code T[]}
|
||||
* @return a VarHandle giving access to elements of an array
|
||||
* @throws NullPointerException if the arrayClass is null
|
||||
* @throws IllegalArgumentException if arrayClass is not an array type
|
||||
* @since 9
|
||||
*/
|
||||
public static
|
||||
VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {
|
||||
return VarHandles.makeArrayElementHandle(arrayClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to elements of a {@code byte[]} array
|
||||
* viewed as if it were a different primitive array type, such as
|
||||
* {@code int[]} or {@code long[]}. The shape of the resulting VarHandle is
|
||||
* {@code (byte[], int : T)}, where the {@code int} coordinate type
|
||||
* corresponds to an argument that is an index in a {@code byte[]} array,
|
||||
* and {@code T} is the component type of the given view array class. The
|
||||
* returned VarHandle accesses bytes at an index in a {@code byte[]} array,
|
||||
* composing bytes to or from a value of {@code T} according to the given
|
||||
* endianness.
|
||||
* <p>
|
||||
* The supported component types (variables types) are {@code short},
|
||||
* {@code char}, {@code int}, {@code long}, {@code float} and
|
||||
* {@code double}.
|
||||
* <p>
|
||||
* Access of bytes at a given index will result in an
|
||||
* {@code IndexOutOfBoundsException} if the index is less than {@code 0}
|
||||
* or greater than the {@code byte[]} array length minus the size (in bytes)
|
||||
* of {@code T}.
|
||||
* <p>
|
||||
* Access of bytes at an index may be aligned or misaligned for {@code T},
|
||||
* with respect to the underlying memory address, {@code A} say, associated
|
||||
* with the array and index.
|
||||
* If access is misaligned then access for anything other than the
|
||||
* {@code get} and {@code set} access modes will result in an
|
||||
* {@code IllegalStateException}. In such cases atomic access is only
|
||||
* guaranteed with respect to the largest power of two that divides the GCD
|
||||
* of {@code A} and the size (in bytes) of {@code T}.
|
||||
* If access is aligned then following access modes are supported and are
|
||||
* guaranteed to support atomic access:
|
||||
* <ul>
|
||||
* <li>read write access modes for all {@code T};
|
||||
* <li>atomic update access modes for {@code int}, {@code long},
|
||||
* {@code float} or {@code double}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* types for certain currently unsupported access modes.)
|
||||
* <li>numeric atomic update access modes for {@code int} and {@code long}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* numeric types for certain currently unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* Misaligned access, and therefore atomicity guarantees, may be determined
|
||||
* for {@code byte[]} arrays without operating on a specific array. Given
|
||||
* an {@code index}, {@code T} and it's corresponding boxed type,
|
||||
* {@code T_BOX}, misalignment may be determined as follows:
|
||||
* <pre>{@code
|
||||
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
|
||||
* int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
|
||||
* alignmentOffset(0, sizeOfT);
|
||||
* int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
|
||||
* boolean isMisaligned = misalignedAtIndex != 0;
|
||||
* }</pre>
|
||||
*
|
||||
* @implNote
|
||||
* The variable types {@code float} and {@code double} are supported as if
|
||||
* by transformation to and access with the variable types {@code int} and
|
||||
* {@code long} respectively. For example, the transformation of a
|
||||
* {@code double} value to a long value is performed as if using
|
||||
* {@link Double#doubleToRawLongBits(double)}, and the reverse
|
||||
* transformation is performed as if using
|
||||
* {@link Double#longBitsToDouble(long)}.
|
||||
*
|
||||
* @param viewArrayClass the view array class, with a component type of
|
||||
* type {@code T}
|
||||
* @param bigEndian true if the endianness of the view array elements, as
|
||||
* stored in the underlying {@code byte} array, is big endian, otherwise
|
||||
* little endian
|
||||
* @return a VarHandle giving access to elements of a {@code byte[]} array
|
||||
* viewed as if elements corresponding to the components type of the view
|
||||
* array class
|
||||
* @throws NullPointerException if viewArrayClass is null
|
||||
* @throws IllegalArgumentException if viewArrayClass is not an array type
|
||||
* @throws UnsupportedOperationException if the component type of
|
||||
* viewArrayClass is not supported as a variable type
|
||||
* @since 9
|
||||
*/
|
||||
public static
|
||||
VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
|
||||
boolean bigEndian) throws IllegalArgumentException {
|
||||
return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a VarHandle giving access to elements of a {@code ByteBuffer}
|
||||
* viewed as if it were an array of elements of a different primitive
|
||||
* component type to that of {@code byte}, such as {@code int[]} or
|
||||
* {@code long[]}. The shape of the resulting VarHandle is
|
||||
* {@code (ByteBuffer, int : T)}, where the {@code int} coordinate type
|
||||
* corresponds to an argument that is an index in a {@code ByteBuffer}, and
|
||||
* {@code T} is the component type of the given view array class. The
|
||||
* returned VarHandle accesses bytes at an index in a {@code ByteBuffer},
|
||||
* composing bytes to or from a value of {@code T} according to the given
|
||||
* endianness.
|
||||
* <p>
|
||||
* The supported component types (variables types) are {@code short},
|
||||
* {@code char}, {@code int}, {@code long}, {@code float} and
|
||||
* {@code double}.
|
||||
* <p>
|
||||
* Access will result in a {@code ReadOnlyBufferException} for anything
|
||||
* other than the read access modes if the {@code ByteBuffer} is read-only.
|
||||
* <p>
|
||||
* Access of bytes at a given index will result in an
|
||||
* {@code IndexOutOfBoundsException} if the index is less than {@code 0}
|
||||
* or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
|
||||
* {@code T}.
|
||||
* <p>
|
||||
* Access of bytes at an index may be aligned or misaligned for {@code T},
|
||||
* with respect to the underlying memory address, {@code A} say, associated
|
||||
* with the {@code ByteBuffer} and index.
|
||||
* If access is misaligned then access for anything other than the
|
||||
* {@code get} and {@code set} access modes will result in an
|
||||
* {@code IllegalStateException}. In such cases atomic access is only
|
||||
* guaranteed with respect to the largest power of two that divides the GCD
|
||||
* of {@code A} and the size (in bytes) of {@code T}.
|
||||
* If access is aligned then following access modes are supported and are
|
||||
* guaranteed to support atomic access:
|
||||
* <ul>
|
||||
* <li>read write access modes for all {@code T};
|
||||
* <li>atomic update access modes for {@code int}, {@code long},
|
||||
* {@code float} or {@code double}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* types for certain currently unsupported access modes.)
|
||||
* <li>numeric atomic update access modes for {@code int} and {@code long}.
|
||||
* (Future major platform releases of the JDK may support additional
|
||||
* numeric types for certain currently unsupported access modes.)
|
||||
* </ul>
|
||||
* <p>
|
||||
* Misaligned access, and therefore atomicity guarantees, may be determined
|
||||
* for a {@code ByteBuffer}, {@code bb} (direct or otherwise), an
|
||||
* {@code index}, {@code T} and it's corresponding boxed type,
|
||||
* {@code T_BOX}, as follows:
|
||||
* <pre>{@code
|
||||
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
|
||||
* ByteBuffer bb = ...
|
||||
* int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT);
|
||||
* boolean isMisaligned = misalignedAtIndex != 0;
|
||||
* }</pre>
|
||||
*
|
||||
* @implNote
|
||||
* The variable types {@code float} and {@code double} are supported as if
|
||||
* by transformation to and access with the variable types {@code int} and
|
||||
* {@code long} respectively. For example, the transformation of a
|
||||
* {@code double} value to a long value is performed as if using
|
||||
* {@link Double#doubleToRawLongBits(double)}, and the reverse
|
||||
* transformation is performed as if using
|
||||
* {@link Double#longBitsToDouble(long)}.
|
||||
*
|
||||
* @param viewArrayClass the view array class, with a component type of
|
||||
* type {@code T}
|
||||
* @param bigEndian true if the endianness of the view array elements, as
|
||||
* stored in the underlying {@code ByteBuffer}, is big endian, otherwise
|
||||
* little endian (Note this overrides the endianness of a
|
||||
* {@code ByteBuffer})
|
||||
* @return a VarHandle giving access to elements of a {@code ByteBuffer}
|
||||
* viewed as if elements corresponding to the components type of the view
|
||||
* array class
|
||||
* @throws NullPointerException if viewArrayClass is null
|
||||
* @throws IllegalArgumentException if viewArrayClass is not an array type
|
||||
* @throws UnsupportedOperationException if the component type of
|
||||
* viewArrayClass is not supported as a variable type
|
||||
* @since 9
|
||||
*/
|
||||
public static
|
||||
VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
|
||||
boolean bigEndian) throws IllegalArgumentException {
|
||||
return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian);
|
||||
}
|
||||
|
||||
|
||||
/// method handle invocation (reflective style)
|
||||
|
||||
/**
|
||||
@ -2153,6 +2580,54 @@ return invoker;
|
||||
return type.invokers().genericInvoker();
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a special <em>invoker method handle</em> which can be used to
|
||||
* invoke a signature-polymorphic access mode method on any VarHandle whose
|
||||
* associated access mode type is compatible with the given type.
|
||||
* The resulting invoker will have a type which is exactly equal to the
|
||||
* desired given type, except that it will accept an additional leading
|
||||
* argument of type {@code VarHandle}.
|
||||
*
|
||||
* @param accessMode the VarHandle access mode
|
||||
* @param type the desired target type
|
||||
* @return a method handle suitable for invoking an access mode method of
|
||||
* any VarHandle whose access mode type is of the given type.
|
||||
* @since 9
|
||||
*/
|
||||
static public
|
||||
MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) {
|
||||
return type.invokers().varHandleMethodExactInvoker(accessMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a special <em>invoker method handle</em> which can be used to
|
||||
* invoke a signature-polymorphic access mode method on any VarHandle whose
|
||||
* associated access mode type is compatible with the given type.
|
||||
* The resulting invoker will have a type which is exactly equal to the
|
||||
* desired given type, except that it will accept an additional leading
|
||||
* argument of type {@code VarHandle}.
|
||||
* <p>
|
||||
* Before invoking its target, if the access mode type differs from the
|
||||
* desired given type, the invoker will apply reference casts as necessary
|
||||
* and box, unbox, or widen primitive values, as if by
|
||||
* {@link MethodHandle#asType asType}. Similarly, the return value will be
|
||||
* converted as necessary.
|
||||
* <p>
|
||||
* This method is equivalent to the following code (though it may be more
|
||||
* efficient): {@code publicLookup().findVirtual(VarHandle.class, accessMode.name(), type)}
|
||||
*
|
||||
* @param accessMode the VarHandle access mode
|
||||
* @param type the desired target type
|
||||
* @return a method handle suitable for invoking an access mode method of
|
||||
* any VarHandle whose access mode type is convertible to the given
|
||||
* type.
|
||||
* @since 9
|
||||
*/
|
||||
static public
|
||||
MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) {
|
||||
return type.invokers().varHandleMethodInvoker(accessMode);
|
||||
}
|
||||
|
||||
static /*non-public*/
|
||||
MethodHandle basicInvoker(MethodType type) {
|
||||
return type.invokers().basicInvoker();
|
||||
|
||||
@ -95,7 +95,7 @@ class MethodType implements java.io.Serializable {
|
||||
|
||||
// The rtype and ptypes fields define the structural identity of the method type:
|
||||
private final Class<?> rtype;
|
||||
private final Class<?>[] ptypes;
|
||||
private final @Stable Class<?>[] ptypes;
|
||||
|
||||
// The remaining fields are caches of various sorts:
|
||||
private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
|
||||
|
||||
164
jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java
Normal file
164
jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.lang.invoke.VarHandle.AccessMode;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||
|
||||
/**
|
||||
* A var handle form containing a set of member name, one for each operation.
|
||||
* Each member characterizes a static method.
|
||||
*/
|
||||
class VarForm {
|
||||
|
||||
// Holds VarForm for VarHandle implementation classes
|
||||
private static final ClassValue<VarForm> VFORMS
|
||||
= new ClassValue<VarForm>() {
|
||||
@Override
|
||||
protected VarForm computeValue(Class<?> impl) {
|
||||
return new VarForm(link(staticMethodLinker(impl)));
|
||||
}
|
||||
};
|
||||
|
||||
final MemberName mbGet;
|
||||
final MemberName mbSet;
|
||||
final MemberName mbGetVolatile;
|
||||
final MemberName mbSetVolatile;
|
||||
final MemberName mbGetAcquire;
|
||||
final MemberName mbSetRelease;
|
||||
final MemberName mbCompareAndSet;
|
||||
final MemberName mbCompareAndExchangeVolatile;
|
||||
final MemberName mbCompareAndExchangeAcquire;
|
||||
final MemberName mbCompareAndExchangeRelease;
|
||||
final MemberName mbWeakCompareAndSet;
|
||||
final MemberName mbWeakCompareAndSetAcquire;
|
||||
final MemberName mbWeakCompareAndSetRelease;
|
||||
final MemberName mbGetAndSet;
|
||||
final MemberName mbGetAndAdd;
|
||||
final MemberName mbAddAndGet;
|
||||
final MemberName mbGetOpaque;
|
||||
final MemberName mbSetOpaque;
|
||||
|
||||
VarForm(Map<AccessMode, MemberName> linkMap) {
|
||||
mbGet = linkMap.get(AccessMode.get);
|
||||
mbSet = linkMap.get(AccessMode.set);
|
||||
mbGetVolatile = linkMap.get(AccessMode.getVolatile);
|
||||
mbSetVolatile = linkMap.get(AccessMode.setVolatile);
|
||||
mbGetOpaque = linkMap.get(AccessMode.getOpaque);
|
||||
mbSetOpaque = linkMap.get(AccessMode.setOpaque);
|
||||
mbGetAcquire = linkMap.get(AccessMode.getAcquire);
|
||||
mbSetRelease = linkMap.get(AccessMode.setRelease);
|
||||
mbCompareAndSet = linkMap.get(AccessMode.compareAndSet);
|
||||
mbCompareAndExchangeVolatile = linkMap.get(AccessMode.compareAndExchangeVolatile);
|
||||
mbCompareAndExchangeAcquire = linkMap.get(AccessMode.compareAndExchangeAcquire);
|
||||
mbCompareAndExchangeRelease = linkMap.get(AccessMode.compareAndExchangeRelease);
|
||||
mbWeakCompareAndSet = linkMap.get(AccessMode.weakCompareAndSet);
|
||||
mbWeakCompareAndSetAcquire = linkMap.get(AccessMode.weakCompareAndSetAcquire);
|
||||
mbWeakCompareAndSetRelease = linkMap.get(AccessMode.weakCompareAndSetRelease);
|
||||
mbGetAndSet = linkMap.get(AccessMode.getAndSet);
|
||||
mbGetAndAdd = linkMap.get(AccessMode.getAndAdd);
|
||||
mbAddAndGet = linkMap.get(AccessMode.addAndGet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a var form given an VarHandle implementation class.
|
||||
* Each signature polymorphic method is linked to a static method of the
|
||||
* same name on the implementation class or a super class.
|
||||
*/
|
||||
static VarForm createFromStatic(Class<? extends VarHandle> impl) {
|
||||
return VFORMS.get(impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link all signature polymorphic methods.
|
||||
*/
|
||||
private static Map<AccessMode, MemberName> link(Function<AccessMode, MemberName> linker) {
|
||||
Map<AccessMode, MemberName> links = new HashMap<>();
|
||||
for (AccessMode ak : AccessMode.values()) {
|
||||
links.put(ak, linker.apply(ak));
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a function that associates an AccessMode with a MemberName that
|
||||
* is a static concrete method implementation for the access operation of
|
||||
* the implementing class.
|
||||
*/
|
||||
private static Function<AccessMode, MemberName> staticMethodLinker(Class<?> implClass) {
|
||||
// Find all declared static methods on the implementation class and
|
||||
// all super classes up to but not including VarHandle
|
||||
List<Method> staticMethods = new ArrayList<>(AccessMode.values().length);
|
||||
for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
|
||||
for (Method m : c.getDeclaredMethods()) {
|
||||
if (Modifier.isStatic(m.getModifiers())) {
|
||||
staticMethods.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This needs to be an anonymous inner class and not a lambda expression
|
||||
// The latter will cause the intialization of classes in java.lang.invoke
|
||||
// resulting in circular dependencies if VarHandles are utilized early
|
||||
// in the start up process. For example, if ConcurrentHashMap
|
||||
// is modified to use VarHandles.
|
||||
return new Function<>() {
|
||||
@Override
|
||||
public MemberName apply(AccessMode ak) {
|
||||
Method m = null;
|
||||
for (Method to_m : staticMethods) {
|
||||
if (to_m.getName().equals(ak.name()) &&
|
||||
Modifier.isStatic(to_m.getModifiers())) {
|
||||
assert m == null : String.format(
|
||||
"Two or more static methods named %s are present on " +
|
||||
"class %s or a super class", ak.name(), implClass.getName());
|
||||
m = to_m;
|
||||
}
|
||||
}
|
||||
|
||||
if (m == null)
|
||||
return null;
|
||||
|
||||
MemberName linkedMethod = new MemberName(m);
|
||||
try {
|
||||
return MemberName.getFactory().resolveOrFail(
|
||||
REF_invokeStatic, linkedMethod, m.getDeclaringClass(), NoSuchMethodException.class);
|
||||
}
|
||||
catch (ReflectiveOperationException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
1416
jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
Normal file
1416
jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
/**
|
||||
* The base class for generated byte array and byte buffer view
|
||||
* implementations
|
||||
*/
|
||||
abstract class VarHandleByteArrayBase {
|
||||
// Buffer.address
|
||||
static final long BUFFER_ADDRESS;
|
||||
// Buffer.limit
|
||||
static final long BUFFER_LIMIT;
|
||||
// ByteBuffer.hb
|
||||
static final long BYTE_BUFFER_HB;
|
||||
// ByteBuffer.isReadOnly
|
||||
static final long BYTE_BUFFER_IS_READ_ONLY;
|
||||
|
||||
static {
|
||||
try {
|
||||
BUFFER_ADDRESS = UNSAFE.objectFieldOffset(
|
||||
Buffer.class.getDeclaredField("address"));
|
||||
|
||||
BUFFER_LIMIT = UNSAFE.objectFieldOffset(
|
||||
Buffer.class.getDeclaredField("limit"));
|
||||
|
||||
BYTE_BUFFER_HB = UNSAFE.objectFieldOffset(
|
||||
ByteBuffer.class.getDeclaredField("hb"));
|
||||
|
||||
BYTE_BUFFER_IS_READ_ONLY = UNSAFE.objectFieldOffset(
|
||||
ByteBuffer.class.getDeclaredField("isReadOnly"));
|
||||
}
|
||||
catch (ReflectiveOperationException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static final boolean BE = UNSAFE.isBigEndian();
|
||||
|
||||
static IllegalStateException newIllegalStateExceptionForMisalignedAccess(int index) {
|
||||
return new IllegalStateException("Misaligned access at index: " + index);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
533
jdk/src/java.base/share/classes/java/lang/invoke/VarHandles.java
Normal file
533
jdk/src/java.base/share/classes/java/lang/invoke/VarHandles.java
Normal file
@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.invoke;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
final class VarHandles {
|
||||
|
||||
static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
|
||||
if (!f.isStatic()) {
|
||||
long foffset = MethodHandleNatives.objectFieldOffset(f);
|
||||
if (!type.isPrimitive()) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleObjects.FieldInstanceReadOnly(refc, foffset, type)
|
||||
: new VarHandleObjects.FieldInstanceReadWrite(refc, foffset, type);
|
||||
}
|
||||
else if (type == boolean.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == byte.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == short.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == char.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == int.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == long.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == float.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else if (type == double.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
|
||||
: new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO This is not lazy on first invocation
|
||||
// and might cause some circular initialization issues
|
||||
|
||||
// Replace with something similar to direct method handles
|
||||
// where a barrier is used then elided after use
|
||||
|
||||
if (UNSAFE.shouldBeInitialized(refc))
|
||||
UNSAFE.ensureClassInitialized(refc);
|
||||
|
||||
Object base = MethodHandleNatives.staticFieldBase(f);
|
||||
long foffset = MethodHandleNatives.staticFieldOffset(f);
|
||||
if (!type.isPrimitive()) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleObjects.FieldStaticReadOnly(base, foffset, type)
|
||||
: new VarHandleObjects.FieldStaticReadWrite(base, foffset, type);
|
||||
}
|
||||
else if (type == boolean.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == byte.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleBytes.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == short.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleShorts.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == char.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleChars.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleChars.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == int.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleInts.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleInts.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == long.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleLongs.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == float.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleFloats.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else if (type == double.class) {
|
||||
return f.isFinal() && !isWriteAllowedOnFinalFields
|
||||
? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
|
||||
: new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
|
||||
if (!arrayClass.isArray())
|
||||
throw new IllegalArgumentException("not an array: " + arrayClass);
|
||||
|
||||
Class<?> componentType = arrayClass.getComponentType();
|
||||
|
||||
int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
|
||||
int ascale = UNSAFE.arrayIndexScale(arrayClass);
|
||||
int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
|
||||
|
||||
if (!componentType.isPrimitive()) {
|
||||
return new VarHandleObjects.Array(aoffset, ashift, arrayClass);
|
||||
}
|
||||
else if (componentType == boolean.class) {
|
||||
return new VarHandleBooleans.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == byte.class) {
|
||||
return new VarHandleBytes.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == short.class) {
|
||||
return new VarHandleShorts.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == char.class) {
|
||||
return new VarHandleChars.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == int.class) {
|
||||
return new VarHandleInts.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == long.class) {
|
||||
return new VarHandleLongs.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == float.class) {
|
||||
return new VarHandleFloats.Array(aoffset, ashift);
|
||||
}
|
||||
else if (componentType == double.class) {
|
||||
return new VarHandleDoubles.Array(aoffset, ashift);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
|
||||
boolean be) {
|
||||
if (!viewArrayClass.isArray())
|
||||
throw new IllegalArgumentException("not an array: " + viewArrayClass);
|
||||
|
||||
Class<?> viewComponentType = viewArrayClass.getComponentType();
|
||||
|
||||
if (viewComponentType == long.class) {
|
||||
return new VarHandleByteArrayAsLongs.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == int.class) {
|
||||
return new VarHandleByteArrayAsInts.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == short.class) {
|
||||
return new VarHandleByteArrayAsShorts.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == char.class) {
|
||||
return new VarHandleByteArrayAsChars.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == double.class) {
|
||||
return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
|
||||
}
|
||||
else if (viewComponentType == float.class) {
|
||||
return new VarHandleByteArrayAsFloats.ArrayHandle(be);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
|
||||
boolean be) {
|
||||
if (!viewArrayClass.isArray())
|
||||
throw new IllegalArgumentException("not an array: " + viewArrayClass);
|
||||
|
||||
Class<?> viewComponentType = viewArrayClass.getComponentType();
|
||||
|
||||
if (viewComponentType == long.class) {
|
||||
return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == int.class) {
|
||||
return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == short.class) {
|
||||
return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == char.class) {
|
||||
return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == double.class) {
|
||||
return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
|
||||
}
|
||||
else if (viewComponentType == float.class) {
|
||||
return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * A helper program to generate the VarHandleGuards class with a set of
|
||||
// * static guard methods each of which corresponds to a particular shape and
|
||||
// * performs a type check of the symbolic type descriptor with the VarHandle
|
||||
// * type descriptor before linking/invoking to the underlying operation as
|
||||
// * characterized by the operation member name on the VarForm of the
|
||||
// * VarHandle.
|
||||
// * <p>
|
||||
// * The generated class essentially encapsulates pre-compiled LambdaForms,
|
||||
// * one for each method, for the most set of common method signatures.
|
||||
// * This reduces static initialization costs, footprint costs, and circular
|
||||
// * dependencies that may arise if a class is generated per LambdaForm.
|
||||
// * <p>
|
||||
// * A maximum of L*T*S methods will be generated where L is the number of
|
||||
// * access modes kinds (or unique operation signatures) and T is the number
|
||||
// * of variable types and S is the number of shapes (such as instance field,
|
||||
// * static field, or array access).
|
||||
// * If there are 4 unique operation signatures, 5 basic types (Object, int,
|
||||
// * long, float, double), and 3 shapes then a maximum of 60 methods will be
|
||||
// * generated. However, the number is likely to be less since there
|
||||
// * be duplicate signatures.
|
||||
// * <p>
|
||||
// * Each method is annotated with @LambdaForm.Compiled to inform the runtime
|
||||
// * that such methods should be treated as if a method of a class that is the
|
||||
// * result of compiling a LambdaForm. Annotation of such methods is
|
||||
// * important for correct evaluation of certain assertions and method return
|
||||
// * type profiling in HotSpot.
|
||||
// */
|
||||
// public static class GuardMethodGenerator {
|
||||
//
|
||||
// static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
|
||||
//
|
||||
// static final String GUARD_METHOD_TEMPLATE =
|
||||
// "@ForceInline\n" +
|
||||
// "@LambdaForm.Compiled\n" +
|
||||
// "final static <METHOD> throws Throwable {\n" +
|
||||
// " MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
|
||||
// " MethodType symbolic = ad.symbolicMethodType;\n" +
|
||||
// " if (target == symbolic) {\n" +
|
||||
// " <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// " else if (target.erase() == symbolic.erase()) {\n" +
|
||||
// " <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
|
||||
// " }\n" +
|
||||
// " else {\n" +
|
||||
// " MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
|
||||
// " <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
|
||||
// " }\n" +
|
||||
// "}";
|
||||
//
|
||||
// static final String GET_MEMBER_NAME_METHOD =
|
||||
// "@ForceInline\n" +
|
||||
// "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
|
||||
// " MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
|
||||
// " if (mn == null) {\n" +
|
||||
// " throw handle.unsupported();\n" +
|
||||
// " }\n" +
|
||||
// " return mn;\n" +
|
||||
// "}";
|
||||
//
|
||||
// // A template for deriving the operations
|
||||
// // could be supported by annotating VarHandle directly with the
|
||||
// // operation kind and shape
|
||||
// interface VarHandleTemplate {
|
||||
// Object get();
|
||||
//
|
||||
// void set(Object value);
|
||||
//
|
||||
// boolean compareAndSwap(Object actualValue, Object expectedValue);
|
||||
//
|
||||
// Object compareAndExchange(Object actualValue, Object expectedValue);
|
||||
//
|
||||
// Object getAndUpdate(Object value);
|
||||
// }
|
||||
//
|
||||
// static class HandleType {
|
||||
// final Class<?> receiver;
|
||||
// final Class<?>[] intermediates;
|
||||
// final Class<?> value;
|
||||
//
|
||||
// HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
||||
// this.receiver = receiver;
|
||||
// this.intermediates = intermediates;
|
||||
// this.value = value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * @param args parameters
|
||||
// */
|
||||
// public static void main(String[] args) {
|
||||
// System.out.println("package java.lang.invoke;");
|
||||
// System.out.println();
|
||||
// System.out.println("import jdk.internal.vm.annotation.ForceInline;");
|
||||
// System.out.println();
|
||||
// System.out.println("// This class is auto-generated by " +
|
||||
// GuardMethodGenerator.class.getName() +
|
||||
// ". Do not edit.");
|
||||
// System.out.println("final class VarHandleGuards {");
|
||||
//
|
||||
// System.out.println();
|
||||
// System.out.println(GET_MEMBER_NAME_METHOD);
|
||||
// System.out.println();
|
||||
//
|
||||
// // Declare the stream of shapes
|
||||
// Stream<HandleType> hts = Stream.of(
|
||||
// // Object->Object
|
||||
// new HandleType(Object.class, Object.class),
|
||||
// // Object->int
|
||||
// new HandleType(Object.class, int.class),
|
||||
// // Object->long
|
||||
// new HandleType(Object.class, long.class),
|
||||
// // Object->float
|
||||
// new HandleType(Object.class, float.class),
|
||||
// // Object->double
|
||||
// new HandleType(Object.class, double.class),
|
||||
//
|
||||
// // <static>->Object
|
||||
// new HandleType(null, Object.class),
|
||||
// // <static>->int
|
||||
// new HandleType(null, int.class),
|
||||
// // <static>->long
|
||||
// new HandleType(null, long.class),
|
||||
// // <static>->float
|
||||
// new HandleType(null, float.class),
|
||||
// // <static>->double
|
||||
// new HandleType(null, double.class),
|
||||
//
|
||||
// // Array[int]->Object
|
||||
// new HandleType(Object.class, Object.class, int.class),
|
||||
// // Array[int]->int
|
||||
// new HandleType(Object.class, int.class, int.class),
|
||||
// // Array[int]->long
|
||||
// new HandleType(Object.class, long.class, int.class),
|
||||
// // Array[int]->float
|
||||
// new HandleType(Object.class, float.class, int.class),
|
||||
// // Array[int]->double
|
||||
// new HandleType(Object.class, double.class, int.class),
|
||||
//
|
||||
// // Array[long]->int
|
||||
// new HandleType(Object.class, int.class, long.class),
|
||||
// // Array[long]->long
|
||||
// new HandleType(Object.class, long.class, long.class)
|
||||
// );
|
||||
//
|
||||
// hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
|
||||
// map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
|
||||
// distinct().
|
||||
// map(mt -> generateMethod(mt)).
|
||||
// forEach(s -> {
|
||||
// System.out.println(s);
|
||||
// System.out.println();
|
||||
// });
|
||||
//
|
||||
// System.out.println("}");
|
||||
// }
|
||||
//
|
||||
// static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
||||
// Class<?> returnType = m.getReturnType() == Object.class
|
||||
// ? value : m.getReturnType();
|
||||
//
|
||||
// List<Class<?>> params = new ArrayList<>();
|
||||
// if (receiver != null)
|
||||
// params.add(receiver);
|
||||
// for (int i = 0; i < intermediates.length; i++) {
|
||||
// params.add(intermediates[i]);
|
||||
// }
|
||||
// for (Parameter p : m.getParameters()) {
|
||||
// params.add(value);
|
||||
// }
|
||||
// return MethodType.methodType(returnType, params);
|
||||
// }
|
||||
//
|
||||
// static String generateMethod(MethodType mt) {
|
||||
// Class<?> returnType = mt.returnType();
|
||||
//
|
||||
// LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
|
||||
// params.put("handle", VarHandle.class);
|
||||
// for (int i = 0; i < mt.parameterCount(); i++) {
|
||||
// params.put("arg" + i, mt.parameterType(i));
|
||||
// }
|
||||
// params.put("ad", VarHandle.AccessDescriptor.class);
|
||||
//
|
||||
// // Generate method signature line
|
||||
// String RETURN = className(returnType);
|
||||
// String NAME = "guard";
|
||||
// String SIGNATURE = getSignature(mt);
|
||||
// String PARAMS = params.entrySet().stream().
|
||||
// map(e -> className(e.getValue()) + " " + e.getKey()).
|
||||
// collect(joining(", "));
|
||||
// String METHOD = GUARD_METHOD_SIG_TEMPLATE.
|
||||
// replace("<RETURN>", RETURN).
|
||||
// replace("<NAME>", NAME).
|
||||
// replace("<SIGNATURE>", SIGNATURE).
|
||||
// replace("<PARAMS>", PARAMS);
|
||||
//
|
||||
// // Generate method
|
||||
// params.remove("ad");
|
||||
//
|
||||
// List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
// LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
|
||||
//
|
||||
// List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
|
||||
// collect(toList());
|
||||
//
|
||||
// RETURN = returnType == void.class
|
||||
// ? ""
|
||||
// : returnType == Object.class
|
||||
// ? "return "
|
||||
// : "return (" + returnType.getName() + ") ";
|
||||
//
|
||||
// String RESULT_ERASED = returnType == void.class
|
||||
// ? ""
|
||||
// : returnType != Object.class
|
||||
// ? "return (" + returnType.getName() + ") "
|
||||
// : "Object r = ";
|
||||
//
|
||||
// String RETURN_ERASED = returnType != Object.class
|
||||
// ? ""
|
||||
// : " return symbolic.returnType().cast(r);";
|
||||
//
|
||||
// return GUARD_METHOD_TEMPLATE.
|
||||
// replace("<METHOD>", METHOD).
|
||||
// replace("<NAME>", NAME).
|
||||
// replaceAll("<RETURN>", RETURN).
|
||||
// replace("<RESULT_ERASED>", RESULT_ERASED).
|
||||
// replace("<RETURN_ERASED>", RETURN_ERASED).
|
||||
// replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
|
||||
// collect(joining(", "))).
|
||||
// replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
|
||||
// collect(joining(", ")))
|
||||
// ;
|
||||
// }
|
||||
//
|
||||
// static String className(Class<?> c) {
|
||||
// String n = c.getName();
|
||||
// if (n.startsWith("java.lang.")) {
|
||||
// n = n.replace("java.lang.", "");
|
||||
// if (n.startsWith("invoke.")) {
|
||||
// n = n.replace("invoke.", "");
|
||||
// }
|
||||
// }
|
||||
// return n.replace('$', '.');
|
||||
// }
|
||||
//
|
||||
// static String getSignature(MethodType m) {
|
||||
// StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
|
||||
//
|
||||
// for (int i = 0; i < m.parameterCount(); i++) {
|
||||
// Class<?> pt = m.parameterType(i);
|
||||
// sb.append(getCharType(pt));
|
||||
// }
|
||||
//
|
||||
// sb.append('_').append(getCharType(m.returnType()));
|
||||
//
|
||||
// return sb.toString();
|
||||
// }
|
||||
//
|
||||
// static char getCharType(Class<?> pt) {
|
||||
// if (pt == void.class) {
|
||||
// return 'V';
|
||||
// }
|
||||
// else if (!pt.isPrimitive()) {
|
||||
// return 'L';
|
||||
// }
|
||||
// else if (pt == boolean.class) {
|
||||
// return 'Z';
|
||||
// }
|
||||
// else if (pt == int.class) {
|
||||
// return 'I';
|
||||
// }
|
||||
// else if (pt == long.class) {
|
||||
// return 'J';
|
||||
// }
|
||||
// else if (pt == float.class) {
|
||||
// return 'F';
|
||||
// }
|
||||
// else if (pt == double.class) {
|
||||
// return 'D';
|
||||
// }
|
||||
// else {
|
||||
// throw new IllegalStateException(pt.getName());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@ -0,0 +1,602 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import java.util.Objects;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
#warn
|
||||
|
||||
final class VarHandle$Type$s {
|
||||
|
||||
static class FieldInstanceReadOnly extends VarHandle {
|
||||
final long fieldOffset;
|
||||
final Class<?> receiverType;
|
||||
#if[Object]
|
||||
final Class<?> fieldType;
|
||||
#end[Object]
|
||||
|
||||
FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
|
||||
}
|
||||
|
||||
protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldInstanceReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
|
||||
this.fieldOffset = fieldOffset;
|
||||
this.receiverType = receiverType;
|
||||
#if[Object]
|
||||
this.fieldType = fieldType;
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(FieldInstanceReadOnly handle, Object holder) {
|
||||
return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
|
||||
|
||||
FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
UNSAFE.put$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
return UNSAFE.getAndSet$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
|
||||
handle.fieldOffset,
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static class FieldStaticReadOnly extends VarHandle {
|
||||
final Object base;
|
||||
final long fieldOffset;
|
||||
#if[Object]
|
||||
final Class<?> fieldType;
|
||||
#end[Object]
|
||||
|
||||
FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
|
||||
}
|
||||
|
||||
protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
|
||||
Class<? extends FieldStaticReadOnly> handle) {
|
||||
super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
|
||||
this.base = base;
|
||||
this.fieldOffset = fieldOffset;
|
||||
#if[Object]
|
||||
this.fieldType = fieldType;
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$Volatile(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$Opaque(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(FieldStaticReadOnly handle) {
|
||||
return UNSAFE.get$Type$Acquire(handle.base,
|
||||
handle.fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
static class FieldStaticReadWrite extends FieldStaticReadOnly {
|
||||
|
||||
FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
|
||||
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$Volatile(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$Opaque(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(FieldStaticReadWrite handle, $type$ value) {
|
||||
UNSAFE.put$Type$Release(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndSwap$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Volatile(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.compareAndExchange$Type$Release(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
|
||||
return UNSAFE.weakCompareAndSwap$Type$Release(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(expected):expected},
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(FieldStaticReadWrite handle, $type$ value) {
|
||||
return UNSAFE.getAndSet$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
{#if[Object]?handle.fieldType.cast(value):value});
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(FieldStaticReadWrite handle, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(FieldStaticReadWrite handle, $type$ value) {
|
||||
return UNSAFE.getAndAdd$Type$(handle.base,
|
||||
handle.fieldOffset,
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static final class Array extends VarHandle {
|
||||
final int abase;
|
||||
final int ashift;
|
||||
#if[Object]
|
||||
final Class<{#if[Object]??:$type$[]}> arrayType;
|
||||
final Class<?> componentType;
|
||||
#end[Object]
|
||||
|
||||
Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
|
||||
super(VarForm.createFromStatic(Array.class),
|
||||
{#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
|
||||
this.abase = abase;
|
||||
this.ashift = ashift;
|
||||
#if[Object]
|
||||
this.arrayType = {#if[Object]?arrayType:$type$[].class};
|
||||
this.componentType = arrayType.getComponentType();
|
||||
#end[Object]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return array[index];
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
array[index] = {#if[Object]?handle.componentType.cast(value):value};
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.get$Type$Volatile(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
UNSAFE.put$Type$Volatile(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.get$Type$Opaque(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
UNSAFE.put$Type$Opaque(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(Array handle, Object oarray, int index) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.get$Type$Acquire(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
UNSAFE.put$Type$Release(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndSwap$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndExchange$Type$Volatile(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndExchange$Type$Acquire(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.compareAndExchange$Type$Release(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.weakCompareAndSwap$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.weakCompareAndSwap$Type$Release(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(expected):expected},
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.getAndSet$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
{#if[Object]?handle.componentType.cast(value):value});
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.getAndAdd$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
value);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(Array handle, Object oarray, int index, $type$ value) {
|
||||
#if[Object]
|
||||
Object[] array = (Object[]) handle.arrayType.cast(oarray);
|
||||
#else[Object]
|
||||
$type$[] array = ($type$[]) oarray;
|
||||
#end[Object]
|
||||
return UNSAFE.getAndAdd$Type$(array,
|
||||
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
|
||||
value) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.lang.invoke;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||
|
||||
#warn
|
||||
|
||||
final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
|
||||
|
||||
static final int ALIGN = $BoxType$.BYTES - 1;
|
||||
|
||||
#if[floatingPoint]
|
||||
@ForceInline
|
||||
static $rawType$ convEndian(boolean big, $type$ v) {
|
||||
$rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
|
||||
return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ convEndian(boolean big, $rawType$ rv) {
|
||||
rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
|
||||
return $Type$.$rawType$BitsTo$Type$(rv);
|
||||
}
|
||||
#else[floatingPoint]
|
||||
@ForceInline
|
||||
static $type$ convEndian(boolean big, $type$ n) {
|
||||
return big == BE ? n : $BoxType$.reverseBytes(n);
|
||||
}
|
||||
#end[floatingPoint]
|
||||
|
||||
|
||||
private static class ByteArrayViewVarHandle extends VarHandle {
|
||||
final boolean be;
|
||||
|
||||
ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
|
||||
Class<?> arrayType, Class<?> component, boolean be) {
|
||||
super(VarForm.createFromStatic(implSubType),
|
||||
arrayType, component, int.class);
|
||||
this.be = be;
|
||||
}
|
||||
}
|
||||
|
||||
static final class ArrayHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ArrayHandle(boolean be) {
|
||||
super(ArrayHandle.class, byte[].class, $type$.class, be);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static int index(byte[] ba, int index) {
|
||||
return Objects.checkIndex(index, ba.length - ALIGN, null);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static long address(byte[] ba, int index) {
|
||||
long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
|
||||
if ((address & ALIGN) != 0)
|
||||
throw newIllegalStateExceptionForMisalignedAccess(index);
|
||||
return address;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
#if[floatingPoint]
|
||||
$rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
handle.be);
|
||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||
#else[floatingPoint]
|
||||
return UNSAFE.get$Type$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
#if[floatingPoint]
|
||||
UNSAFE.put$RawType$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||
handle.be);
|
||||
#else[floatingPoint]
|
||||
UNSAFE.put$RawType$Unaligned(
|
||||
ba,
|
||||
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
|
||||
value,
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Volatile(
|
||||
ba,
|
||||
address(ba, index(ba, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
UNSAFE.put$RawType$Volatile(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Acquire(
|
||||
ba,
|
||||
address(ba, index(ba, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
UNSAFE.put$RawType$Release(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(ArrayHandle handle, Object oba, int index) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Opaque(
|
||||
ba,
|
||||
address(ba, index(ba, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
UNSAFE.put$RawType$Opaque(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.compareAndSwap$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Volatile(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Acquire(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Release(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Release(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndSet$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndAdd$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
|
||||
byte[] ba = (byte[]) oba;
|
||||
return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
|
||||
ba,
|
||||
address(ba, index(ba, index)),
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static final class ByteBufferHandle extends ByteArrayViewVarHandle {
|
||||
|
||||
ByteBufferHandle(boolean be) {
|
||||
super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static int index(ByteBuffer bb, int index) {
|
||||
return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static int indexRO(ByteBuffer bb, int index) {
|
||||
if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
|
||||
throw new ReadOnlyBufferException();
|
||||
return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static long address(ByteBuffer bb, int index) {
|
||||
long address = ((long) index) + UNSAFE.getLong(bb, BUFFER_ADDRESS);
|
||||
if ((address & ALIGN) != 0)
|
||||
throw newIllegalStateExceptionForMisalignedAccess(index);
|
||||
return address;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ get(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
#if[floatingPoint]
|
||||
$rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
handle.be);
|
||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||
#else[floatingPoint]
|
||||
return UNSAFE.get$Type$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void set(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
#if[floatingPoint]
|
||||
UNSAFE.put$RawType$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||
handle.be);
|
||||
#else[floatingPoint]
|
||||
UNSAFE.put$Type$Unaligned(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
|
||||
value,
|
||||
handle.be);
|
||||
#end[floatingPoint]
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getVolatile(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Volatile(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, index(bb, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setVolatile(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
UNSAFE.put$RawType$Volatile(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAcquire(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Acquire(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, index(bb, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setRelease(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
UNSAFE.put$RawType$Release(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getOpaque(ByteBufferHandle handle, Object obb, int index) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.get$RawType$Opaque(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, index(bb, index))));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static void setOpaque(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
UNSAFE.put$RawType$Opaque(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value));
|
||||
}
|
||||
#if[CAS]
|
||||
|
||||
@ForceInline
|
||||
static boolean compareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.compareAndSwap$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Volatile(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Acquire(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ compareAndExchangeRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.compareAndExchange$RawType$Release(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static boolean weakCompareAndSetRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return UNSAFE.weakCompareAndSwap$RawType$Release(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndSet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndSet$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
#end[CAS]
|
||||
#if[AtomicAdd]
|
||||
|
||||
@ForceInline
|
||||
static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndAdd$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value)));
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
|
||||
ByteBuffer bb = (ByteBuffer) obb;
|
||||
return convEndian(handle.be,
|
||||
UNSAFE.getAndAdd$RawType$(
|
||||
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
|
||||
address(bb, indexRO(bb, index)),
|
||||
convEndian(handle.be, value))) + value;
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,7 +32,8 @@
|
||||
* certain types in this package have special relations to dynamic
|
||||
* language support in the virtual machine:
|
||||
* <ul>
|
||||
* <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
|
||||
* <li>The classes {@link java.lang.invoke.MethodHandle MethodHandle}
|
||||
* {@link java.lang.invoke.VarHandle VarHandle} contain
|
||||
* <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
|
||||
* which can be linked regardless of their type descriptor.
|
||||
* Normally, method linkage requires exact matching of type descriptors.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,9 +25,10 @@
|
||||
|
||||
package java.nio;
|
||||
|
||||
import java.util.Spliterator;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
import java.util.Spliterator;
|
||||
|
||||
/**
|
||||
* A container for data of a specific primitive type.
|
||||
*
|
||||
@ -188,7 +189,15 @@ public abstract class Buffer {
|
||||
private int limit;
|
||||
private int capacity;
|
||||
|
||||
// Used only by direct buffers
|
||||
// Used by heap byte buffers or direct buffers with Unsafe access
|
||||
// For heap byte buffers this field will be the address relative to the
|
||||
// array base address and offset into that array. The address might
|
||||
// not align on a word boundary for slices, nor align at a long word
|
||||
// (8 byte) boundary for byte[] allocations on 32-bit systems.
|
||||
// For direct buffers it is the start address of the memory region. The
|
||||
// address might not align on a word boundary for slices, nor when created
|
||||
// using JNI, see NewDirectByteBuffer(void*, long).
|
||||
// Should ideally be declared final
|
||||
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
|
||||
long address;
|
||||
|
||||
|
||||
@ -140,6 +140,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
att = null;
|
||||
#else[rw]
|
||||
super(cap);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
@ -180,6 +181,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
att = null;
|
||||
#else[rw]
|
||||
super(cap, addr, fd, unmapper);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
@ -200,6 +202,7 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
att = db;
|
||||
#else[rw]
|
||||
super(db, mark, pos, lim, cap, off);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
}
|
||||
|
||||
@ -213,6 +216,15 @@ class Direct$Type$Buffer$RW$$BO$
|
||||
return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
|
||||
}
|
||||
|
||||
#if[byte]
|
||||
public $Type$Buffer slice(int pos, int lim) {
|
||||
assert (pos >= 0);
|
||||
assert (pos <= lim);
|
||||
int rem = lim - pos;
|
||||
return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
public $Type$Buffer duplicate() {
|
||||
return new Direct$Type$Buffer$RW$$BO$(this,
|
||||
this.markValue(),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -74,6 +74,9 @@ class Heap$Type$Buffer$RW$
|
||||
super(cap, lim);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
|
||||
@ -87,6 +90,9 @@ class Heap$Type$Buffer$RW$
|
||||
super(buf, off, len);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
protected Heap$Type$Buffer$RW$($type$[] buf,
|
||||
@ -103,6 +109,9 @@ class Heap$Type$Buffer$RW$
|
||||
super(buf, mark, pos, lim, cap, off);
|
||||
this.isReadOnly = true;
|
||||
#end[rw]
|
||||
#if[byte]
|
||||
this.address = arrayBaseOffset + off;
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
public $Type$Buffer slice() {
|
||||
@ -114,6 +123,20 @@ class Heap$Type$Buffer$RW$
|
||||
this.position() + offset);
|
||||
}
|
||||
|
||||
#if[byte]
|
||||
$Type$Buffer slice(int pos, int lim) {
|
||||
assert (pos >= 0);
|
||||
assert (pos <= lim);
|
||||
int rem = lim - pos;
|
||||
return new Heap$Type$Buffer$RW$(hb,
|
||||
-1,
|
||||
0,
|
||||
rem,
|
||||
rem,
|
||||
pos + offset);
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
public $Type$Buffer duplicate() {
|
||||
return new Heap$Type$Buffer$RW$(hb,
|
||||
this.markValue(),
|
||||
@ -144,7 +167,7 @@ class Heap$Type$Buffer$RW$
|
||||
|
||||
#if[byte]
|
||||
private long byteOffset(long i) {
|
||||
return arrayBaseOffset + i + offset;
|
||||
return address + i;
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,6 +39,7 @@ class StringCharBuffer // package-private
|
||||
if ((start < 0) || (start > n) || (end < start) || (end > n))
|
||||
throw new IndexOutOfBoundsException();
|
||||
str = s;
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
|
||||
public CharBuffer slice() {
|
||||
@ -58,6 +59,7 @@ class StringCharBuffer // package-private
|
||||
int offset) {
|
||||
super(mark, pos, limit, cap, null, offset);
|
||||
str = s;
|
||||
this.isReadOnly = true;
|
||||
}
|
||||
|
||||
public CharBuffer duplicate() {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -269,7 +269,7 @@ public abstract class $Type$Buffer
|
||||
//
|
||||
final $type$[] hb; // Non-null only for heap buffers
|
||||
final int offset;
|
||||
boolean isReadOnly; // Valid only for heap buffers
|
||||
boolean isReadOnly;
|
||||
|
||||
// Creates a new buffer with the given mark, position, limit, capacity,
|
||||
// backing array, and array offset
|
||||
@ -530,6 +530,10 @@ public abstract class $Type$Buffer
|
||||
* it will be read-only if, and only if, this buffer is read-only. </p>
|
||||
*
|
||||
* @return The new $type$ buffer
|
||||
#if[byte]
|
||||
*
|
||||
* @see #alignedSlice(int)
|
||||
#end[byte]
|
||||
*/
|
||||
public abstract $Type$Buffer slice();
|
||||
|
||||
@ -1611,6 +1615,143 @@ public abstract class $Type$Buffer
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the memory address, pointing to the byte at the given index,
|
||||
* modulus the given unit size.
|
||||
*
|
||||
* <p> A return value greater than zero indicates the address of the byte at
|
||||
* the index is misaligned for the unit size, and the value's quantity
|
||||
* indicates how much the index should be rounded up or down to locate a
|
||||
* byte at an aligned address. Otherwise, a value of {@code 0} indicates
|
||||
* that the address of the byte at the index is aligned for the unit size.
|
||||
*
|
||||
* @apiNote
|
||||
* This method may be utilized to determine if unit size bytes from an
|
||||
* index can be accessed atomically, if supported by the native platform.
|
||||
*
|
||||
* @implNote
|
||||
* This implementation throws {@code UnsupportedOperationException} for
|
||||
* non-direct buffers when the given unit size is greater then {@code 8}.
|
||||
*
|
||||
* @param index
|
||||
* The index to query for alignment offset, must be non-negative, no
|
||||
* upper bounds check is performed
|
||||
*
|
||||
* @param unitSize
|
||||
* The unit size in bytes, must be a power of {@code 2}
|
||||
*
|
||||
* @return The indexed byte's memory address modulus the unit size
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the index is negative or the unit size is not a power of
|
||||
* {@code 2}
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the native platform does not guarantee stable alignment offset
|
||||
* values for the given unit size when managing the memory regions
|
||||
* of buffers of the same kind as this buffer (direct or
|
||||
* non-direct). For example, if garbage collection would result
|
||||
* in the moving of a memory region covered by a non-direct buffer
|
||||
* from one location to another and both locations have different
|
||||
* alignment characteristics.
|
||||
*
|
||||
* @see #alignedSlice(int)
|
||||
* @since 9
|
||||
*/
|
||||
public final int alignmentOffset(int index, int unitSize) {
|
||||
if (index < 0)
|
||||
throw new IllegalArgumentException("Index less than zero: " + index);
|
||||
if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
|
||||
throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
|
||||
if (unitSize > 8 && !isDirect())
|
||||
throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
|
||||
|
||||
return (int) ((address + index) % unitSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new byte buffer whose content is a shared and aligned
|
||||
* subsequence of this buffer's content.
|
||||
*
|
||||
* <p> The content of the new buffer will start at this buffer's current
|
||||
* position rounded up to the index of the nearest aligned byte for the
|
||||
* given unit size, and end at this buffer's limit rounded down to the index
|
||||
* of the nearest aligned byte for the given unit size.
|
||||
* If rounding results in out-of-bound values then the new buffer's capacity
|
||||
* and limit will be zero. If rounding is within bounds the following
|
||||
* expressions will be true for a new buffer {@code nb} and unit size
|
||||
* {@code unitSize}:
|
||||
* <pre>{@code
|
||||
* nb.alignmentOffset(0, unitSize) == 0
|
||||
* nb.alignmentOffset(nb.limit(), unitSize) == 0
|
||||
* }</pre>
|
||||
*
|
||||
* <p> Changes to this buffer's content will be visible in the new
|
||||
* buffer, and vice versa; the two buffers' position, limit, and mark
|
||||
* values will be independent.
|
||||
*
|
||||
* <p> The new buffer's position will be zero, its capacity and its limit
|
||||
* will be the number of bytes remaining in this buffer or fewer subject to
|
||||
* alignment, its mark will be undefined, and its byte order will be
|
||||
* {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
|
||||
*
|
||||
* The new buffer will be direct if, and only if, this buffer is direct, and
|
||||
* it will be read-only if, and only if, this buffer is read-only. </p>
|
||||
*
|
||||
* @apiNote
|
||||
* This method may be utilized to create a new buffer where unit size bytes
|
||||
* from index, that is a multiple of the unit size, may be accessed
|
||||
* atomically, if supported by the native platform.
|
||||
*
|
||||
* @implNote
|
||||
* This implementation throws {@code UnsupportedOperationException} for
|
||||
* non-direct buffers when the given unit size is greater then {@code 8}.
|
||||
*
|
||||
* @param unitSize
|
||||
* The unit size in bytes, must be a power of {@code 2}
|
||||
*
|
||||
* @return The new byte buffer
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the unit size not a power of {@code 2}
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the native platform does not guarantee stable aligned slices
|
||||
* for the given unit size when managing the memory regions
|
||||
* of buffers of the same kind as this buffer (direct or
|
||||
* non-direct). For example, if garbage collection would result
|
||||
* in the moving of a memory region covered by a non-direct buffer
|
||||
* from one location to another and both locations have different
|
||||
* alignment characteristics.
|
||||
*
|
||||
* @see #alignmentOffset(int, int)
|
||||
* @see #slice()
|
||||
* @since 9
|
||||
*/
|
||||
public final ByteBuffer alignedSlice(int unitSize) {
|
||||
int pos = position();
|
||||
int lim = limit();
|
||||
|
||||
int pos_mod = alignmentOffset(pos, unitSize);
|
||||
int lim_mod = alignmentOffset(lim, unitSize);
|
||||
|
||||
// Round up the position to align with unit size
|
||||
int aligned_pos = (pos_mod > 0)
|
||||
? pos + (unitSize - pos_mod)
|
||||
: pos;
|
||||
|
||||
// Round down the limit to align with unit size
|
||||
int aligned_lim = lim - lim_mod;
|
||||
|
||||
if (aligned_pos > lim || aligned_lim < pos) {
|
||||
aligned_pos = aligned_lim = pos;
|
||||
}
|
||||
|
||||
return slice(aligned_pos, aligned_lim);
|
||||
}
|
||||
|
||||
abstract ByteBuffer slice(int pos, int lim);
|
||||
|
||||
// Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
|
||||
//
|
||||
abstract byte _get(int i); // package-private
|
||||
|
||||
@ -480,7 +480,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
|
||||
}
|
||||
|
||||
static void lazySetNext(Completion c, Completion next) {
|
||||
U.putOrderedObject(c, NEXT, next);
|
||||
U.putObjectRelease(c, NEXT, next);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -309,7 +309,7 @@ public class ConcurrentLinkedDeque<E>
|
||||
}
|
||||
|
||||
void lazySetNext(Node<E> val) {
|
||||
U.putOrderedObject(this, NEXT, val);
|
||||
U.putObjectRelease(this, NEXT, val);
|
||||
}
|
||||
|
||||
boolean casNext(Node<E> cmp, Node<E> val) {
|
||||
@ -317,7 +317,7 @@ public class ConcurrentLinkedDeque<E>
|
||||
}
|
||||
|
||||
void lazySetPrev(Node<E> val) {
|
||||
U.putOrderedObject(this, PREV, val);
|
||||
U.putObjectRelease(this, PREV, val);
|
||||
}
|
||||
|
||||
boolean casPrev(Node<E> cmp, Node<E> val) {
|
||||
|
||||
@ -198,7 +198,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
|
||||
static <E> void lazySetNext(Node<E> node, Node<E> val) {
|
||||
U.putOrderedObject(node, NEXT, val);
|
||||
U.putObjectRelease(node, NEXT, val);
|
||||
}
|
||||
|
||||
static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
|
||||
|
||||
@ -239,7 +239,7 @@ public class Exchanger<V> {
|
||||
* not to be as readily inlined by dynamic compilers when they are
|
||||
* hidden behind other methods that would more nicely name and
|
||||
* encapsulate the intended effects). This includes the use of
|
||||
* putOrderedX to clear fields of the per-thread Nodes between
|
||||
* putXRelease to clear fields of the per-thread Nodes between
|
||||
* uses. Note that field Node.item is not declared as volatile
|
||||
* even though it is read by releasing threads, because they only
|
||||
* do so after CAS operations that must precede access, and all
|
||||
@ -376,7 +376,7 @@ public class Exchanger<V> {
|
||||
for (int h = p.hash, spins = SPINS;;) {
|
||||
Object v = p.match;
|
||||
if (v != null) {
|
||||
U.putOrderedObject(p, MATCH, null);
|
||||
U.putObjectRelease(p, MATCH, null);
|
||||
p.item = null; // clear for next use
|
||||
p.hash = h;
|
||||
return v;
|
||||
@ -507,7 +507,7 @@ public class Exchanger<V> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
U.putOrderedObject(p, MATCH, null);
|
||||
U.putObjectRelease(p, MATCH, null);
|
||||
p.item = null;
|
||||
p.hash = h;
|
||||
return v;
|
||||
|
||||
@ -289,7 +289,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
* on to try or create other queues -- they block only when
|
||||
* creating and registering new queues. Because it is used only as
|
||||
* a spinlock, unlocking requires only a "releasing" store (using
|
||||
* putOrderedInt). The qlock is also used during termination
|
||||
* putIntRelease). The qlock is also used during termination
|
||||
* detection, in which case it is forced to a negative
|
||||
* non-lockable value.
|
||||
*
|
||||
@ -1071,7 +1071,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
popped = true;
|
||||
top = s;
|
||||
}
|
||||
U.putOrderedInt(this, QLOCK, 0);
|
||||
U.putIntRelease(this, QLOCK, 0);
|
||||
}
|
||||
}
|
||||
return popped;
|
||||
@ -1261,7 +1261,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
popped = true;
|
||||
top = s - 1;
|
||||
}
|
||||
U.putOrderedInt(this, QLOCK, 0);
|
||||
U.putIntRelease(this, QLOCK, 0);
|
||||
if (popped)
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ public class ForkJoinWorkerThread extends Thread {
|
||||
ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
|
||||
AccessControlContext acc) {
|
||||
super(threadGroup, null, "aForkJoinWorkerThread");
|
||||
U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
|
||||
U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc);
|
||||
eraseThreadLocals(); // clear before registering
|
||||
this.pool = pool;
|
||||
this.workQueue = pool.registerWorker(this);
|
||||
|
||||
@ -174,7 +174,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
|
||||
if (t != null)
|
||||
t.interrupt();
|
||||
} finally { // final state
|
||||
U.putOrderedInt(this, STATE, INTERRUPTED);
|
||||
U.putIntRelease(this, STATE, INTERRUPTED);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@ -230,7 +230,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
|
||||
protected void set(V v) {
|
||||
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
|
||||
outcome = v;
|
||||
U.putOrderedInt(this, STATE, NORMAL); // final state
|
||||
U.putIntRelease(this, STATE, NORMAL); // final state
|
||||
finishCompletion();
|
||||
}
|
||||
}
|
||||
@ -248,7 +248,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
|
||||
protected void setException(Throwable t) {
|
||||
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
|
||||
outcome = t;
|
||||
U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
|
||||
U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
|
||||
finishCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1496,7 +1496,7 @@ public class SubmissionPublisher<T> implements Flow.Publisher<T>,
|
||||
else if (((c & CONSUME) != 0 ||
|
||||
U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
|
||||
U.compareAndSwapObject(a, i, x, null)) {
|
||||
U.putOrderedInt(this, HEAD, ++h);
|
||||
U.putIntRelease(this, HEAD, ++h);
|
||||
U.getAndAddLong(this, DEMAND, -1L);
|
||||
if ((w = waiter) != null)
|
||||
signalWaiter(w);
|
||||
|
||||
@ -136,7 +136,7 @@ public class AtomicBoolean implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(boolean newValue) {
|
||||
U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
|
||||
U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -108,7 +108,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int newValue) {
|
||||
U.putOrderedInt(this, VALUE, newValue);
|
||||
U.putIntRelease(this, VALUE, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -136,7 +136,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, int newValue) {
|
||||
U.putOrderedInt(array, checkedByteOffset(i), newValue);
|
||||
U.putIntRelease(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -475,7 +475,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
|
||||
|
||||
public final void lazySet(T obj, int newValue) {
|
||||
accessCheck(obj);
|
||||
U.putOrderedInt(obj, offset, newValue);
|
||||
U.putIntRelease(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final int get(T obj) {
|
||||
|
||||
@ -124,7 +124,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(long newValue) {
|
||||
U.putOrderedLong(this, VALUE, newValue);
|
||||
U.putLongRelease(this, VALUE, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -135,7 +135,7 @@ public class AtomicLongArray implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, long newValue) {
|
||||
U.putOrderedLong(array, checkedByteOffset(i), newValue);
|
||||
U.putLongRelease(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -457,7 +457,7 @@ public abstract class AtomicLongFieldUpdater<T> {
|
||||
|
||||
public final void lazySet(T obj, long newValue) {
|
||||
accessCheck(obj);
|
||||
U.putOrderedLong(obj, offset, newValue);
|
||||
U.putLongRelease(obj, offset, newValue);
|
||||
}
|
||||
|
||||
public final long get(T obj) {
|
||||
|
||||
@ -103,7 +103,7 @@ public class AtomicReference<V> implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(V newValue) {
|
||||
U.putOrderedObject(this, VALUE, newValue);
|
||||
U.putObjectRelease(this, VALUE, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -147,7 +147,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
|
||||
* @since 1.6
|
||||
*/
|
||||
public final void lazySet(int i, E newValue) {
|
||||
U.putOrderedObject(array, checkedByteOffset(i), newValue);
|
||||
U.putObjectRelease(array, checkedByteOffset(i), newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -426,7 +426,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
|
||||
public final void lazySet(T obj, V newValue) {
|
||||
accessCheck(obj);
|
||||
valueCheck(newValue);
|
||||
U.putOrderedObject(obj, offset, newValue);
|
||||
U.putObjectRelease(obj, offset, newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@ -86,8 +86,8 @@ public final class InnocuousThread extends Thread {
|
||||
|
||||
private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
|
||||
super(group, target, name, 0L, false);
|
||||
UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
|
||||
UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, tccl);
|
||||
UNSAFE.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
|
||||
UNSAFE.putObjectRelease(this, CONTEXTCLASSLOADER, tccl);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1457,25 +1457,7 @@ public final class Unsafe {
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putDoubleVolatile(Object o, long offset, double x);
|
||||
|
||||
/**
|
||||
* Version of {@link #putObjectVolatile(Object, long, Object)}
|
||||
* that does not guarantee immediate visibility of the store to
|
||||
* other threads. This method is generally only useful if the
|
||||
* underlying field is a Java volatile (or if an array cell, one
|
||||
* that is otherwise only accessed using volatile accesses).
|
||||
*
|
||||
* Corresponds to C11 atomic_store_explicit(..., memory_order_release).
|
||||
*/
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedObject(Object o, long offset, Object x);
|
||||
|
||||
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedInt(Object o, long offset, int x);
|
||||
|
||||
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public native void putOrderedLong(Object o, long offset, long x);
|
||||
|
||||
/** Acquire version of {@link #getObjectVolatile(Object, long)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
@ -1531,6 +1513,16 @@ public final class Unsafe {
|
||||
return getDoubleVolatile(o, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Versions of {@link #putObjectVolatile(Object, long, Object)}
|
||||
* that do not guarantee immediate visibility of the store to
|
||||
* other threads. This method is generally only useful if the
|
||||
* underlying field is a Java volatile (or if an array cell, one
|
||||
* that is otherwise only accessed using volatile accesses).
|
||||
*
|
||||
* Corresponds to C11 atomic_store_explicit(..., memory_order_release).
|
||||
*/
|
||||
|
||||
/** Release version of {@link #putObjectVolatile(Object, long, Object)} */
|
||||
@HotSpotIntrinsicCandidate
|
||||
public final void putObjectRelease(Object o, long offset, Object x) {
|
||||
|
||||
@ -1068,19 +1068,19 @@ public final class Unsafe {
|
||||
*/
|
||||
@ForceInline
|
||||
public void putOrderedObject(Object o, long offset, Object x) {
|
||||
theInternalUnsafe.putOrderedObject(o, offset, x);
|
||||
theInternalUnsafe.putObjectRelease(o, offset, x);
|
||||
}
|
||||
|
||||
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
|
||||
@ForceInline
|
||||
public void putOrderedInt(Object o, long offset, int x) {
|
||||
theInternalUnsafe.putOrderedInt(o, offset, x);
|
||||
theInternalUnsafe.putIntRelease(o, offset, x);
|
||||
}
|
||||
|
||||
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
|
||||
@ForceInline
|
||||
public void putOrderedLong(Object o, long offset, long x) {
|
||||
theInternalUnsafe.putOrderedLong(o, offset, x);
|
||||
theInternalUnsafe.putLongRelease(o, offset, x);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
public abstract class VarHandleBaseByteArrayTest extends VarHandleBaseTest {
|
||||
|
||||
enum MemoryMode {
|
||||
ALIGNED(0, false), UNALIGNED(0, true),
|
||||
BIG_ENDIAN(1, false), LITTLE_ENDIAN(1, true),
|
||||
READ_WRITE(2, false), READ_ONLY(2, true),;
|
||||
|
||||
final int bit;
|
||||
final int value;
|
||||
|
||||
MemoryMode(int bit, boolean value) {
|
||||
this.bit = bit;
|
||||
this.value = value ? 1 << bit : 0;
|
||||
}
|
||||
|
||||
boolean isSet(int bitSet) {
|
||||
return (bitSet & (1 << bit)) == value;
|
||||
}
|
||||
|
||||
static int bitSet(MemoryMode... modes) {
|
||||
if (modes == null) return 0;
|
||||
|
||||
int set = 0;
|
||||
for (MemoryMode m : modes) {
|
||||
set = (set & ~(1 << m.bit)) | m.value;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
static EnumSet<MemoryMode> enumSet(int bitSet) {
|
||||
EnumSet<MemoryMode> es = EnumSet.noneOf(MemoryMode.class);
|
||||
for (MemoryMode m : values()) {
|
||||
if (m.isSet(bitSet)) {
|
||||
es.add(m);
|
||||
}
|
||||
}
|
||||
return es;
|
||||
}
|
||||
}
|
||||
|
||||
static class Source<T> {
|
||||
final T s;
|
||||
final int memoryModes;
|
||||
|
||||
public Source(T s, MemoryMode... modes) {
|
||||
this.s = s;
|
||||
memoryModes = MemoryMode.bitSet(modes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return s.getClass().getCanonicalName() + " " + MemoryMode.enumSet(memoryModes);
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class ByteArrayViewSource<T> extends Source<T> {
|
||||
public ByteArrayViewSource(T t, MemoryMode... modes) {
|
||||
super(t, modes);
|
||||
}
|
||||
|
||||
abstract void fill(byte value);
|
||||
|
||||
abstract void fill(byte[] values);
|
||||
}
|
||||
|
||||
static class ByteArraySource extends ByteArrayViewSource<byte[]> {
|
||||
public ByteArraySource(byte[] bytes, MemoryMode... modes) {
|
||||
super(bytes, modes);
|
||||
}
|
||||
|
||||
void fill(byte value) {
|
||||
Arrays.fill(s, value);
|
||||
}
|
||||
|
||||
void fill(byte[] values) {
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
s[i] = values[i % values.length];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ByteBufferSource extends ByteArrayViewSource<ByteBuffer> {
|
||||
public ByteBufferSource(ByteBuffer buffer, MemoryMode... modes) {
|
||||
super(buffer, modes);
|
||||
}
|
||||
|
||||
void fill(byte value) {
|
||||
for (int i = 0; i < s.limit(); i++) {
|
||||
s.put(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
void fill(byte[] values) {
|
||||
for (int i = 0; i < s.limit(); i++) {
|
||||
s.put(i, values[i % values.length]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return s + " " + MemoryMode.enumSet(memoryModes);
|
||||
}
|
||||
}
|
||||
|
||||
static class ByteBufferReadOnlySource extends ByteBufferSource {
|
||||
final ByteBuffer rwSource;
|
||||
|
||||
public ByteBufferReadOnlySource(ByteBuffer roBuffer, ByteBuffer rwSource, MemoryMode... modes) {
|
||||
super(roBuffer, modes);
|
||||
this.rwSource = rwSource;
|
||||
}
|
||||
|
||||
void fill(byte value) {
|
||||
for (int i = 0; i < rwSource.limit(); i++) {
|
||||
rwSource.put(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
void fill(byte[] values) {
|
||||
for (int i = 0; i < rwSource.limit(); i++) {
|
||||
rwSource.put(i, values[i % values.length]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class VarHandleSource extends Source<VarHandle> {
|
||||
VarHandleSource(VarHandle vh, MemoryMode... modes) {
|
||||
super(vh, modes);
|
||||
}
|
||||
|
||||
boolean matches(ByteArrayViewSource<?> bav) {
|
||||
return s.coordinateTypes().get(0).isAssignableFrom(bav.s.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return " VarHandle " + MemoryMode.enumSet(memoryModes);
|
||||
}
|
||||
}
|
||||
|
||||
static class VarHandleSourceAccessTestCase extends AccessTestCase<VarHandleSource> {
|
||||
final ByteArrayViewSource<?> bs;
|
||||
final VarHandleSource vhs;
|
||||
|
||||
VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata) {
|
||||
this(desc, bs, vhs, ata, true);
|
||||
}
|
||||
|
||||
VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata, boolean loop) {
|
||||
super(vhs + " -> " + bs + " " + desc, ata, loop);
|
||||
this.bs = bs;
|
||||
this.vhs = vhs;
|
||||
}
|
||||
|
||||
@Override
|
||||
VarHandleSource get() {
|
||||
return vhs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static double rotateLeft(double i, int distance) {
|
||||
return Double.longBitsToDouble(
|
||||
Long.rotateLeft(Double.doubleToRawLongBits(i), distance));
|
||||
}
|
||||
|
||||
static double rotateRight(double i, int distance) {
|
||||
return Double.longBitsToDouble(
|
||||
Long.rotateRight(Double.doubleToRawLongBits(i), distance));
|
||||
}
|
||||
|
||||
static float rotateLeft(float i, int distance) {
|
||||
return Float.intBitsToFloat(
|
||||
Integer.rotateLeft(Float.floatToRawIntBits(i), distance));
|
||||
}
|
||||
|
||||
static float rotateRight(float i, int distance) {
|
||||
return Float.intBitsToFloat(
|
||||
Integer.rotateRight(Float.floatToRawIntBits(i), distance));
|
||||
}
|
||||
|
||||
static long rotateLeft(long i, int distance) {
|
||||
return Long.rotateLeft(i, distance);
|
||||
}
|
||||
|
||||
static long rotateRight(long i, int distance) {
|
||||
return Long.rotateRight(i, distance);
|
||||
}
|
||||
|
||||
static int rotateLeft(int i, int distance) {
|
||||
return Integer.rotateLeft(i, distance);
|
||||
}
|
||||
|
||||
static int rotateRight(int i, int distance) {
|
||||
return Integer.rotateRight(i, distance);
|
||||
}
|
||||
|
||||
static short rotateLeft(short i, int distance) {
|
||||
int v = (i << 16) | i;
|
||||
v = Integer.rotateLeft(v, distance);
|
||||
return (short) v;
|
||||
}
|
||||
|
||||
static short rotateRight(short i, int distance) {
|
||||
int v = (i << 16) | i;
|
||||
v = Integer.rotateRight(v, distance);
|
||||
return (short) v;
|
||||
}
|
||||
|
||||
static char rotateLeft(char i, int distance) {
|
||||
int v = (i << 16) | i;
|
||||
v = Integer.rotateLeft(v, distance);
|
||||
return (char) v;
|
||||
}
|
||||
|
||||
static char rotateRight(char i, int distance) {
|
||||
int v = (i << 16) | i;
|
||||
v = Integer.rotateRight(v, distance);
|
||||
return (char) v;
|
||||
}
|
||||
|
||||
static final int LENGTH_BYTES = 32;
|
||||
|
||||
byte[] array;
|
||||
|
||||
List<ByteArrayViewSource<?>> bavss;
|
||||
|
||||
List<VarHandleSource> vhss;
|
||||
|
||||
public void setupByteSources() {
|
||||
array = new byte[LENGTH_BYTES];
|
||||
|
||||
// Native endianess
|
||||
MemoryMode ne = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN
|
||||
? MemoryMode.BIG_ENDIAN : MemoryMode.LITTLE_ENDIAN;
|
||||
|
||||
bavss = new ArrayList<>();
|
||||
|
||||
// byte[] source
|
||||
ByteArraySource a =
|
||||
new ByteArraySource(array,
|
||||
ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(a);
|
||||
|
||||
|
||||
// Combinations of ByteBuffer sources
|
||||
ByteBufferSource hbb =
|
||||
new ByteBufferSource(ByteBuffer.wrap(array),
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(hbb);
|
||||
ByteBufferReadOnlySource hbb_ro =
|
||||
new ByteBufferReadOnlySource(hbb.s.asReadOnlyBuffer(), hbb.s,
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
|
||||
bavss.add(hbb_ro);
|
||||
|
||||
ByteBufferSource hbb_offset_aligned =
|
||||
new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4, array.length / 2).slice(),
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(hbb_offset_aligned);
|
||||
ByteBufferReadOnlySource hbb_offset_aligned_ro =
|
||||
new ByteBufferReadOnlySource(hbb_offset_aligned.s.asReadOnlyBuffer(), hbb_offset_aligned.s,
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
|
||||
bavss.add(hbb_offset_aligned_ro);
|
||||
|
||||
ByteBufferSource hbb_offset_unaligned =
|
||||
new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4 - 1, array.length / 2).slice(),
|
||||
MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(hbb_offset_unaligned);
|
||||
ByteBufferReadOnlySource hbb_offset_unaligned_ro =
|
||||
new ByteBufferReadOnlySource(hbb_offset_unaligned.s.asReadOnlyBuffer(), hbb_offset_unaligned.s,
|
||||
MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
|
||||
bavss.add(hbb_offset_unaligned_ro);
|
||||
|
||||
|
||||
ByteBufferSource dbb =
|
||||
new ByteBufferSource(ByteBuffer.allocateDirect(array.length),
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(dbb);
|
||||
ByteBufferReadOnlySource dbb_ro =
|
||||
new ByteBufferReadOnlySource(dbb.s.asReadOnlyBuffer(), dbb.s,
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
|
||||
bavss.add(dbb_ro);
|
||||
|
||||
ByteBufferSource dbb_offset_aligned =
|
||||
new ByteBufferSource(dbb.s.slice().position(array.length / 4).limit(array.length / 4 + array.length / 2).slice(),
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(dbb_offset_aligned);
|
||||
ByteBufferReadOnlySource dbb_offset_aligned_ro =
|
||||
new ByteBufferReadOnlySource(dbb_offset_aligned.s.asReadOnlyBuffer(), dbb_offset_aligned.s,
|
||||
MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
|
||||
bavss.add(dbb_offset_aligned_ro);
|
||||
|
||||
ByteBufferSource dbb_offset_unaligned =
|
||||
new ByteBufferSource(dbb.s.slice().position(array.length / 4 - 1).limit(array.length / 4 - 1 + array.length / 2).slice(),
|
||||
MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
|
||||
bavss.add(dbb_offset_unaligned);
|
||||
ByteBufferReadOnlySource dbb_offset_unaligned_ro =
|
||||
new ByteBufferReadOnlySource(dbb_offset_unaligned.s.asReadOnlyBuffer(), dbb_offset_unaligned.s,
|
||||
MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
|
||||
bavss.add(dbb_offset_unaligned_ro);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public void setup() {
|
||||
setupByteSources();
|
||||
setupVarHandleSources();
|
||||
}
|
||||
|
||||
abstract void setupVarHandleSources();
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
return vhss.stream().map(cvh -> new Object[]{cvh}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<java.lang.Class<?>> aepts = Arrays.asList(byte[].class, int.class);
|
||||
List<java.lang.Class<?>> bbpts = Arrays.asList(ByteBuffer.class, int.class);
|
||||
|
||||
Function<VarHandle, List<Class<?>>> vhToPts = vh ->
|
||||
vh.coordinateTypes().get(0) == byte[].class ? aepts : bbpts;
|
||||
|
||||
return vhss.stream().map(vh -> new Object[]{vh.s, vhToPts.apply(vh.s)}).toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
476
jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
Normal file
476
jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.invoke.WrongMethodTypeException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
abstract class VarHandleBaseTest {
|
||||
static final int ITERS = Integer.getInteger("iters", 1);
|
||||
|
||||
interface ThrowingRunnable {
|
||||
void run() throws Throwable;
|
||||
}
|
||||
|
||||
static void checkUOE(ThrowingRunnable r) {
|
||||
checkWithThrowable(UnsupportedOperationException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkUOE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(UnsupportedOperationException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkROBE(ThrowingRunnable r) {
|
||||
checkWithThrowable(ReadOnlyBufferException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkROBE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(ReadOnlyBufferException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkIOOBE(ThrowingRunnable r) {
|
||||
checkWithThrowable(IndexOutOfBoundsException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkIOOBE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(IndexOutOfBoundsException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkISE(ThrowingRunnable r) {
|
||||
checkWithThrowable(IllegalStateException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkISE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(IllegalStateException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkIAE(ThrowingRunnable r) {
|
||||
checkWithThrowable(IllegalAccessException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkIAE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(IllegalAccessException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkWMTE(ThrowingRunnable r) {
|
||||
checkWithThrowable(WrongMethodTypeException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkWMTE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(WrongMethodTypeException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkCCE(ThrowingRunnable r) {
|
||||
checkWithThrowable(ClassCastException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkCCE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(ClassCastException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkNPE(ThrowingRunnable r) {
|
||||
checkWithThrowable(NullPointerException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkNPE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(NullPointerException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkWithThrowable(Class<? extends Throwable> re,
|
||||
Object message,
|
||||
ThrowingRunnable r) {
|
||||
Throwable _e = null;
|
||||
try {
|
||||
r.run();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
_e = e;
|
||||
}
|
||||
message = message == null ? "" : message + ". ";
|
||||
assertNotNull(_e, String.format("%sNo throwable thrown. Expected %s", message, re));
|
||||
assertTrue(re.isInstance(_e), String.format("%sIncorrect throwable thrown, %s. Expected %s", message, _e, re));
|
||||
}
|
||||
|
||||
|
||||
enum TestAccessType {
|
||||
get,
|
||||
set,
|
||||
compareAndSet,
|
||||
compareAndExchange,
|
||||
getAndSet,
|
||||
getAndAdd;
|
||||
}
|
||||
|
||||
enum TestAccessMode {
|
||||
get(TestAccessType.get),
|
||||
set(TestAccessType.set),
|
||||
getVolatile(TestAccessType.get),
|
||||
setVolatile(TestAccessType.set),
|
||||
getAcquire(TestAccessType.get),
|
||||
setRelease(TestAccessType.set),
|
||||
getOpaque(TestAccessType.get),
|
||||
setOpaque(TestAccessType.set),
|
||||
compareAndSet(TestAccessType.compareAndSet),
|
||||
compareAndExchangeVolatile(TestAccessType.compareAndExchange),
|
||||
compareAndExchangeAcquire(TestAccessType.compareAndExchange),
|
||||
compareAndExchangeRelease(TestAccessType.compareAndExchange),
|
||||
weakCompareAndSet(TestAccessType.compareAndSet),
|
||||
weakCompareAndSetAcquire(TestAccessType.compareAndSet),
|
||||
weakCompareAndSetRelease(TestAccessType.compareAndSet),
|
||||
getAndSet(TestAccessType.getAndSet),
|
||||
getAndAdd(TestAccessType.getAndAdd),
|
||||
addAndGet(TestAccessType.getAndAdd),;
|
||||
|
||||
final TestAccessType at;
|
||||
final boolean isPolyMorphicInReturnType;
|
||||
final Class<?> returnType;
|
||||
|
||||
TestAccessMode(TestAccessType at) {
|
||||
this.at = at;
|
||||
|
||||
try {
|
||||
Method m = VarHandle.class.getMethod(name(), Object[].class);
|
||||
this.returnType = m.getReturnType();
|
||||
isPolyMorphicInReturnType = returnType != Object.class;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isOfType(TestAccessType at) {
|
||||
return this.at == at;
|
||||
}
|
||||
|
||||
VarHandle.AccessMode toAccessMode() {
|
||||
return VarHandle.AccessMode.valueOf(name());
|
||||
}
|
||||
}
|
||||
|
||||
static List<TestAccessMode> testAccessModes() {
|
||||
return Stream.of(TestAccessMode.values()).collect(toList());
|
||||
}
|
||||
|
||||
static List<TestAccessMode> testAccessModesOfType(TestAccessType... ats) {
|
||||
Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
|
||||
for (TestAccessType at : ats) {
|
||||
s = s.filter(e -> e.isOfType(at));
|
||||
}
|
||||
return s.collect(toList());
|
||||
}
|
||||
|
||||
static List<VarHandle.AccessMode> accessModes() {
|
||||
return Stream.of(VarHandle.AccessMode.values()).collect(toList());
|
||||
}
|
||||
|
||||
static List<VarHandle.AccessMode> accessModesOfType(TestAccessType... ats) {
|
||||
Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
|
||||
for (TestAccessType at : ats) {
|
||||
s = s.filter(e -> e.isOfType(at));
|
||||
}
|
||||
return s.map(TestAccessMode::toAccessMode).collect(toList());
|
||||
}
|
||||
|
||||
static MethodHandle toMethodHandle(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
return vh.toMethodHandle(tam.toAccessMode());
|
||||
}
|
||||
|
||||
static MethodHandle findVirtual(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
mt = vh.accessModeType(tam.toAccessMode());
|
||||
MethodHandle mh;
|
||||
try {
|
||||
mh = MethodHandles.publicLookup().
|
||||
findVirtual(VarHandle.class,
|
||||
tam.name(),
|
||||
mt);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return bind(vh, tam, mh, mt);
|
||||
}
|
||||
|
||||
static MethodHandle varHandleInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
mt = vh.accessModeType(tam.toAccessMode());
|
||||
MethodHandle mh = MethodHandles.varHandleInvoker(
|
||||
tam.toAccessMode(),
|
||||
mt);
|
||||
|
||||
return bind(vh, tam, mh, mt);
|
||||
}
|
||||
|
||||
static MethodHandle varHandleInvokerWithSymbolicTypeDescriptor(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
MethodHandle mh = MethodHandles.varHandleInvoker(
|
||||
tam.toAccessMode(),
|
||||
mt);
|
||||
|
||||
return bind(vh, tam, mh, mt);
|
||||
}
|
||||
|
||||
static MethodHandle varHandleExactInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
mt = vh.accessModeType(tam.toAccessMode());
|
||||
MethodHandle mh = MethodHandles.varHandleExactInvoker(
|
||||
tam.toAccessMode(),
|
||||
mt);
|
||||
|
||||
return bind(vh, tam, mh, mt);
|
||||
}
|
||||
|
||||
private static MethodHandle bind(VarHandle vh, TestAccessMode testAccessMode, MethodHandle mh, MethodType emt) {
|
||||
assertEquals(mh.type(), emt.insertParameterTypes(0, VarHandle.class),
|
||||
"MethodHandle type differs from access mode type");
|
||||
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
assertEquals(info.getMethodType(), emt,
|
||||
"MethodHandleInfo method type differs from access mode type");
|
||||
|
||||
return mh.bindTo(vh);
|
||||
}
|
||||
|
||||
private interface TriFunction<T, U, V, R> {
|
||||
R apply(T t, U u, V v);
|
||||
}
|
||||
|
||||
enum VarHandleToMethodHandle {
|
||||
VAR_HANDLE_TO_METHOD_HANDLE(
|
||||
"VarHandle.toMethodHandle",
|
||||
VarHandleBaseTest::toMethodHandle),
|
||||
METHOD_HANDLES_LOOKUP_FIND_VIRTUAL(
|
||||
"Lookup.findVirtual",
|
||||
VarHandleBaseTest::findVirtual),
|
||||
METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_ACCESS_MODE_TYPE(
|
||||
"MethodHandles.varHandleInvoker(accessModeType)",
|
||||
VarHandleBaseTest::varHandleInvokerWithAccessModeType),
|
||||
METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_SYMBOLIC_TYPE_DESCRIPTOR(
|
||||
"MethodHandles.varHandleInvoker(symbolicTypeDescriptor)",
|
||||
VarHandleBaseTest::varHandleInvokerWithSymbolicTypeDescriptor),
|
||||
METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER_WITH_ACCESS_MODE_TYPE(
|
||||
"MethodHandles.varHandleExactInvoker(accessModeType)",
|
||||
VarHandleBaseTest::varHandleExactInvokerWithAccessModeType);
|
||||
|
||||
final String desc;
|
||||
final TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f;
|
||||
final boolean exact;
|
||||
|
||||
VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
|
||||
this(desc, f, false);
|
||||
}
|
||||
|
||||
VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f,
|
||||
boolean exact) {
|
||||
this.desc = desc;
|
||||
this.f = f;
|
||||
this.exact = exact;
|
||||
}
|
||||
|
||||
MethodHandle apply(VarHandle vh, TestAccessMode am, MethodType mt) {
|
||||
return f.apply(vh, am, mt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
static class Handles {
|
||||
static class AccessModeAndType {
|
||||
final TestAccessMode tam;
|
||||
final MethodType t;
|
||||
|
||||
public AccessModeAndType(TestAccessMode tam, MethodType t) {
|
||||
this.tam = tam;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AccessModeAndType x = (AccessModeAndType) o;
|
||||
|
||||
if (tam != x.tam) return false;
|
||||
if (t != null ? !t.equals(x.t) : x.t != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = tam != null ? tam.hashCode() : 0;
|
||||
result = 31 * result + (t != null ? t.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
final VarHandle vh;
|
||||
final VarHandleToMethodHandle f;
|
||||
final EnumMap<TestAccessMode, MethodType> amToType;
|
||||
final Map<AccessModeAndType, MethodHandle> amToHandle;
|
||||
|
||||
Handles(VarHandle vh, VarHandleToMethodHandle f) throws Exception {
|
||||
this.vh = vh;
|
||||
this.f = f;
|
||||
this.amToHandle = new HashMap<>();
|
||||
|
||||
amToType = new EnumMap<>(TestAccessMode.class);
|
||||
for (TestAccessMode am : testAccessModes()) {
|
||||
amToType.put(am, vh.accessModeType(am.toAccessMode()));
|
||||
}
|
||||
}
|
||||
|
||||
MethodHandle get(TestAccessMode am) {
|
||||
return get(am, amToType.get(am));
|
||||
}
|
||||
|
||||
MethodHandle get(TestAccessMode am, MethodType mt) {
|
||||
AccessModeAndType amt = new AccessModeAndType(am, mt);
|
||||
return amToHandle.computeIfAbsent(
|
||||
amt, k -> f.apply(vh, am, mt));
|
||||
}
|
||||
}
|
||||
|
||||
interface AccessTestAction<T> {
|
||||
void action(T t) throws Throwable;
|
||||
}
|
||||
|
||||
static abstract class AccessTestCase<T> {
|
||||
final String desc;
|
||||
final AccessTestAction<T> ata;
|
||||
final boolean loop;
|
||||
|
||||
AccessTestCase(String desc, AccessTestAction<T> ata, boolean loop) {
|
||||
this.desc = desc;
|
||||
this.ata = ata;
|
||||
this.loop = loop;
|
||||
}
|
||||
|
||||
boolean requiresLoop() {
|
||||
return loop;
|
||||
}
|
||||
|
||||
abstract T get() throws Exception;
|
||||
|
||||
void testAccess(T t) throws Throwable {
|
||||
ata.action(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
static class VarHandleAccessTestCase extends AccessTestCase<VarHandle> {
|
||||
final VarHandle vh;
|
||||
|
||||
VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata) {
|
||||
this(desc, vh, ata, true);
|
||||
}
|
||||
|
||||
VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata, boolean loop) {
|
||||
super("VarHandle -> " + desc, ata, loop);
|
||||
this.vh = vh;
|
||||
}
|
||||
|
||||
@Override
|
||||
VarHandle get() {
|
||||
return vh;
|
||||
}
|
||||
}
|
||||
|
||||
static class MethodHandleAccessTestCase extends AccessTestCase<Handles> {
|
||||
final VarHandle vh;
|
||||
final VarHandleToMethodHandle f;
|
||||
|
||||
MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata) {
|
||||
this(desc, vh, f, ata, true);
|
||||
}
|
||||
|
||||
MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata, boolean loop) {
|
||||
super("VarHandle -> " + f.toString() + " -> " + desc, ata, loop);
|
||||
this.vh = vh;
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
@Override
|
||||
Handles get() throws Exception {
|
||||
return new Handles(vh, f);
|
||||
}
|
||||
}
|
||||
|
||||
static void testTypes(VarHandle vh) {
|
||||
List<Class<?>> pts = vh.coordinateTypes();
|
||||
|
||||
for (TestAccessMode accessMode : testAccessModes()) {
|
||||
MethodType amt = vh.accessModeType(accessMode.toAccessMode());
|
||||
|
||||
assertEquals(amt.parameterList().subList(0, pts.size()), pts);
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.get)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(mt.returnType(), vh.varType());
|
||||
assertEquals(mt.parameterList(), pts);
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.set)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(mt.returnType(), void.class);
|
||||
assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(mt.returnType(), boolean.class);
|
||||
assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
|
||||
assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(mt.returnType(), vh.varType());
|
||||
assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
|
||||
assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.getAndSet, TestAccessType.getAndAdd)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(mt.returnType(), vh.varType());
|
||||
assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessBoolean
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessBoolean
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessBoolean
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessBoolean
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
|
||||
static final boolean static_final_v = true;
|
||||
|
||||
static boolean static_v;
|
||||
|
||||
final boolean final_v = true;
|
||||
|
||||
boolean v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "final_v", boolean.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "v", boolean.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "static_v", boolean.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessBoolean.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(boolean[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), boolean.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "final_v", boolean.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "v", boolean.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessBoolean.class, "static_v", boolean.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessBoolean::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessBoolean::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessBoolean::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessBoolean::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessBoolean::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessBoolean recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
assertEquals(x, true, "get boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
assertEquals(x, true, "getVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
assertEquals(x, true, "getRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
assertEquals(x, true, "getOpaque boolean value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.getAndAdd(recv, true);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.addAndGet(recv, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
boolean x = (boolean) vh.get();
|
||||
assertEquals(x, true, "get boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
assertEquals(x, true, "getVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
assertEquals(x, true, "getRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
assertEquals(x, true, "getOpaque boolean value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.getAndAdd(true);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.addAndGet(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, true);
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
assertEquals(x, true, "set boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, false);
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
assertEquals(x, false, "setVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, true);
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
assertEquals(x, true, "setRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, false);
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
assertEquals(x, false, "setOpaque boolean value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.getAndAdd(recv, true);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.addAndGet(recv, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(true);
|
||||
boolean x = (boolean) vh.get();
|
||||
assertEquals(x, true, "set boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(false);
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
assertEquals(x, false, "setVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(true);
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
assertEquals(x, true, "setRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(false);
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
assertEquals(x, false, "setOpaque boolean value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.getAndAdd(true);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.addAndGet(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
boolean[] array = new boolean[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, true);
|
||||
boolean x = (boolean) vh.get(array, i);
|
||||
assertEquals(x, true, "get boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, false);
|
||||
boolean x = (boolean) vh.getVolatile(array, i);
|
||||
assertEquals(x, false, "setVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, true);
|
||||
boolean x = (boolean) vh.getAcquire(array, i);
|
||||
assertEquals(x, true, "setRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, false);
|
||||
boolean x = (boolean) vh.getOpaque(array, i);
|
||||
assertEquals(x, false, "setOpaque boolean value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
boolean[] array = new boolean[10];
|
||||
|
||||
int i = 0;
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeVolatile(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = (boolean) vh.compareAndExchangeRelease(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, true, false);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.getAndAdd(array, i, true);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean o = (boolean) vh.addAndGet(array, i, true);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
boolean[] array = new boolean[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean x = (boolean) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, true);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean x = (boolean) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, true);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean x = (boolean) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, true);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean x = (boolean) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, true);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessByte
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessByte
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessByte
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessByte
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessByte extends VarHandleBaseTest {
|
||||
static final byte static_final_v = (byte)1;
|
||||
|
||||
static byte static_v;
|
||||
|
||||
final byte final_v = (byte)1;
|
||||
|
||||
byte v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessByte.class, "final_v", byte.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessByte.class, "v", byte.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessByte.class, "static_final_v", byte.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessByte.class, "static_v", byte.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessByte.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(byte[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), byte.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessByte.class, "final_v", byte.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessByte.class, "v", byte.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessByte.class, "static_final_v", byte.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessByte.class, "static_v", byte.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessByte::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessByte::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessByte::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessByte::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessByte::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessByte recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
byte x = (byte) vh.get(recv);
|
||||
assertEquals(x, (byte)1, "get byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
byte x = (byte) vh.getVolatile(recv);
|
||||
assertEquals(x, (byte)1, "getVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
byte x = (byte) vh.getAcquire(recv);
|
||||
assertEquals(x, (byte)1, "getRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
byte x = (byte) vh.getOpaque(recv);
|
||||
assertEquals(x, (byte)1, "getOpaque byte value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.getAndAdd(recv, (byte)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.addAndGet(recv, (byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
byte x = (byte) vh.get();
|
||||
assertEquals(x, (byte)1, "get byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
byte x = (byte) vh.getVolatile();
|
||||
assertEquals(x, (byte)1, "getVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
byte x = (byte) vh.getAcquire();
|
||||
assertEquals(x, (byte)1, "getRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
byte x = (byte) vh.getOpaque();
|
||||
assertEquals(x, (byte)1, "getOpaque byte value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set((byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile((byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease((byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque((byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.getAndAdd((byte)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.addAndGet((byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, (byte)1);
|
||||
byte x = (byte) vh.get(recv);
|
||||
assertEquals(x, (byte)1, "set byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, (byte)2);
|
||||
byte x = (byte) vh.getVolatile(recv);
|
||||
assertEquals(x, (byte)2, "setVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, (byte)1);
|
||||
byte x = (byte) vh.getAcquire(recv);
|
||||
assertEquals(x, (byte)1, "setRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, (byte)2);
|
||||
byte x = (byte) vh.getOpaque(recv);
|
||||
assertEquals(x, (byte)2, "setOpaque byte value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.getAndAdd(recv, (byte)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.addAndGet(recv, (byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set((byte)1);
|
||||
byte x = (byte) vh.get();
|
||||
assertEquals(x, (byte)1, "set byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile((byte)2);
|
||||
byte x = (byte) vh.getVolatile();
|
||||
assertEquals(x, (byte)2, "setVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease((byte)1);
|
||||
byte x = (byte) vh.getAcquire();
|
||||
assertEquals(x, (byte)1, "setRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque((byte)2);
|
||||
byte x = (byte) vh.getOpaque();
|
||||
assertEquals(x, (byte)2, "setOpaque byte value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.getAndAdd((byte)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.addAndGet((byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
byte[] array = new byte[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, (byte)1);
|
||||
byte x = (byte) vh.get(array, i);
|
||||
assertEquals(x, (byte)1, "get byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, (byte)2);
|
||||
byte x = (byte) vh.getVolatile(array, i);
|
||||
assertEquals(x, (byte)2, "setVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, (byte)1);
|
||||
byte x = (byte) vh.getAcquire(array, i);
|
||||
assertEquals(x, (byte)1, "setRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, (byte)2);
|
||||
byte x = (byte) vh.getOpaque(array, i);
|
||||
assertEquals(x, (byte)2, "setOpaque byte value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
byte[] array = new byte[10];
|
||||
|
||||
int i = 0;
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeVolatile(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.getAndAdd(array, i, (byte)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
byte o = (byte) vh.addAndGet(array, i, (byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
byte[] array = new byte[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
byte x = (byte) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, (byte)1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
byte x = (byte) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, (byte)1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
byte x = (byte) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, (byte)1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
byte x = (byte) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, (byte)1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessChar
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessChar
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessChar
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessChar extends VarHandleBaseTest {
|
||||
static final char static_final_v = 'a';
|
||||
|
||||
static char static_v;
|
||||
|
||||
final char final_v = 'a';
|
||||
|
||||
char v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessChar.class, "final_v", char.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessChar.class, "v", char.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessChar.class, "static_final_v", char.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessChar.class, "static_v", char.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(char[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessChar.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(char[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), char.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessChar.class, "final_v", char.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessChar.class, "v", char.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessChar.class, "static_final_v", char.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessChar.class, "static_v", char.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessChar::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessChar::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessChar::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessChar::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessChar::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessChar recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
char x = (char) vh.get(recv);
|
||||
assertEquals(x, 'a', "get char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
char x = (char) vh.getVolatile(recv);
|
||||
assertEquals(x, 'a', "getVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
char x = (char) vh.getAcquire(recv);
|
||||
assertEquals(x, 'a', "getRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
char x = (char) vh.getOpaque(recv);
|
||||
assertEquals(x, 'a', "getOpaque char value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(recv, 'a');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet(recv, 'a');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
char x = (char) vh.get();
|
||||
assertEquals(x, 'a', "get char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
char x = (char) vh.getVolatile();
|
||||
assertEquals(x, 'a', "getVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
char x = (char) vh.getAcquire();
|
||||
assertEquals(x, 'a', "getRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
char x = (char) vh.getOpaque();
|
||||
assertEquals(x, 'a', "getOpaque char value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set('b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile('b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease('b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque('b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd('a');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet('a');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, 'a');
|
||||
char x = (char) vh.get(recv);
|
||||
assertEquals(x, 'a', "set char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, 'b');
|
||||
char x = (char) vh.getVolatile(recv);
|
||||
assertEquals(x, 'b', "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, 'a');
|
||||
char x = (char) vh.getAcquire(recv);
|
||||
assertEquals(x, 'a', "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, 'b');
|
||||
char x = (char) vh.getOpaque(recv);
|
||||
assertEquals(x, 'b', "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(recv, 'a');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet(recv, 'a');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set('a');
|
||||
char x = (char) vh.get();
|
||||
assertEquals(x, 'a', "set char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile('b');
|
||||
char x = (char) vh.getVolatile();
|
||||
assertEquals(x, 'b', "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease('a');
|
||||
char x = (char) vh.getAcquire();
|
||||
assertEquals(x, 'a', "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque('b');
|
||||
char x = (char) vh.getOpaque();
|
||||
assertEquals(x, 'b', "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease('a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd('a');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet('a');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
char[] array = new char[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, 'a');
|
||||
char x = (char) vh.get(array, i);
|
||||
assertEquals(x, 'a', "get char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, 'b');
|
||||
char x = (char) vh.getVolatile(array, i);
|
||||
assertEquals(x, 'b', "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, 'a');
|
||||
char x = (char) vh.getAcquire(array, i);
|
||||
assertEquals(x, 'a', "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, 'b');
|
||||
char x = (char) vh.getOpaque(array, i);
|
||||
assertEquals(x, 'b', "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
char[] array = new char[10];
|
||||
|
||||
int i = 0;
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, 'a', 'b');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, i, 'a');
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet(array, i, 'a');
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
char[] array = new char[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, 'a');
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, 'a');
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, 'a');
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, 'a');
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessDouble
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessDouble
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessDouble
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessDouble
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessDouble extends VarHandleBaseTest {
|
||||
static final double static_final_v = 1.0d;
|
||||
|
||||
static double static_v;
|
||||
|
||||
final double final_v = 1.0d;
|
||||
|
||||
double v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessDouble.class, "final_v", double.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessDouble.class, "v", double.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessDouble.class, "static_final_v", double.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessDouble.class, "static_v", double.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(double[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessDouble.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(double[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), double.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessDouble.class, "final_v", double.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessDouble.class, "v", double.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessDouble.class, "static_final_v", double.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessDouble.class, "static_v", double.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessDouble::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessDouble::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessDouble::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessDouble::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessDouble::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessDouble::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessDouble::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessDouble recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
double x = (double) vh.get(recv);
|
||||
assertEquals(x, 1.0d, "get double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
double x = (double) vh.getVolatile(recv);
|
||||
assertEquals(x, 1.0d, "getVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
double x = (double) vh.getAcquire(recv);
|
||||
assertEquals(x, 1.0d, "getRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
double x = (double) vh.getOpaque(recv);
|
||||
assertEquals(x, 1.0d, "getOpaque double value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(recv, 1.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(recv, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
double x = (double) vh.get();
|
||||
assertEquals(x, 1.0d, "get double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
double x = (double) vh.getVolatile();
|
||||
assertEquals(x, 1.0d, "getVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
double x = (double) vh.getAcquire();
|
||||
assertEquals(x, 1.0d, "getRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
double x = (double) vh.getOpaque();
|
||||
assertEquals(x, 1.0d, "getOpaque double value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(1.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, 1.0d);
|
||||
double x = (double) vh.get(recv);
|
||||
assertEquals(x, 1.0d, "set double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, 2.0d);
|
||||
double x = (double) vh.getVolatile(recv);
|
||||
assertEquals(x, 2.0d, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, 1.0d);
|
||||
double x = (double) vh.getAcquire(recv);
|
||||
assertEquals(x, 1.0d, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, 2.0d);
|
||||
double x = (double) vh.getOpaque(recv);
|
||||
assertEquals(x, 2.0d, "setOpaque double value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(recv, 1.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(recv, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(1.0d);
|
||||
double x = (double) vh.get();
|
||||
assertEquals(x, 1.0d, "set double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(2.0d);
|
||||
double x = (double) vh.getVolatile();
|
||||
assertEquals(x, 2.0d, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(1.0d);
|
||||
double x = (double) vh.getAcquire();
|
||||
assertEquals(x, 1.0d, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(2.0d);
|
||||
double x = (double) vh.getOpaque();
|
||||
assertEquals(x, 2.0d, "setOpaque double value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(1.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
double[] array = new double[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, 1.0d);
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, 1.0d, "get double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, 2.0d);
|
||||
double x = (double) vh.getVolatile(array, i);
|
||||
assertEquals(x, 2.0d, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, 1.0d);
|
||||
double x = (double) vh.getAcquire(array, i);
|
||||
assertEquals(x, 1.0d, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, 2.0d);
|
||||
double x = (double) vh.getOpaque(array, i);
|
||||
assertEquals(x, 2.0d, "setOpaque double value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
double[] array = new double[10];
|
||||
|
||||
int i = 0;
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(array, i, 1.0d);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(array, i, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, 1.0d);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, 1.0d);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, 1.0d);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, 1.0d);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessFloat
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessFloat
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessFloat
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessFloat
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessFloat extends VarHandleBaseTest {
|
||||
static final float static_final_v = 1.0f;
|
||||
|
||||
static float static_v;
|
||||
|
||||
final float final_v = 1.0f;
|
||||
|
||||
float v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessFloat.class, "final_v", float.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessFloat.class, "v", float.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessFloat.class, "static_final_v", float.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessFloat.class, "static_v", float.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(float[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessFloat.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(float[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), float.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessFloat.class, "final_v", float.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessFloat.class, "v", float.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessFloat.class, "static_final_v", float.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessFloat.class, "static_v", float.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessFloat::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessFloat::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessFloat::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessFloat::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessFloat::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessFloat::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessFloat::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessFloat recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
float x = (float) vh.get(recv);
|
||||
assertEquals(x, 1.0f, "get float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
float x = (float) vh.getVolatile(recv);
|
||||
assertEquals(x, 1.0f, "getVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
float x = (float) vh.getAcquire(recv);
|
||||
assertEquals(x, 1.0f, "getRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
float x = (float) vh.getOpaque(recv);
|
||||
assertEquals(x, 1.0f, "getOpaque float value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessFloat recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(recv, 1.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(recv, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
float x = (float) vh.get();
|
||||
assertEquals(x, 1.0f, "get float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
float x = (float) vh.getVolatile();
|
||||
assertEquals(x, 1.0f, "getVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
float x = (float) vh.getAcquire();
|
||||
assertEquals(x, 1.0f, "getRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
float x = (float) vh.getOpaque();
|
||||
assertEquals(x, 1.0f, "getOpaque float value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(1.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, 1.0f);
|
||||
float x = (float) vh.get(recv);
|
||||
assertEquals(x, 1.0f, "set float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, 2.0f);
|
||||
float x = (float) vh.getVolatile(recv);
|
||||
assertEquals(x, 2.0f, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, 1.0f);
|
||||
float x = (float) vh.getAcquire(recv);
|
||||
assertEquals(x, 1.0f, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, 2.0f);
|
||||
float x = (float) vh.getOpaque(recv);
|
||||
assertEquals(x, 2.0f, "setOpaque float value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessFloat recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(recv, 1.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(recv, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(1.0f);
|
||||
float x = (float) vh.get();
|
||||
assertEquals(x, 1.0f, "set float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(2.0f);
|
||||
float x = (float) vh.getVolatile();
|
||||
assertEquals(x, 2.0f, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(1.0f);
|
||||
float x = (float) vh.getAcquire();
|
||||
assertEquals(x, 1.0f, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(2.0f);
|
||||
float x = (float) vh.getOpaque();
|
||||
assertEquals(x, 2.0f, "setOpaque float value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(1.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
float[] array = new float[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, 1.0f);
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, 1.0f, "get float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, 2.0f);
|
||||
float x = (float) vh.getVolatile(array, i);
|
||||
assertEquals(x, 2.0f, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, 1.0f);
|
||||
float x = (float) vh.getAcquire(array, i);
|
||||
assertEquals(x, 1.0f, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, 2.0f);
|
||||
float x = (float) vh.getOpaque(array, i);
|
||||
assertEquals(x, 2.0f, "setOpaque float value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
float[] array = new float[10];
|
||||
|
||||
int i = 0;
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(array, i, 1.0f);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(array, i, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, 1.0f);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, 1.0f);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, 1.0f);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, 1.0f);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
803
jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
Normal file
803
jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
Normal file
@ -0,0 +1,803 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessInt
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessInt
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessInt
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessInt
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessInt extends VarHandleBaseTest {
|
||||
static final int static_final_v = 1;
|
||||
|
||||
static int static_v;
|
||||
|
||||
final int final_v = 1;
|
||||
|
||||
int v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessInt.class, "final_v", int.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessInt.class, "v", int.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessInt.class, "static_final_v", int.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessInt.class, "static_v", int.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(int[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessInt.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(int[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), int.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessInt.class, "final_v", int.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessInt.class, "v", int.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessInt.class, "static_final_v", int.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessInt.class, "static_v", int.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessInt::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessInt::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessInt::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessInt::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessInt::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessInt::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessInt::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessInt recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "get int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
int x = (int) vh.getVolatile(recv);
|
||||
assertEquals(x, 1, "getVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
int x = (int) vh.getAcquire(recv);
|
||||
assertEquals(x, 1, "getRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
int x = (int) vh.getOpaque(recv);
|
||||
assertEquals(x, 1, "getOpaque int value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, 2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, 2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, 2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, 2);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "get int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
int x = (int) vh.getVolatile();
|
||||
assertEquals(x, 1, "getVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
int x = (int) vh.getAcquire();
|
||||
assertEquals(x, 1, "getRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
int x = (int) vh.getOpaque();
|
||||
assertEquals(x, 1, "getOpaque int value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(2);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, 1);
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "set int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, 2);
|
||||
int x = (int) vh.getVolatile(recv);
|
||||
assertEquals(x, 2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, 1);
|
||||
int x = (int) vh.getAcquire(recv);
|
||||
assertEquals(x, 1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, 2);
|
||||
int x = (int) vh.getOpaque(recv);
|
||||
assertEquals(x, 2, "setOpaque int value");
|
||||
}
|
||||
|
||||
vh.set(recv, 1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(recv, 1, 2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(recv, 1, 3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(recv, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(recv, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(recv, 1, 2);
|
||||
assertEquals(r, 1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(recv, 1, 3);
|
||||
assertEquals(r, 2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(recv, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(recv, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(recv, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 2, 1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) vh.getAndSet(recv, 1);
|
||||
assertEquals(o, 2, "getAndSet int");
|
||||
int x = (int) vh.get(recv);
|
||||
assertEquals(x, 1, "getAndSet int value");
|
||||
}
|
||||
|
||||
vh.set(recv, 1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) vh.getAndAdd(recv, 3);
|
||||
assertEquals(o, 1, "getAndAdd int");
|
||||
int c = (int) vh.addAndGet(recv, 3);
|
||||
assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(1);
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "set int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(2);
|
||||
int x = (int) vh.getVolatile();
|
||||
assertEquals(x, 2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(1);
|
||||
int x = (int) vh.getAcquire();
|
||||
assertEquals(x, 1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(2);
|
||||
int x = (int) vh.getOpaque();
|
||||
assertEquals(x, 2, "setOpaque int value");
|
||||
}
|
||||
|
||||
vh.set(1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(1, 2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(1, 3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(1, 2);
|
||||
assertEquals(r, 1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(1, 3);
|
||||
assertEquals(r, 2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeRelease int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSet(1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSetAcquire(2, 1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSetRelease( 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) vh.getAndSet( 1);
|
||||
assertEquals(o, 2, "getAndSet int");
|
||||
int x = (int) vh.get();
|
||||
assertEquals(x, 1, "getAndSet int value");
|
||||
}
|
||||
|
||||
vh.set(1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) vh.getAndAdd( 3);
|
||||
assertEquals(o, 1, "getAndAdd int");
|
||||
int c = (int) vh.addAndGet(3);
|
||||
assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
int[] array = new int[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, 1);
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "get int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, 2);
|
||||
int x = (int) vh.getVolatile(array, i);
|
||||
assertEquals(x, 2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, 1);
|
||||
int x = (int) vh.getAcquire(array, i);
|
||||
assertEquals(x, 1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, 2);
|
||||
int x = (int) vh.getOpaque(array, i);
|
||||
assertEquals(x, 2, "setOpaque int value");
|
||||
}
|
||||
|
||||
vh.set(array, i, 1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, 1, 2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, 1, 3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, i, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, i, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, i, 1, 2);
|
||||
assertEquals(r, 1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, i, 1, 3);
|
||||
assertEquals(r, 2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(array, i, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(array, i, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, 2, 1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) vh.getAndSet(array, i, 1);
|
||||
assertEquals(o, 2, "getAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, 1, "getAndSet int value");
|
||||
}
|
||||
|
||||
vh.set(array, i, 1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) vh.getAndAdd(array, i, 3);
|
||||
assertEquals(o, 1, "getAndAdd int");
|
||||
int c = (int) vh.addAndGet(array, i, 3);
|
||||
assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
int[] array = new int[10];
|
||||
|
||||
int i = 0;
|
||||
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
int[] array = new int[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, 1, 2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, ci, 2, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, ci, 2, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeRelease(array, ci, 2, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, 1, 2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, 1, 2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, 1, 2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.getAndSet(array, ci, 1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.getAndAdd(array, ci, 3);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.addAndGet(array, ci, 3);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,803 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessLong
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessLong
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessLong
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessLong
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessLong extends VarHandleBaseTest {
|
||||
static final long static_final_v = 1L;
|
||||
|
||||
static long static_v;
|
||||
|
||||
final long final_v = 1L;
|
||||
|
||||
long v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessLong.class, "final_v", long.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessLong.class, "v", long.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessLong.class, "static_final_v", long.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessLong.class, "static_v", long.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(long[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessLong.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(long[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), long.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessLong.class, "final_v", long.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessLong.class, "v", long.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessLong.class, "static_final_v", long.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessLong.class, "static_v", long.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessLong::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessLong::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessLong::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessLong::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessLong::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessLong::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessLong::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessLong recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "get long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
long x = (long) vh.getVolatile(recv);
|
||||
assertEquals(x, 1L, "getVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
long x = (long) vh.getAcquire(recv);
|
||||
assertEquals(x, 1L, "getRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
long x = (long) vh.getOpaque(recv);
|
||||
assertEquals(x, 1L, "getOpaque long value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, 2L);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, 2L);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, 2L);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, 2L);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "get long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
long x = (long) vh.getVolatile();
|
||||
assertEquals(x, 1L, "getVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
long x = (long) vh.getAcquire();
|
||||
assertEquals(x, 1L, "getRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
long x = (long) vh.getOpaque();
|
||||
assertEquals(x, 1L, "getOpaque long value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(2L);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(2L);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(2L);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(2L);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, 1L);
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "set long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, 2L);
|
||||
long x = (long) vh.getVolatile(recv);
|
||||
assertEquals(x, 2L, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, 1L);
|
||||
long x = (long) vh.getAcquire(recv);
|
||||
assertEquals(x, 1L, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, 2L);
|
||||
long x = (long) vh.getOpaque(recv);
|
||||
assertEquals(x, 2L, "setOpaque long value");
|
||||
}
|
||||
|
||||
vh.set(recv, 1L);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(recv, 1L, 2L);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 2L, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(recv, 1L, 3L);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 2L, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(recv, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(recv, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(recv, 1L, 2L);
|
||||
assertEquals(r, 1L, "success compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(recv, 1L, 3L);
|
||||
assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(recv, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(recv, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(recv, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 2L, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, 2L, 1L);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 2L, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) vh.getAndSet(recv, 1L);
|
||||
assertEquals(o, 2L, "getAndSet long");
|
||||
long x = (long) vh.get(recv);
|
||||
assertEquals(x, 1L, "getAndSet long value");
|
||||
}
|
||||
|
||||
vh.set(recv, 1L);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) vh.getAndAdd(recv, 3L);
|
||||
assertEquals(o, 1L, "getAndAdd long");
|
||||
long c = (long) vh.addAndGet(recv, 3L);
|
||||
assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(1L);
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "set long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(2L);
|
||||
long x = (long) vh.getVolatile();
|
||||
assertEquals(x, 2L, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(1L);
|
||||
long x = (long) vh.getAcquire();
|
||||
assertEquals(x, 1L, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(2L);
|
||||
long x = (long) vh.getOpaque();
|
||||
assertEquals(x, 2L, "setOpaque long value");
|
||||
}
|
||||
|
||||
vh.set(1L);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(1L, 2L);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 2L, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(1L, 3L);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 2L, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(1L, 2L);
|
||||
assertEquals(r, 1L, "success compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(1L, 3L);
|
||||
assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeRelease long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeRelease long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSet(1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 2L, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSetAcquire(2L, 1L);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSetRelease( 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 2L, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) vh.getAndSet( 1L);
|
||||
assertEquals(o, 2L, "getAndSet long");
|
||||
long x = (long) vh.get();
|
||||
assertEquals(x, 1L, "getAndSet long value");
|
||||
}
|
||||
|
||||
vh.set(1L);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) vh.getAndAdd( 3L);
|
||||
assertEquals(o, 1L, "getAndAdd long");
|
||||
long c = (long) vh.addAndGet(3L);
|
||||
assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
long[] array = new long[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, 1L);
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "get long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, 2L);
|
||||
long x = (long) vh.getVolatile(array, i);
|
||||
assertEquals(x, 2L, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, 1L);
|
||||
long x = (long) vh.getAcquire(array, i);
|
||||
assertEquals(x, 1L, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, 2L);
|
||||
long x = (long) vh.getOpaque(array, i);
|
||||
assertEquals(x, 2L, "setOpaque long value");
|
||||
}
|
||||
|
||||
vh.set(array, i, 1L);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, 1L, 2L);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 2L, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, 1L, 3L);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 2L, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, i, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, i, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, i, 1L, 2L);
|
||||
assertEquals(r, 1L, "success compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, i, 1L, 3L);
|
||||
assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(array, i, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(array, i, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 2L, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, 2L, 1L);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 2L, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) vh.getAndSet(array, i, 1L);
|
||||
assertEquals(o, 2L, "getAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, 1L, "getAndSet long value");
|
||||
}
|
||||
|
||||
vh.set(array, i, 1L);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) vh.getAndAdd(array, i, 3L);
|
||||
assertEquals(o, 1L, "getAndAdd long");
|
||||
long c = (long) vh.addAndGet(array, i, 3L);
|
||||
assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
long[] array = new long[10];
|
||||
|
||||
int i = 0;
|
||||
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
long[] array = new long[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, 1L, 2L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, ci, 2L, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, ci, 2L, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeRelease(array, ci, 2L, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, 1L, 2L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, 1L, 2L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, 1L, 2L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.getAndSet(array, ci, 1L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.getAndAdd(array, ci, 3L);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.addAndGet(array, ci, 3L);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessShort
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessShort
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessShort
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessShort
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessShort extends VarHandleBaseTest {
|
||||
static final short static_final_v = (short)1;
|
||||
|
||||
static short static_v;
|
||||
|
||||
final short final_v = (short)1;
|
||||
|
||||
short v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessShort.class, "final_v", short.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessShort.class, "v", short.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessShort.class, "static_final_v", short.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessShort.class, "static_v", short.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(short[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessShort.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(short[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), short.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessShort.class, "final_v", short.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessShort.class, "v", short.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessShort.class, "static_final_v", short.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessShort.class, "static_v", short.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessShort::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessShort::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessShort::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessShort::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessShort::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessShort::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessShort::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessShort recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
short x = (short) vh.get(recv);
|
||||
assertEquals(x, (short)1, "get short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
short x = (short) vh.getVolatile(recv);
|
||||
assertEquals(x, (short)1, "getVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
short x = (short) vh.getAcquire(recv);
|
||||
assertEquals(x, (short)1, "getRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
short x = (short) vh.getOpaque(recv);
|
||||
assertEquals(x, (short)1, "getOpaque short value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(recv, (short)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet(recv, (short)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
short x = (short) vh.get();
|
||||
assertEquals(x, (short)1, "get short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
short x = (short) vh.getVolatile();
|
||||
assertEquals(x, (short)1, "getVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
short x = (short) vh.getAcquire();
|
||||
assertEquals(x, (short)1, "getRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
short x = (short) vh.getOpaque();
|
||||
assertEquals(x, (short)1, "getOpaque short value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set((short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile((short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease((short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque((short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd((short)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet((short)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, (short)1);
|
||||
short x = (short) vh.get(recv);
|
||||
assertEquals(x, (short)1, "set short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, (short)2);
|
||||
short x = (short) vh.getVolatile(recv);
|
||||
assertEquals(x, (short)2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, (short)1);
|
||||
short x = (short) vh.getAcquire(recv);
|
||||
assertEquals(x, (short)1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, (short)2);
|
||||
short x = (short) vh.getOpaque(recv);
|
||||
assertEquals(x, (short)2, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(recv, (short)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet(recv, (short)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set((short)1);
|
||||
short x = (short) vh.get();
|
||||
assertEquals(x, (short)1, "set short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile((short)2);
|
||||
short x = (short) vh.getVolatile();
|
||||
assertEquals(x, (short)2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease((short)1);
|
||||
short x = (short) vh.getAcquire();
|
||||
assertEquals(x, (short)1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque((short)2);
|
||||
short x = (short) vh.getOpaque();
|
||||
assertEquals(x, (short)2, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease((short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd((short)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet((short)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
short[] array = new short[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, (short)1);
|
||||
short x = (short) vh.get(array, i);
|
||||
assertEquals(x, (short)1, "get short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, (short)2);
|
||||
short x = (short) vh.getVolatile(array, i);
|
||||
assertEquals(x, (short)2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, (short)1);
|
||||
short x = (short) vh.getAcquire(array, i);
|
||||
assertEquals(x, (short)1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, (short)2);
|
||||
short x = (short) vh.getOpaque(array, i);
|
||||
assertEquals(x, (short)2, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
short[] array = new short[10];
|
||||
|
||||
int i = 0;
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, (short)1, (short)2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, i, (short)1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet(array, i, (short)1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
short[] array = new short[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, (short)1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, (short)1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, (short)1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, (short)1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,804 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=10 -Xint VarHandleTestAccessString
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessString
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestAccessString
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessString
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestAccessString extends VarHandleBaseTest {
|
||||
static final String static_final_v = "foo";
|
||||
|
||||
static String static_v;
|
||||
|
||||
final String final_v = "foo";
|
||||
|
||||
String v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessString.class, "final_v", String.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessString.class, "v", String.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessString.class, "static_final_v", String.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessString.class, "static_v", String.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(String[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
List<VarHandle> vhs = new ArrayList<>();
|
||||
vhs.add(vhField);
|
||||
vhs.add(vhStaticField);
|
||||
vhs.add(vhArray);
|
||||
|
||||
return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandle vh) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] typesProvider() throws Exception {
|
||||
List<Object[]> types = new ArrayList<>();
|
||||
types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessString.class)});
|
||||
types.add(new Object[] {vhStaticField, Arrays.asList()});
|
||||
types.add(new Object[] {vhArray, Arrays.asList(String[].class, int.class)});
|
||||
|
||||
return types.stream().toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<Class<?>> pts) {
|
||||
assertEquals(vh.varType(), String.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLookupInstanceToStatic() {
|
||||
checkIAE("Lookup of static final field to instance final field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessString.class, "final_v", String.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of static field to instance field", () -> {
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestAccessString.class, "v", String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupStaticToInstance() {
|
||||
checkIAE("Lookup of instance final field to static final field", () -> {
|
||||
MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessString.class, "static_final_v", String.class);
|
||||
});
|
||||
|
||||
checkIAE("Lookup of instance field to static field", () -> {
|
||||
vhStaticField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestAccessString.class, "static_v", String.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field",
|
||||
vhFinalField, vh -> testInstanceFinalField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
|
||||
vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static final field",
|
||||
vhStaticFinalField, VarHandleTestAccessString::testStaticFinalField));
|
||||
cases.add(new VarHandleAccessTestCase("Static final field unsupported",
|
||||
vhStaticFinalField, VarHandleTestAccessString::testStaticFinalFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field",
|
||||
vhField, vh -> testInstanceField(this, vh)));
|
||||
cases.add(new VarHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, vh -> testInstanceFieldUnsupported(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field",
|
||||
vhStaticField, VarHandleTestAccessString::testStaticField));
|
||||
cases.add(new VarHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, VarHandleTestAccessString::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array",
|
||||
vhArray, VarHandleTestAccessString::testArray));
|
||||
cases.add(new VarHandleAccessTestCase("Array unsupported",
|
||||
vhArray, VarHandleTestAccessString::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new VarHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, VarHandleTestAccessString::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void testInstanceFinalField(VarHandleTestAccessString recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "get String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
String x = (String) vh.getVolatile(recv);
|
||||
assertEquals(x, "foo", "getVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
String x = (String) vh.getAcquire(recv);
|
||||
assertEquals(x, "foo", "getRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
String x = (String) vh.getOpaque(recv);
|
||||
assertEquals(x, "foo", "getOpaque String value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFinalFieldUnsupported(VarHandleTestAccessString recv, VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set(recv, "bar");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile(recv, "bar");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease(recv, "bar");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque(recv, "bar");
|
||||
});
|
||||
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.getAndAdd(recv, "foo");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.addAndGet(recv, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFinalField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "get String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
String x = (String) vh.getVolatile();
|
||||
assertEquals(x, "foo", "getVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
String x = (String) vh.getAcquire();
|
||||
assertEquals(x, "foo", "getRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
String x = (String) vh.getOpaque();
|
||||
assertEquals(x, "foo", "getOpaque String value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFinalFieldUnsupported(VarHandle vh) {
|
||||
checkUOE(() -> {
|
||||
vh.set("bar");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setVolatile("bar");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setRelease("bar");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
vh.setOpaque("bar");
|
||||
});
|
||||
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.getAndAdd("foo");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.addAndGet("foo");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(recv, "foo");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "set String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(recv, "bar");
|
||||
String x = (String) vh.getVolatile(recv);
|
||||
assertEquals(x, "bar", "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(recv, "foo");
|
||||
String x = (String) vh.getAcquire(recv);
|
||||
assertEquals(x, "foo", "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(recv, "bar");
|
||||
String x = (String) vh.getOpaque(recv);
|
||||
assertEquals(x, "bar", "setOpaque String value");
|
||||
}
|
||||
|
||||
vh.set(recv, "foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(recv, "foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "bar", "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(recv, "foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "bar", "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeVolatile(recv, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeVolatile String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeVolatile(recv, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeAcquire(recv, "foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeAcquire(recv, "foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeRelease(recv, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeRelease(recv, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(recv, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSet String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "bar", "weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(recv, "bar", "foo");
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(recv, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSetRelease String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "bar", "weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) vh.getAndSet(recv, "foo");
|
||||
assertEquals(o, "bar", "getAndSet String");
|
||||
String x = (String) vh.get(recv);
|
||||
assertEquals(x, "foo", "getAndSet String value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestAccessString recv, VarHandle vh) {
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.getAndAdd(recv, "foo");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.addAndGet(recv, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(VarHandle vh) {
|
||||
// Plain
|
||||
{
|
||||
vh.set("foo");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "set String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile("bar");
|
||||
String x = (String) vh.getVolatile();
|
||||
assertEquals(x, "bar", "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease("foo");
|
||||
String x = (String) vh.getAcquire();
|
||||
assertEquals(x, "foo", "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque("bar");
|
||||
String x = (String) vh.getOpaque();
|
||||
assertEquals(x, "bar", "setOpaque String value");
|
||||
}
|
||||
|
||||
vh.set("foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet("foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "bar", "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet("foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "bar", "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeVolatile("bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeVolatile String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeVolatile("bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeAcquire("foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeAcquire("foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeRelease("bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeRelease("bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSet("foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSet String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "bar", "weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSetAcquire("bar", "foo");
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) vh.weakCompareAndSetRelease( "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSetRelease String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "bar", "weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) vh.getAndSet( "foo");
|
||||
assertEquals(o, "bar", "getAndSet String");
|
||||
String x = (String) vh.get();
|
||||
assertEquals(x, "foo", "getAndSet String value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(VarHandle vh) {
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.getAndAdd("foo");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.addAndGet("foo");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static void testArray(VarHandle vh) {
|
||||
String[] array = new String[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, "foo");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "get String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, "bar");
|
||||
String x = (String) vh.getVolatile(array, i);
|
||||
assertEquals(x, "bar", "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, "foo");
|
||||
String x = (String) vh.getAcquire(array, i);
|
||||
assertEquals(x, "foo", "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, "bar");
|
||||
String x = (String) vh.getOpaque(array, i);
|
||||
assertEquals(x, "bar", "setOpaque String value");
|
||||
}
|
||||
|
||||
vh.set(array, i, "foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "bar", "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, "foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "bar", "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeVolatile(array, i, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeVolatile String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeVolatile(array, i, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeAcquire(array, i, "foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeAcquire(array, i, "foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeRelease(array, i, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) vh.compareAndExchangeRelease(array, i, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSet String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "bar", "weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, "bar", "foo");
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSetRelease String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "bar", "weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) vh.getAndSet(array, i, "foo");
|
||||
assertEquals(o, "bar", "getAndSet String");
|
||||
String x = (String) vh.get(array, i);
|
||||
assertEquals(x, "foo", "getAndSet String value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(VarHandle vh) {
|
||||
String[] array = new String[10];
|
||||
|
||||
int i = 0;
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.getAndAdd(array, i, "foo");
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
String o = (String) vh.addAndGet(array, i, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
|
||||
String[] array = new String[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String x = (String) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String x = (String) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String x = (String) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String x = (String) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, "foo", "bar");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String r = (String) vh.compareAndExchangeVolatile(array, ci, "bar", "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String r = (String) vh.compareAndExchangeAcquire(array, ci, "bar", "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String r = (String) vh.compareAndExchangeRelease(array, ci, "bar", "foo");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, "foo", "bar");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, "foo", "bar");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, "foo", "bar");
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
String o = (String) vh.getAndSet(array, ci, "foo");
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsChar
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsChar
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest {
|
||||
static final int SIZE = Character.BYTES;
|
||||
|
||||
static final char VALUE_1 = (char)0x0102;
|
||||
|
||||
static final char VALUE_2 = (char)0x1112;
|
||||
|
||||
static final char VALUE_3 = (char)0x2122;
|
||||
|
||||
|
||||
@Override
|
||||
public void setupVarHandleSources() {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(char[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(char[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(vh.varType(), char.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (ByteArrayViewSource<?> bav : bavss) {
|
||||
for (VarHandleSource vh : vhss) {
|
||||
if (vh.matches(bav)) {
|
||||
if (bav instanceof ByteArraySource) {
|
||||
ByteArraySource bas = (ByteArraySource) bav;
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bas, h),
|
||||
true));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
|
||||
false));
|
||||
}
|
||||
else {
|
||||
ByteBufferSource bbs = (ByteBufferSource) bav;
|
||||
|
||||
if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bbs, h),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read only", bav, vh, h -> testArrayReadOnly(bbs, h),
|
||||
true));
|
||||
}
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
int ci = 1;
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
int ci = 0;
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.get(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
char x = (char) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
char x = (char) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
char x = (char) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
char x = (char) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
char x = (char) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
char x = (char) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
char x = (char) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
char x = (char) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get char value");
|
||||
}
|
||||
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
char x = (char) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
char x = (char) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
char x = (char) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque char value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
char x = (char) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get char value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
char x = (char) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
char x = (char) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
char x = (char) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque char value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(SIZE);
|
||||
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
bs.fill(bb.putChar(0, VALUE_2).array());
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
char v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
|
||||
? rotateLeft(VALUE_2, (i % SIZE) << 3)
|
||||
: rotateRight(VALUE_2, (i % SIZE) << 3);
|
||||
// Plain
|
||||
{
|
||||
char x = (char) vh.get(array, i);
|
||||
assertEquals(x, v, "get char value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
char x = (char) vh.getVolatile(array, i);
|
||||
assertEquals(x, v, "getVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
char x = (char) vh.getAcquire(array, i);
|
||||
assertEquals(x, v, "getRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
char x = (char) vh.getOpaque(array, i);
|
||||
assertEquals(x, v, "getOpaque char value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,892 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsDouble
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsDouble
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
|
||||
static final int SIZE = Double.BYTES;
|
||||
|
||||
static final double VALUE_1 = 0x0102030405060708L;
|
||||
|
||||
static final double VALUE_2 = 0x1112131415161718L;
|
||||
|
||||
static final double VALUE_3 = 0x2122232425262728L;
|
||||
|
||||
|
||||
@Override
|
||||
public void setupVarHandleSources() {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(double[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(double[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(vh.varType(), double.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (ByteArrayViewSource<?> bav : bavss) {
|
||||
for (VarHandleSource vh : vhss) {
|
||||
if (vh.matches(bav)) {
|
||||
if (bav instanceof ByteArraySource) {
|
||||
ByteArraySource bas = (ByteArraySource) bav;
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bas, h),
|
||||
true));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
|
||||
false));
|
||||
}
|
||||
else {
|
||||
ByteBufferSource bbs = (ByteBufferSource) bav;
|
||||
|
||||
if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bbs, h),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read only", bav, vh, h -> testArrayReadOnly(bbs, h),
|
||||
true));
|
||||
}
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
int ci = 1;
|
||||
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
int ci = 0;
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
double o = (double) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
double o = (double) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double o = (double) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.get(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double x = (double) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
double o = (double) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
double x = (double) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double x = (double) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double x = (double) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double o = (double) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
double x = (double) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double x = (double) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double x = (double) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
double o = (double) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get double value");
|
||||
}
|
||||
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
double x = (double) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
double x = (double) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
double x = (double) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque double value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
double o = (double) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet double value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get double value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
double x = (double) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
double x = (double) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
double x = (double) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque double value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
double o = (double) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet double");
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet double value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(SIZE);
|
||||
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
bs.fill(bb.putDouble(0, VALUE_2).array());
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
double v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
|
||||
? rotateLeft(VALUE_2, (i % SIZE) << 3)
|
||||
: rotateRight(VALUE_2, (i % SIZE) << 3);
|
||||
// Plain
|
||||
{
|
||||
double x = (double) vh.get(array, i);
|
||||
assertEquals(x, v, "get double value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
double x = (double) vh.getVolatile(array, i);
|
||||
assertEquals(x, v, "getVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
double x = (double) vh.getAcquire(array, i);
|
||||
assertEquals(x, v, "getRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
double x = (double) vh.getOpaque(array, i);
|
||||
assertEquals(x, v, "getOpaque double value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,892 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsFloat
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsFloat
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
|
||||
static final int SIZE = Float.BYTES;
|
||||
|
||||
static final float VALUE_1 = 0x01020304;
|
||||
|
||||
static final float VALUE_2 = 0x11121314;
|
||||
|
||||
static final float VALUE_3 = 0x21222324;
|
||||
|
||||
|
||||
@Override
|
||||
public void setupVarHandleSources() {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(float[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(float[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(vh.varType(), float.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (ByteArrayViewSource<?> bav : bavss) {
|
||||
for (VarHandleSource vh : vhss) {
|
||||
if (vh.matches(bav)) {
|
||||
if (bav instanceof ByteArraySource) {
|
||||
ByteArraySource bas = (ByteArraySource) bav;
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bas, h),
|
||||
true));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
|
||||
false));
|
||||
}
|
||||
else {
|
||||
ByteBufferSource bbs = (ByteBufferSource) bav;
|
||||
|
||||
if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bbs, h),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read only", bav, vh, h -> testArrayReadOnly(bbs, h),
|
||||
true));
|
||||
}
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
int ci = 1;
|
||||
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
int ci = 0;
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
float o = (float) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
float o = (float) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float o = (float) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.get(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float x = (float) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
float o = (float) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
float x = (float) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float x = (float) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float x = (float) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float o = (float) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
float x = (float) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float x = (float) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float x = (float) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
float o = (float) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get float value");
|
||||
}
|
||||
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
float x = (float) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
float x = (float) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
float x = (float) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque float value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
float o = (float) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet float value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get float value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
float x = (float) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
float x = (float) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
float x = (float) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque float value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
float o = (float) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet float");
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet float value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(SIZE);
|
||||
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
bs.fill(bb.putFloat(0, VALUE_2).array());
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
float v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
|
||||
? rotateLeft(VALUE_2, (i % SIZE) << 3)
|
||||
: rotateRight(VALUE_2, (i % SIZE) << 3);
|
||||
// Plain
|
||||
{
|
||||
float x = (float) vh.get(array, i);
|
||||
assertEquals(x, v, "get float value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
float x = (float) vh.getVolatile(array, i);
|
||||
assertEquals(x, v, "getVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
float x = (float) vh.getAcquire(array, i);
|
||||
assertEquals(x, v, "getRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
float x = (float) vh.getOpaque(array, i);
|
||||
assertEquals(x, v, "getOpaque float value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,924 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsInt
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsInt
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
|
||||
static final int SIZE = Integer.BYTES;
|
||||
|
||||
static final int VALUE_1 = 0x01020304;
|
||||
|
||||
static final int VALUE_2 = 0x11121314;
|
||||
|
||||
static final int VALUE_3 = 0x21222324;
|
||||
|
||||
|
||||
@Override
|
||||
public void setupVarHandleSources() {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(int[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(int[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(vh.varType(), int.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (ByteArrayViewSource<?> bav : bavss) {
|
||||
for (VarHandleSource vh : vhss) {
|
||||
if (vh.matches(bav)) {
|
||||
if (bav instanceof ByteArraySource) {
|
||||
ByteArraySource bas = (ByteArraySource) bav;
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bas, h),
|
||||
true));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
|
||||
false));
|
||||
}
|
||||
else {
|
||||
ByteBufferSource bbs = (ByteBufferSource) bav;
|
||||
|
||||
if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bbs, h),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read only", bav, vh, h -> testArrayReadOnly(bbs, h),
|
||||
true));
|
||||
}
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
int ci = 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
int ci = 0;
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
int o = (int) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
int o = (int) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.get(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int x = (int) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
int o = (int) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
int x = (int) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int x = (int) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int x = (int) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int o = (int) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int o = (int) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
int x = (int) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int x = (int) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int x = (int) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int o = (int) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
int o = (int) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get int value");
|
||||
}
|
||||
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
int x = (int) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
int x = (int) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
int x = (int) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque int value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet int value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) vh.getAndAdd(array, i, VALUE_3);
|
||||
assertEquals(o, VALUE_1, "getAndAdd int");
|
||||
int c = (int) vh.addAndGet(array, i, VALUE_3);
|
||||
assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get int value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
int x = (int) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
int x = (int) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
int x = (int) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque int value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet int");
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet int value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) vh.getAndAdd(array, i, VALUE_3);
|
||||
assertEquals(o, VALUE_1, "getAndAdd int");
|
||||
int c = (int) vh.addAndGet(array, i, VALUE_3);
|
||||
assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(SIZE);
|
||||
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
bs.fill(bb.putInt(0, VALUE_2).array());
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
int v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
|
||||
? rotateLeft(VALUE_2, (i % SIZE) << 3)
|
||||
: rotateRight(VALUE_2, (i % SIZE) << 3);
|
||||
// Plain
|
||||
{
|
||||
int x = (int) vh.get(array, i);
|
||||
assertEquals(x, v, "get int value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
int x = (int) vh.getVolatile(array, i);
|
||||
assertEquals(x, v, "getVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
int x = (int) vh.getAcquire(array, i);
|
||||
assertEquals(x, v, "getRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
int x = (int) vh.getOpaque(array, i);
|
||||
assertEquals(x, v, "getOpaque int value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,924 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsLong
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsLong
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
|
||||
static final int SIZE = Long.BYTES;
|
||||
|
||||
static final long VALUE_1 = 0x0102030405060708L;
|
||||
|
||||
static final long VALUE_2 = 0x1112131415161718L;
|
||||
|
||||
static final long VALUE_3 = 0x2122232425262728L;
|
||||
|
||||
|
||||
@Override
|
||||
public void setupVarHandleSources() {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(long[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(long[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(vh.varType(), long.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (ByteArrayViewSource<?> bav : bavss) {
|
||||
for (VarHandleSource vh : vhss) {
|
||||
if (vh.matches(bav)) {
|
||||
if (bav instanceof ByteArraySource) {
|
||||
ByteArraySource bas = (ByteArraySource) bav;
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bas, h),
|
||||
true));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
|
||||
false));
|
||||
}
|
||||
else {
|
||||
ByteBufferSource bbs = (ByteBufferSource) bav;
|
||||
|
||||
if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bbs, h),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read only", bav, vh, h -> testArrayReadOnly(bbs, h),
|
||||
true));
|
||||
}
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
int ci = 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
int ci = 0;
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
long o = (long) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
long o = (long) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.get(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long x = (long) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
long o = (long) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
long x = (long) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long x = (long) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long x = (long) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long o = (long) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long o = (long) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
long x = (long) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long x = (long) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long x = (long) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long o = (long) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
long o = (long) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get long value");
|
||||
}
|
||||
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
long x = (long) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
long x = (long) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
long x = (long) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque long value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet long value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) vh.getAndAdd(array, i, VALUE_3);
|
||||
assertEquals(o, VALUE_1, "getAndAdd long");
|
||||
long c = (long) vh.addAndGet(array, i, VALUE_3);
|
||||
assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get long value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
long x = (long) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
long x = (long) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
long x = (long) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque long value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
|
||||
assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
|
||||
assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) vh.getAndSet(array, i, VALUE_1);
|
||||
assertEquals(o, VALUE_2, "getAndSet long");
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "getAndSet long value");
|
||||
}
|
||||
|
||||
vh.set(array, i, VALUE_1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) vh.getAndAdd(array, i, VALUE_3);
|
||||
assertEquals(o, VALUE_1, "getAndAdd long");
|
||||
long c = (long) vh.addAndGet(array, i, VALUE_3);
|
||||
assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(SIZE);
|
||||
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
bs.fill(bb.putLong(0, VALUE_2).array());
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
long v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
|
||||
? rotateLeft(VALUE_2, (i % SIZE) << 3)
|
||||
: rotateRight(VALUE_2, (i % SIZE) << 3);
|
||||
// Plain
|
||||
{
|
||||
long x = (long) vh.get(array, i);
|
||||
assertEquals(x, v, "get long value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
long x = (long) vh.getVolatile(array, i);
|
||||
assertEquals(x, v, "getVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
long x = (long) vh.getAcquire(array, i);
|
||||
assertEquals(x, v, "getRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
long x = (long) vh.getOpaque(array, i);
|
||||
assertEquals(x, v, "getOpaque long value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestByteArrayAsShort
|
||||
* @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestByteArrayAsShort
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest {
|
||||
static final int SIZE = Short.BYTES;
|
||||
|
||||
static final short VALUE_1 = (short)0x0102;
|
||||
|
||||
static final short VALUE_2 = (short)0x1112;
|
||||
|
||||
static final short VALUE_3 = (short)0x2122;
|
||||
|
||||
|
||||
@Override
|
||||
public void setupVarHandleSources() {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(short[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(short[].class,
|
||||
endianess == MemoryMode.BIG_ENDIAN),
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
|
||||
}
|
||||
|
||||
@Test(dataProvider = "typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(vh.varType(), short.class);
|
||||
|
||||
assertEquals(vh.coordinateTypes(), pts);
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (ByteArrayViewSource<?> bav : bavss) {
|
||||
for (VarHandleSource vh : vhss) {
|
||||
if (vh.matches(bav)) {
|
||||
if (bav instanceof ByteArraySource) {
|
||||
ByteArraySource bas = (ByteArraySource) bav;
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bas, h),
|
||||
true));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
|
||||
false));
|
||||
}
|
||||
else {
|
||||
ByteBufferSource bbs = (ByteBufferSource) bav;
|
||||
|
||||
if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read write", bav, vh, h -> testArrayReadWrite(bbs, h),
|
||||
true));
|
||||
}
|
||||
else {
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"read only", bav, vh, h -> testArrayReadOnly(bbs, h),
|
||||
true));
|
||||
}
|
||||
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
|
||||
false));
|
||||
cases.add(new VarHandleSourceAccessTestCase(
|
||||
"misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
int ci = 1;
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
int ci = 0;
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
if (readOnly) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndSet(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.addAndGet(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.get(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
short x = (short) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkIOOBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkIOOBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
short x = (short) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
short x = (short) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
short x = (short) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
final int ci = i;
|
||||
|
||||
if (!iAligned) {
|
||||
checkISE(() -> {
|
||||
short x = (short) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
short x = (short) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
short x = (short) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
if (!readOnly) {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = bs.s;
|
||||
|
||||
int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
short x = (short) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get short value");
|
||||
}
|
||||
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
short x = (short) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
short x = (short) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
short x = (short) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque short value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
short x = (short) vh.get(array, i);
|
||||
assertEquals(x, VALUE_1, "get short value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
short x = (short) vh.getVolatile(array, i);
|
||||
assertEquals(x, VALUE_2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
short x = (short) vh.getAcquire(array, i);
|
||||
assertEquals(x, VALUE_1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
short x = (short) vh.getOpaque(array, i);
|
||||
assertEquals(x, VALUE_2, "setOpaque short value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
int misalignmentAtZero = array.alignmentOffset(0, SIZE);
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(SIZE);
|
||||
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
|
||||
bs.fill(bb.putShort(0, VALUE_2).array());
|
||||
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
|
||||
|
||||
short v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
|
||||
? rotateLeft(VALUE_2, (i % SIZE) << 3)
|
||||
: rotateRight(VALUE_2, (i % SIZE) << 3);
|
||||
// Plain
|
||||
{
|
||||
short x = (short) vh.get(array, i);
|
||||
assertEquals(x, v, "get short value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
short x = (short) vh.getVolatile(array, i);
|
||||
assertEquals(x, v, "getVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
short x = (short) vh.getAcquire(array, i);
|
||||
assertEquals(x, v, "getRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
short x = (short) vh.getOpaque(array, i);
|
||||
assertEquals(x, v, "getOpaque short value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessBoolean
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessBoolean extends VarHandleBaseTest {
|
||||
static final boolean static_final_v = true;
|
||||
|
||||
static boolean static_v;
|
||||
|
||||
final boolean final_v = true;
|
||||
|
||||
boolean v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessBoolean.class, "final_v", boolean.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessBoolean.class, "v", boolean.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessBoolean.class, "static_final_v", boolean.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessBoolean.class, "static_v", boolean.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessBoolean::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessBoolean::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, true);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, true, "set boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, false);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, false, "setVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, true);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, true, "setRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, false);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, false, "setOpaque boolean value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessBoolean recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, true, false);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, true, false);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, true);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(true);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, true, "set boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(false);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, false, "setVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(true);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, true, "setRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(false);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, false, "setOpaque boolean value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(true, false);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(true, false);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(true);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
boolean[] array = new boolean[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, true);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, true, "get boolean value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, false);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, false, "setVolatile boolean value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, true);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, true, "setRelease boolean value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, false);
|
||||
boolean x = (boolean) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, false, "setOpaque boolean value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
boolean[] array = new boolean[10];
|
||||
|
||||
final int i = 0;
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, true, false);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, true, false);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, true);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean o = (boolean) hs.get(am).invokeExact(array, i, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
boolean[] array = new boolean[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
boolean x = (boolean) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessByte
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessByte extends VarHandleBaseTest {
|
||||
static final byte static_final_v = (byte)1;
|
||||
|
||||
static byte static_v;
|
||||
|
||||
final byte final_v = (byte)1;
|
||||
|
||||
byte v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessByte.class, "final_v", byte.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessByte.class, "v", byte.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessByte.class, "static_final_v", byte.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessByte.class, "static_v", byte.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessByte::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessByte::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessByte::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessByte::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessByte::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, (byte)1);
|
||||
byte x = (byte) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, (byte)1, "set byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, (byte)2);
|
||||
byte x = (byte) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, (byte)2, "setVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, (byte)1);
|
||||
byte x = (byte) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, (byte)1, "setRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, (byte)2);
|
||||
byte x = (byte) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, (byte)2, "setOpaque byte value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessByte recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, (byte)1, (byte)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact(recv, (byte)1, (byte)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact(recv, (byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact(recv, (byte)1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact((byte)1);
|
||||
byte x = (byte) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, (byte)1, "set byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact((byte)2);
|
||||
byte x = (byte) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, (byte)2, "setVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact((byte)1);
|
||||
byte x = (byte) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, (byte)1, "setRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact((byte)2);
|
||||
byte x = (byte) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, (byte)2, "setOpaque byte value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact((byte)1, (byte)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact((byte)1, (byte)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact((byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact((byte)1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
byte[] array = new byte[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, (byte)1);
|
||||
byte x = (byte) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, (byte)1, "get byte value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, (byte)2);
|
||||
byte x = (byte) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, (byte)2, "setVolatile byte value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, (byte)1);
|
||||
byte x = (byte) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, (byte)1, "setRelease byte value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, (byte)2);
|
||||
byte x = (byte) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, (byte)2, "setOpaque byte value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
byte[] array = new byte[10];
|
||||
|
||||
final int i = 0;
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact(array, i, (byte)1, (byte)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
byte r = (byte) hs.get(am).invokeExact(array, i, (byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
byte o = (byte) hs.get(am).invokeExact(array, i, (byte)1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
byte[] array = new byte[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
byte x = (byte) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, (byte)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessChar
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessChar extends VarHandleBaseTest {
|
||||
static final char static_final_v = 'a';
|
||||
|
||||
static char static_v;
|
||||
|
||||
final char final_v = 'a';
|
||||
|
||||
char v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessChar.class, "final_v", char.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessChar.class, "v", char.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessChar.class, "static_final_v", char.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessChar.class, "static_v", char.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(char[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessChar::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessChar::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessChar::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessChar::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessChar::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 'a');
|
||||
char x = (char) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 'a', "set char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, 'b');
|
||||
char x = (char) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, 'b', "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, 'a');
|
||||
char x = (char) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, 'a', "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, 'b');
|
||||
char x = (char) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, 'b', "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessChar recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, 'a', 'b');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact(recv, 'a', 'b');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact(recv, 'a');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact(recv, 'a');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact('a');
|
||||
char x = (char) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 'a', "set char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact('b');
|
||||
char x = (char) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, 'b', "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact('a');
|
||||
char x = (char) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, 'a', "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact('b');
|
||||
char x = (char) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, 'b', "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact('a', 'b');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact('a', 'b');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact('a');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact('a');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
char[] array = new char[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 'a');
|
||||
char x = (char) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 'a', "get char value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 'b');
|
||||
char x = (char) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, 'b', "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, 'a');
|
||||
char x = (char) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, 'a', "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 'b');
|
||||
char x = (char) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, 'b', "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
char[] array = new char[10];
|
||||
|
||||
final int i = 0;
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, 'a', 'b');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact(array, i, 'a', 'b');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
char r = (char) hs.get(am).invokeExact(array, i, 'a');
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
char o = (char) hs.get(am).invokeExact(array, i, 'a');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
char[] array = new char[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
char x = (char) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 'a');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessDouble
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessDouble extends VarHandleBaseTest {
|
||||
static final double static_final_v = 1.0d;
|
||||
|
||||
static double static_v;
|
||||
|
||||
final double final_v = 1.0d;
|
||||
|
||||
double v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessDouble.class, "final_v", double.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessDouble.class, "v", double.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessDouble.class, "static_final_v", double.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessDouble.class, "static_v", double.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(double[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessDouble::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessDouble::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessDouble::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessDouble::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessDouble::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1.0d, "set double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, 2.0d, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, 1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, 1.0d, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, 2.0d, "setOpaque double value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, 1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(recv, 1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(recv, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(recv, 1.0d);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1.0d, "set double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, 2.0d, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, 1.0d, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, 2.0d, "setOpaque double value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(1.0d);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1.0d, "get double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, 2.0d, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, 1.0d, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, 2.0d, "setOpaque double value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
|
||||
final int i = 0;
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(array, i, 1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(array, i, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
double o = (double) hs.get(am).invokeExact(array, i, 1.0d);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
double x = (double) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessFloat
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessFloat extends VarHandleBaseTest {
|
||||
static final float static_final_v = 1.0f;
|
||||
|
||||
static float static_v;
|
||||
|
||||
final float final_v = 1.0f;
|
||||
|
||||
float v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessFloat.class, "final_v", float.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessFloat.class, "v", float.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessFloat.class, "static_final_v", float.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessFloat.class, "static_v", float.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(float[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessFloat::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessFloat::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessFloat::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessFloat::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessFloat::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1.0f, "set float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, 2.0f, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, 1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, 1.0f, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, 2.0f, "setOpaque float value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, 1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(recv, 1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(recv, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(recv, 1.0f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1.0f, "set float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, 2.0f, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, 1.0f, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, 2.0f, "setOpaque float value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(1.0f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1.0f, "get float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, 2.0f, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, 1.0f, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, 2.0f, "setOpaque float value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
|
||||
final int i = 0;
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(array, i, 1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(array, i, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
float o = (float) hs.get(am).invokeExact(array, i, 1.0f);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
float x = (float) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,573 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessInt
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest {
|
||||
static final int static_final_v = 1;
|
||||
|
||||
static int static_v;
|
||||
|
||||
final int final_v = 1;
|
||||
|
||||
int v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessInt.class, "final_v", int.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessInt.class, "v", int.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessInt.class, "static_final_v", int.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessInt.class, "static_v", int.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(int[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessInt::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessInt::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessInt::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessInt::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessInt::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1);
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "set int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2);
|
||||
int x = (int) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, 2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, 1);
|
||||
int x = (int) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, 1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2);
|
||||
int x = (int) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, 2, "setOpaque int value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1, 2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1, 3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1, 2);
|
||||
assertEquals(r, 1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1, 3);
|
||||
assertEquals(r, 2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, 2, 1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) hs.get(TestAccessMode.getAndSet).invokeExact(recv, 1);
|
||||
assertEquals(o, 2, "getAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1, "getAndSet int value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) hs.get(TestAccessMode.getAndAdd).invokeExact(recv, 3);
|
||||
assertEquals(o, 1, "getAndAdd int");
|
||||
int c = (int) hs.get(TestAccessMode.addAndGet).invokeExact(recv, 3);
|
||||
assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessInt recv, Handles hs) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(1);
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "set int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(2);
|
||||
int x = (int) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, 2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(1);
|
||||
int x = (int) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, 1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(2);
|
||||
int x = (int) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, 2, "setOpaque int value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1, 2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1, 3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1, 2);
|
||||
assertEquals(r, 1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1, 3);
|
||||
assertEquals(r, 2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(2, 1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) hs.get(TestAccessMode.getAndSet).invokeExact( 1);
|
||||
assertEquals(o, 2, "getAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1, "getAndSet int value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) hs.get(TestAccessMode.getAndAdd).invokeExact( 3);
|
||||
assertEquals(o, 1, "getAndAdd int");
|
||||
int c = (int) hs.get(TestAccessMode.addAndGet).invokeExact(3);
|
||||
assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
int[] array = new int[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1);
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "get int value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2);
|
||||
int x = (int) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, 2, "setVolatile int value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1);
|
||||
int x = (int) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, 1, "setRelease int value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2);
|
||||
int x = (int) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, 2, "setOpaque int value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1, 2);
|
||||
assertEquals(r, true, "success compareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2, "success compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1, 3);
|
||||
assertEquals(r, false, "failing compareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2, "failing compareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeVolatile int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "success compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeVolatile int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "failing compareAndExchangeVolatile int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1, 2);
|
||||
assertEquals(r, 1, "success compareAndExchangeAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2, "success compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1, 3);
|
||||
assertEquals(r, 2, "failing compareAndExchangeAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2, "failing compareAndExchangeAcquire int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2, 1);
|
||||
assertEquals(r, 2, "success compareAndExchangeRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "success compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
int r = (int) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2, 3);
|
||||
assertEquals(r, 1, "failing compareAndExchangeRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "failing compareAndExchangeRelease int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2, "weakCompareAndSet int value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, 2, 1);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "weakCompareAndSetAcquire int");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, 1, 2);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2, "weakCompareAndSetRelease int");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
int o = (int) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, 1);
|
||||
assertEquals(o, 2, "getAndSet int");
|
||||
int x = (int) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1, "getAndSet int value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
int o = (int) hs.get(TestAccessMode.getAndAdd).invokeExact(array, i, 3);
|
||||
assertEquals(o, 1, "getAndAdd int");
|
||||
int c = (int) hs.get(TestAccessMode.addAndGet).invokeExact(array, i, 3);
|
||||
assertEquals(c, 1 + 3 + 3, "getAndAdd int value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
int[] array = new int[10];
|
||||
|
||||
final int i = 0;
|
||||
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
int[] array = new int[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
int x = (int) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1, 2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkIOOBE(am, () -> {
|
||||
int r = (int) hs.get(am).invokeExact(array, ci, 2, 1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
int o = (int) hs.get(am).invokeExact(array, ci, 1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkIOOBE(am, () -> {
|
||||
int o = (int) hs.get(am).invokeExact(array, ci, 3);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,573 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessLong
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest {
|
||||
static final long static_final_v = 1L;
|
||||
|
||||
static long static_v;
|
||||
|
||||
final long final_v = 1L;
|
||||
|
||||
long v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessLong.class, "final_v", long.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessLong.class, "v", long.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessLong.class, "static_final_v", long.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessLong.class, "static_v", long.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(long[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessLong::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessLong::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessLong::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessLong::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessLong::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1L);
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "set long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, 2L);
|
||||
long x = (long) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, 2L, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, 1L);
|
||||
long x = (long) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, 1L, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, 2L);
|
||||
long x = (long) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, 2L, "setOpaque long value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1L);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1L, 2L);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2L, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, 1L, 3L);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2L, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeVolatile long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1L, 2L);
|
||||
assertEquals(r, 1L, "success compareAndExchangeAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, 1L, 3L);
|
||||
assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2L, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, 2L, 1L);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 2L, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) hs.get(TestAccessMode.getAndSet).invokeExact(recv, 1L);
|
||||
assertEquals(o, 2L, "getAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, 1L, "getAndSet long value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, 1L);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) hs.get(TestAccessMode.getAndAdd).invokeExact(recv, 3L);
|
||||
assertEquals(o, 1L, "getAndAdd long");
|
||||
long c = (long) hs.get(TestAccessMode.addAndGet).invokeExact(recv, 3L);
|
||||
assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessLong recv, Handles hs) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(1L);
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "set long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(2L);
|
||||
long x = (long) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, 2L, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(1L);
|
||||
long x = (long) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, 1L, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(2L);
|
||||
long x = (long) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, 2L, "setOpaque long value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(1L);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1L, 2L);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2L, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(1L, 3L);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2L, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeVolatile long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1L, 2L);
|
||||
assertEquals(r, 1L, "success compareAndExchangeAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(1L, 3L);
|
||||
assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2L, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(2L, 1L);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 2L, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) hs.get(TestAccessMode.getAndSet).invokeExact( 1L);
|
||||
assertEquals(o, 2L, "getAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, 1L, "getAndSet long value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(1L);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) hs.get(TestAccessMode.getAndAdd).invokeExact( 3L);
|
||||
assertEquals(o, 1L, "getAndAdd long");
|
||||
long c = (long) hs.get(TestAccessMode.addAndGet).invokeExact(3L);
|
||||
assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
long[] array = new long[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1L);
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "get long value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, 2L);
|
||||
long x = (long) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "setVolatile long value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, 1L);
|
||||
long x = (long) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "setRelease long value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, 2L);
|
||||
long x = (long) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "setOpaque long value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1L);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1L, 2L);
|
||||
assertEquals(r, true, "success compareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "success compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, 1L, 3L);
|
||||
assertEquals(r, false, "failing compareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "failing compareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeVolatile long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "success compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeVolatile long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeVolatile long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1L, 2L);
|
||||
assertEquals(r, 1L, "success compareAndExchangeAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "success compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, 1L, 3L);
|
||||
assertEquals(r, 2L, "failing compareAndExchangeAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "failing compareAndExchangeAcquire long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2L, 1L);
|
||||
assertEquals(r, 2L, "success compareAndExchangeRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "success compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
long r = (long) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, 2L, 3L);
|
||||
assertEquals(r, 1L, "failing compareAndExchangeRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "failing compareAndExchangeRelease long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "weakCompareAndSet long value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, 2L, 1L);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "weakCompareAndSetAcquire long");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, 1L, 2L);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 2L, "weakCompareAndSetRelease long");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
long o = (long) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, 1L);
|
||||
assertEquals(o, 2L, "getAndSet long");
|
||||
long x = (long) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, 1L, "getAndSet long value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, 1L);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
long o = (long) hs.get(TestAccessMode.getAndAdd).invokeExact(array, i, 3L);
|
||||
assertEquals(o, 1L, "getAndAdd long");
|
||||
long c = (long) hs.get(TestAccessMode.addAndGet).invokeExact(array, i, 3L);
|
||||
assertEquals(c, 1L + 3L + 3L, "getAndAdd long value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
long[] array = new long[10];
|
||||
|
||||
final int i = 0;
|
||||
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
long[] array = new long[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
long x = (long) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 1L);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1L, 2L);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkIOOBE(am, () -> {
|
||||
long r = (long) hs.get(am).invokeExact(array, ci, 2L, 1L);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
long o = (long) hs.get(am).invokeExact(array, ci, 1L);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkIOOBE(am, () -> {
|
||||
long o = (long) hs.get(am).invokeExact(array, ci, 3L);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessShort
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessShort extends VarHandleBaseTest {
|
||||
static final short static_final_v = (short)1;
|
||||
|
||||
static short static_v;
|
||||
|
||||
final short final_v = (short)1;
|
||||
|
||||
short v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessShort.class, "final_v", short.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessShort.class, "v", short.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessShort.class, "static_final_v", short.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessShort.class, "static_v", short.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(short[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessShort::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessShort::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessShort::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessShort::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessShort::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, (short)1);
|
||||
short x = (short) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, (short)1, "set short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, (short)2);
|
||||
short x = (short) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, (short)2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, (short)1);
|
||||
short x = (short) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, (short)1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, (short)2);
|
||||
short x = (short) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, (short)2, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessShort recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, (short)1, (short)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact(recv, (short)1, (short)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact(recv, (short)1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact(recv, (short)1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact((short)1);
|
||||
short x = (short) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, (short)1, "set short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact((short)2);
|
||||
short x = (short) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, (short)2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact((short)1);
|
||||
short x = (short) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, (short)1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact((short)2);
|
||||
short x = (short) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, (short)2, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact((short)1, (short)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact((short)1, (short)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact((short)1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact((short)1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
short[] array = new short[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, (short)1);
|
||||
short x = (short) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, (short)1, "get short value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, (short)2);
|
||||
short x = (short) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, (short)2, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, (short)1);
|
||||
short x = (short) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, (short)1, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, (short)2);
|
||||
short x = (short) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, (short)2, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
short[] array = new short[10];
|
||||
|
||||
final int i = 0;
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, (short)1, (short)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact(array, i, (short)1, (short)2);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
short r = (short) hs.get(am).invokeExact(array, i, (short)1);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
short o = (short) hs.get(am).invokeExact(array, i, (short)1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
short[] array = new short[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
short x = (short) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, (short)1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessString
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
|
||||
static final String static_final_v = "foo";
|
||||
|
||||
static String static_v;
|
||||
|
||||
final String final_v = "foo";
|
||||
|
||||
String v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessString.class, "final_v", String.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccessString.class, "v", String.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessString.class, "static_final_v", String.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccessString.class, "static_v", String.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(String[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessString::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessString::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccessString::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, "foo");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "set String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, "bar", "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, "foo");
|
||||
String x = (String) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, "foo", "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, "bar", "setOpaque String value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, "foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, "foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "bar", "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, "foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "bar", "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeVolatile String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, "foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, "foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "bar", "weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, "bar", "foo");
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "bar", "weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) hs.get(TestAccessMode.getAndSet).invokeExact(recv, "foo");
|
||||
assertEquals(o, "bar", "getAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, "foo", "getAndSet String value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
String r = (String) hs.get(am).invokeExact(recv, "foo");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact("foo");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "set String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact("bar");
|
||||
String x = (String) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, "bar", "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact("foo");
|
||||
String x = (String) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, "foo", "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact("bar");
|
||||
String x = (String) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, "bar", "setOpaque String value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact("foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact("foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "bar", "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact("foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "bar", "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact("bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeVolatile String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact("bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact("foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact("foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact("bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact("bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact("foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "bar", "weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact("bar", "foo");
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "bar", "weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) hs.get(TestAccessMode.getAndSet).invokeExact( "foo");
|
||||
assertEquals(o, "bar", "getAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, "foo", "getAndSet String value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
String r = (String) hs.get(am).invokeExact("foo");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
String[] array = new String[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, "foo");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "get String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, "foo");
|
||||
String x = (String) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "setOpaque String value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, "foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, "foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeVolatile String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "success compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeVolatile String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeVolatile String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, "foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, "foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, "bar", "foo");
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "bar", "weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, "foo");
|
||||
assertEquals(o, "bar", "getAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, "foo", "getAndSet String value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
String[] array = new String[10];
|
||||
|
||||
final int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
String o = (String) hs.get(am).invokeExact(array, i, "foo");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
String[] array = new String[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
String x = (String) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, "foo", "bar");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkIOOBE(am, () -> {
|
||||
String r = (String) hs.get(am).invokeExact(array, ci, "bar", "foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
String o = (String) hs.get(am).invokeExact(array, ci, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm VarHandleTestMethodTypeBoolean
|
||||
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeBoolean
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
|
||||
static final boolean static_final_v = true;
|
||||
|
||||
static boolean static_v = true;
|
||||
|
||||
final boolean final_v = true;
|
||||
|
||||
boolean v = true;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeBoolean.class, "final_v", boolean.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeBoolean.class, "v", boolean.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeBoolean.class, "static_final_v", boolean.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeBoolean.class, "static_v", boolean.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
|
||||
false));
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, f, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, f, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
|
||||
false));
|
||||
}
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv, VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
boolean x = (boolean) vh.get(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
boolean x = (boolean) vh.get(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
boolean x = (boolean) vh.get(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.get(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.get(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.set(null, true);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.set(Void.class, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(recv, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
boolean x = (boolean) vh.getVolatile(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
boolean x = (boolean) vh.getVolatile(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
boolean x = (boolean) vh.getVolatile(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getVolatile(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getVolatile(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setVolatile(null, true);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setVolatile(Void.class, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(recv, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
boolean x = (boolean) vh.getOpaque(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
boolean x = (boolean) vh.getOpaque(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
boolean x = (boolean) vh.getOpaque(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getOpaque(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getOpaque(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setOpaque(null, true);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setOpaque(Void.class, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(recv, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
boolean x = (boolean) vh.getAcquire(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
boolean x = (boolean) vh.getAcquire(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
boolean x = (boolean) vh.getAcquire(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getAcquire(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getAcquire(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setRelease(null, true);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setRelease(Void.class, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(recv, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class)).
|
||||
invoke(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
|
||||
invoke(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
hs.get(am, methodType(void.class, Void.class, boolean.class)).
|
||||
invoke(null, true);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
hs.get(am, methodType(void.class, Class.class, boolean.class)).
|
||||
invoke(Void.class, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, boolean.class)).
|
||||
invoke(0, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)).
|
||||
invoke(recv, true, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.get();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.get(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getVolatile(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getOpaque(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getAcquire(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
|
||||
int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) hs.get(am, methodType(int.class)).
|
||||
invoke();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) hs.get(am, methodType(Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, boolean.class, Class.class)).
|
||||
invoke(true, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
|
||||
boolean[] array = new boolean[10];
|
||||
Arrays.fill(array, true);
|
||||
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
boolean x = (boolean) vh.get(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
boolean x = (boolean) vh.get(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
boolean x = (boolean) vh.get(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
boolean x = (boolean) vh.get(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.get(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.get(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.set(null, 0, true);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.set(Void.class, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.set(array, Void.class, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(array, 0, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
boolean x = (boolean) vh.getVolatile(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
boolean x = (boolean) vh.getVolatile(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
boolean x = (boolean) vh.getVolatile(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
boolean x = (boolean) vh.getVolatile(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getVolatile(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getVolatile(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setVolatile(null, 0, true);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setVolatile(Void.class, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setVolatile(array, Void.class, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(array, 0, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
boolean x = (boolean) vh.getOpaque(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
boolean x = (boolean) vh.getOpaque(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
boolean x = (boolean) vh.getOpaque(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
boolean x = (boolean) vh.getOpaque(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getOpaque(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getOpaque(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setOpaque(null, 0, true);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setOpaque(Void.class, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setOpaque(array, Void.class, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(array, 0, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
boolean x = (boolean) vh.getAcquire(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
boolean x = (boolean) vh.getAcquire(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
boolean x = (boolean) vh.getAcquire(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
boolean x = (boolean) vh.getAcquire(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) vh.getAcquire(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) vh.getAcquire(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setRelease(null, 0, true);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setRelease(Void.class, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setRelease(array, Void.class, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(array, 0, true, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayWrongMethodType(Handles hs) throws Throwable {
|
||||
boolean[] array = new boolean[10];
|
||||
Arrays.fill(array, true);
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, Void.class, int.class)).
|
||||
invoke(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
|
||||
invoke(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
|
||||
invoke(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class)).
|
||||
invoke(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
hs.get(am, methodType(void.class, Void.class, int.class, boolean.class)).
|
||||
invoke(null, 0, true);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
hs.get(am, methodType(void.class, Class.class, int.class, boolean.class)).
|
||||
invoke(Void.class, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, int.class, boolean.class)).
|
||||
invoke(0, 0, true);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
hs.get(am, methodType(void.class, boolean[].class, Class.class, boolean.class)).
|
||||
invoke(array, Void.class, true);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
|
||||
invoke(array, 0, true, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm VarHandleTestMethodTypeByte
|
||||
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeByte
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
|
||||
static final byte static_final_v = (byte)1;
|
||||
|
||||
static byte static_v = (byte)1;
|
||||
|
||||
final byte final_v = (byte)1;
|
||||
|
||||
byte v = (byte)1;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeByte.class, "final_v", byte.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeByte.class, "v", byte.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeByte.class, "static_final_v", byte.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeByte.class, "static_v", byte.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
|
||||
false));
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, f, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, f, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
|
||||
false));
|
||||
}
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
byte x = (byte) vh.get(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
byte x = (byte) vh.get(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
byte x = (byte) vh.get(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.get(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.set(null, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.set(Void.class, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(recv, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
byte x = (byte) vh.getVolatile(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
byte x = (byte) vh.getVolatile(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
byte x = (byte) vh.getVolatile(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getVolatile(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setVolatile(null, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setVolatile(Void.class, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(recv, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
byte x = (byte) vh.getOpaque(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
byte x = (byte) vh.getOpaque(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
byte x = (byte) vh.getOpaque(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getOpaque(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setOpaque(null, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setOpaque(Void.class, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(recv, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
byte x = (byte) vh.getAcquire(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
byte x = (byte) vh.getAcquire(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
byte x = (byte) vh.getAcquire(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getAcquire(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setRelease(null, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setRelease(Void.class, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(recv, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, Void.class)).
|
||||
invoke(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, int.class)).
|
||||
invoke(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) hs.get(am, methodType(byte.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
hs.get(am, methodType(void.class, Void.class, byte.class)).
|
||||
invoke(null, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
hs.get(am, methodType(void.class, Class.class, byte.class)).
|
||||
invoke(Void.class, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, byte.class)).
|
||||
invoke(0, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)).
|
||||
invoke(recv, (byte)1, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.get(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set((byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getVolatile(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile((byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getOpaque(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque((byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getAcquire(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease((byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
|
||||
int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) hs.get(am, methodType(Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, byte.class, Class.class)).
|
||||
invoke((byte)1, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
|
||||
byte[] array = new byte[10];
|
||||
Arrays.fill(array, (byte)1);
|
||||
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
byte x = (byte) vh.get(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
byte x = (byte) vh.get(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
byte x = (byte) vh.get(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
byte x = (byte) vh.get(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.get(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.set(null, 0, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.set(Void.class, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.set(array, Void.class, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(array, 0, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
byte x = (byte) vh.getVolatile(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
byte x = (byte) vh.getVolatile(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
byte x = (byte) vh.getVolatile(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
byte x = (byte) vh.getVolatile(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getVolatile(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setVolatile(null, 0, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setVolatile(Void.class, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setVolatile(array, Void.class, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(array, 0, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
byte x = (byte) vh.getOpaque(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
byte x = (byte) vh.getOpaque(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
byte x = (byte) vh.getOpaque(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
byte x = (byte) vh.getOpaque(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getOpaque(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setOpaque(null, 0, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setOpaque(Void.class, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setOpaque(array, Void.class, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(array, 0, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
byte x = (byte) vh.getAcquire(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
byte x = (byte) vh.getAcquire(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
byte x = (byte) vh.getAcquire(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
byte x = (byte) vh.getAcquire(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) vh.getAcquire(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setRelease(null, 0, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setRelease(Void.class, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setRelease(array, Void.class, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(array, 0, (byte)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayWrongMethodType(Handles hs) throws Throwable {
|
||||
byte[] array = new byte[10];
|
||||
Arrays.fill(array, (byte)1);
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, Void.class, int.class)).
|
||||
invoke(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class)).
|
||||
invoke(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class)).
|
||||
invoke(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class)).
|
||||
invoke(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
byte x = (byte) hs.get(am, methodType(byte.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
hs.get(am, methodType(void.class, Void.class, int.class, byte.class)).
|
||||
invoke(null, 0, (byte)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
hs.get(am, methodType(void.class, Class.class, int.class, byte.class)).
|
||||
invoke(Void.class, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, int.class, byte.class)).
|
||||
invoke(0, 0, (byte)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
hs.get(am, methodType(void.class, byte[].class, Class.class, byte.class)).
|
||||
invoke(array, Void.class, (byte)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
|
||||
invoke(array, 0, (byte)1, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm VarHandleTestMethodTypeChar
|
||||
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeChar
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
|
||||
static final char static_final_v = 'a';
|
||||
|
||||
static char static_v = 'a';
|
||||
|
||||
final char final_v = 'a';
|
||||
|
||||
char v = 'a';
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeChar.class, "final_v", char.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeChar.class, "v", char.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeChar.class, "static_final_v", char.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeChar.class, "static_v", char.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(char[].class);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
|
||||
false));
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, f, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, f, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
|
||||
false));
|
||||
}
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
char x = (char) vh.get(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
char x = (char) vh.get(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
char x = (char) vh.get(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.get(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.set(null, 'a');
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.set(Void.class, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(recv, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
char x = (char) vh.getVolatile(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
char x = (char) vh.getVolatile(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
char x = (char) vh.getVolatile(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getVolatile(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setVolatile(null, 'a');
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setVolatile(Void.class, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(recv, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
char x = (char) vh.getOpaque(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
char x = (char) vh.getOpaque(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
char x = (char) vh.getOpaque(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getOpaque(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setOpaque(null, 'a');
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setOpaque(Void.class, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(recv, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
char x = (char) vh.getAcquire(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
char x = (char) vh.getAcquire(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
char x = (char) vh.getAcquire(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getAcquire(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setRelease(null, 'a');
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setRelease(Void.class, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(recv, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
char x = (char) hs.get(am, methodType(char.class, Void.class)).
|
||||
invoke(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
char x = (char) hs.get(am, methodType(char.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
char x = (char) hs.get(am, methodType(char.class, int.class)).
|
||||
invoke(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) hs.get(am, methodType(char.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
hs.get(am, methodType(void.class, Void.class, char.class)).
|
||||
invoke(null, 'a');
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
hs.get(am, methodType(void.class, Class.class, char.class)).
|
||||
invoke(Void.class, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, char.class)).
|
||||
invoke(0, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)).
|
||||
invoke(recv, 'a', Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.get(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set('a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getVolatile(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile('a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getOpaque(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque('a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getAcquire(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease('a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
|
||||
int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) hs.get(am, methodType(Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, char.class, Class.class)).
|
||||
invoke('a', Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
|
||||
char[] array = new char[10];
|
||||
Arrays.fill(array, 'a');
|
||||
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
char x = (char) vh.get(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
char x = (char) vh.get(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
char x = (char) vh.get(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
char x = (char) vh.get(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.get(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.set(null, 0, 'a');
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.set(Void.class, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.set(array, Void.class, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(array, 0, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
char x = (char) vh.getVolatile(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
char x = (char) vh.getVolatile(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
char x = (char) vh.getVolatile(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
char x = (char) vh.getVolatile(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getVolatile(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setVolatile(null, 0, 'a');
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setVolatile(Void.class, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setVolatile(array, Void.class, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(array, 0, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
char x = (char) vh.getOpaque(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
char x = (char) vh.getOpaque(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
char x = (char) vh.getOpaque(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
char x = (char) vh.getOpaque(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getOpaque(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setOpaque(null, 0, 'a');
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setOpaque(Void.class, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setOpaque(array, Void.class, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(array, 0, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
char x = (char) vh.getAcquire(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
char x = (char) vh.getAcquire(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
char x = (char) vh.getAcquire(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
char x = (char) vh.getAcquire(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) vh.getAcquire(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setRelease(null, 0, 'a');
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setRelease(Void.class, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setRelease(array, Void.class, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(array, 0, 'a', Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayWrongMethodType(Handles hs) throws Throwable {
|
||||
char[] array = new char[10];
|
||||
Arrays.fill(array, 'a');
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
char x = (char) hs.get(am, methodType(char.class, Void.class, int.class)).
|
||||
invoke(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
char x = (char) hs.get(am, methodType(char.class, Class.class, int.class)).
|
||||
invoke(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
char x = (char) hs.get(am, methodType(char.class, int.class, int.class)).
|
||||
invoke(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class)).
|
||||
invoke(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class, char[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
char x = (char) hs.get(am, methodType(char.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
hs.get(am, methodType(void.class, Void.class, int.class, char.class)).
|
||||
invoke(null, 0, 'a');
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
hs.get(am, methodType(void.class, Class.class, int.class, char.class)).
|
||||
invoke(Void.class, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, int.class, char.class)).
|
||||
invoke(0, 0, 'a');
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
hs.get(am, methodType(void.class, char[].class, Class.class, char.class)).
|
||||
invoke(array, Void.class, 'a');
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
|
||||
invoke(array, 0, 'a', Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm VarHandleTestMethodTypeDouble
|
||||
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeDouble
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
|
||||
static final double static_final_v = 1.0d;
|
||||
|
||||
static double static_v = 1.0d;
|
||||
|
||||
final double final_v = 1.0d;
|
||||
|
||||
double v = 1.0d;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeDouble.class, "final_v", double.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeDouble.class, "v", double.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeDouble.class, "static_final_v", double.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeDouble.class, "static_v", double.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(double[].class);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
|
||||
false));
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, f, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, f, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
|
||||
false));
|
||||
}
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
double x = (double) vh.get(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
double x = (double) vh.get(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
double x = (double) vh.get(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.get(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.set(null, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.set(Void.class, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(recv, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
double x = (double) vh.getVolatile(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
double x = (double) vh.getVolatile(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
double x = (double) vh.getVolatile(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getVolatile(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setVolatile(null, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setVolatile(Void.class, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(recv, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
double x = (double) vh.getOpaque(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
double x = (double) vh.getOpaque(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
double x = (double) vh.getOpaque(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getOpaque(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setOpaque(null, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setOpaque(Void.class, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(recv, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
double x = (double) vh.getAcquire(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
double x = (double) vh.getAcquire(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
double x = (double) vh.getAcquire(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getAcquire(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setRelease(null, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setRelease(Void.class, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(recv, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
double x = (double) hs.get(am, methodType(double.class, Void.class)).
|
||||
invoke(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
double x = (double) hs.get(am, methodType(double.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
double x = (double) hs.get(am, methodType(double.class, int.class)).
|
||||
invoke(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) hs.get(am, methodType(double.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
hs.get(am, methodType(void.class, Void.class, double.class)).
|
||||
invoke(null, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
hs.get(am, methodType(void.class, Class.class, double.class)).
|
||||
invoke(Void.class, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, double.class)).
|
||||
invoke(0, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)).
|
||||
invoke(recv, 1.0d, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.get(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getVolatile(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getOpaque(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getAcquire(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
|
||||
int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) hs.get(am, methodType(Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, double.class, Class.class)).
|
||||
invoke(1.0d, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
Arrays.fill(array, 1.0d);
|
||||
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
double x = (double) vh.get(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
double x = (double) vh.get(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
double x = (double) vh.get(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
double x = (double) vh.get(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.get(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.set(null, 0, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.set(Void.class, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.set(array, Void.class, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(array, 0, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
double x = (double) vh.getVolatile(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
double x = (double) vh.getVolatile(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
double x = (double) vh.getVolatile(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
double x = (double) vh.getVolatile(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getVolatile(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setVolatile(null, 0, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setVolatile(Void.class, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setVolatile(array, Void.class, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(array, 0, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
double x = (double) vh.getOpaque(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
double x = (double) vh.getOpaque(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
double x = (double) vh.getOpaque(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
double x = (double) vh.getOpaque(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getOpaque(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setOpaque(null, 0, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setOpaque(Void.class, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setOpaque(array, Void.class, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(array, 0, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
double x = (double) vh.getAcquire(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
double x = (double) vh.getAcquire(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
double x = (double) vh.getAcquire(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
double x = (double) vh.getAcquire(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) vh.getAcquire(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setRelease(null, 0, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setRelease(Void.class, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setRelease(array, Void.class, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(array, 0, 1.0d, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayWrongMethodType(Handles hs) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
Arrays.fill(array, 1.0d);
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
double x = (double) hs.get(am, methodType(double.class, Void.class, int.class)).
|
||||
invoke(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
double x = (double) hs.get(am, methodType(double.class, Class.class, int.class)).
|
||||
invoke(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
double x = (double) hs.get(am, methodType(double.class, int.class, int.class)).
|
||||
invoke(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class)).
|
||||
invoke(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class, double[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
double x = (double) hs.get(am, methodType(double.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
hs.get(am, methodType(void.class, Void.class, int.class, double.class)).
|
||||
invoke(null, 0, 1.0d);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
hs.get(am, methodType(void.class, Class.class, int.class, double.class)).
|
||||
invoke(Void.class, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, int.class, double.class)).
|
||||
invoke(0, 0, 1.0d);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
hs.get(am, methodType(void.class, double[].class, Class.class, double.class)).
|
||||
invoke(array, Void.class, 1.0d);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
|
||||
invoke(array, 0, 1.0d, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm VarHandleTestMethodTypeFloat
|
||||
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeFloat
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
|
||||
static final float static_final_v = 1.0f;
|
||||
|
||||
static float static_v = 1.0f;
|
||||
|
||||
final float final_v = 1.0f;
|
||||
|
||||
float v = 1.0f;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeFloat.class, "final_v", float.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeFloat.class, "v", float.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeFloat.class, "static_final_v", float.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeFloat.class, "static_v", float.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(float[].class);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
|
||||
false));
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, f, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, f, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
|
||||
false));
|
||||
}
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
float x = (float) vh.get(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
float x = (float) vh.get(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
float x = (float) vh.get(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.get(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.set(null, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.set(Void.class, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(recv, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
float x = (float) vh.getVolatile(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
float x = (float) vh.getVolatile(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
float x = (float) vh.getVolatile(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getVolatile(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setVolatile(null, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setVolatile(Void.class, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(recv, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
float x = (float) vh.getOpaque(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
float x = (float) vh.getOpaque(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
float x = (float) vh.getOpaque(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getOpaque(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setOpaque(null, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setOpaque(Void.class, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(recv, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
float x = (float) vh.getAcquire(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
float x = (float) vh.getAcquire(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
float x = (float) vh.getAcquire(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getAcquire(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setRelease(null, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setRelease(Void.class, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(recv, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
float x = (float) hs.get(am, methodType(float.class, Void.class)).
|
||||
invoke(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
float x = (float) hs.get(am, methodType(float.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
float x = (float) hs.get(am, methodType(float.class, int.class)).
|
||||
invoke(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) hs.get(am, methodType(float.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
hs.get(am, methodType(void.class, Void.class, float.class)).
|
||||
invoke(null, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
hs.get(am, methodType(void.class, Class.class, float.class)).
|
||||
invoke(Void.class, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, float.class)).
|
||||
invoke(0, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)).
|
||||
invoke(recv, 1.0f, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.get(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getVolatile(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getOpaque(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getAcquire(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
|
||||
int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) hs.get(am, methodType(Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, float.class, Class.class)).
|
||||
invoke(1.0f, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
Arrays.fill(array, 1.0f);
|
||||
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
float x = (float) vh.get(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
float x = (float) vh.get(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
float x = (float) vh.get(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
float x = (float) vh.get(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.get(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.set(null, 0, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.set(Void.class, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.set(array, Void.class, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(array, 0, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
float x = (float) vh.getVolatile(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
float x = (float) vh.getVolatile(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
float x = (float) vh.getVolatile(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
float x = (float) vh.getVolatile(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getVolatile(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setVolatile(null, 0, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setVolatile(Void.class, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setVolatile(array, Void.class, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(array, 0, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
float x = (float) vh.getOpaque(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
float x = (float) vh.getOpaque(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
float x = (float) vh.getOpaque(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
float x = (float) vh.getOpaque(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getOpaque(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setOpaque(null, 0, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setOpaque(Void.class, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setOpaque(array, Void.class, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(array, 0, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
float x = (float) vh.getAcquire(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
float x = (float) vh.getAcquire(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
float x = (float) vh.getAcquire(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
float x = (float) vh.getAcquire(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) vh.getAcquire(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setRelease(null, 0, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setRelease(Void.class, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setRelease(array, Void.class, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(array, 0, 1.0f, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayWrongMethodType(Handles hs) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
Arrays.fill(array, 1.0f);
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
float x = (float) hs.get(am, methodType(float.class, Void.class, int.class)).
|
||||
invoke(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
float x = (float) hs.get(am, methodType(float.class, Class.class, int.class)).
|
||||
invoke(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
float x = (float) hs.get(am, methodType(float.class, int.class, int.class)).
|
||||
invoke(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class)).
|
||||
invoke(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class, float[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
float x = (float) hs.get(am, methodType(float.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
hs.get(am, methodType(void.class, Void.class, int.class, float.class)).
|
||||
invoke(null, 0, 1.0f);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
hs.get(am, methodType(void.class, Class.class, int.class, float.class)).
|
||||
invoke(Void.class, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, int.class, float.class)).
|
||||
invoke(0, 0, 1.0f);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
hs.get(am, methodType(void.class, float[].class, Class.class, float.class)).
|
||||
invoke(array, Void.class, 1.0f);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
|
||||
invoke(array, 0, 1.0f, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
2075
jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
Normal file
2075
jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,856 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm VarHandleTestMethodTypeShort
|
||||
* @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeShort
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import static java.lang.invoke.MethodType.*;
|
||||
|
||||
public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
|
||||
static final short static_final_v = (short)1;
|
||||
|
||||
static short static_v = (short)1;
|
||||
|
||||
final short final_v = (short)1;
|
||||
|
||||
short v = (short)1;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeShort.class, "final_v", short.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodTypeShort.class, "v", short.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeShort.class, "static_final_v", short.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodTypeShort.class, "static_v", short.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle(short[].class);
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new VarHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
|
||||
false));
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field wrong method type",
|
||||
vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field wrong method type",
|
||||
vhStaticField, f, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array wrong method type",
|
||||
vhArray, f, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
|
||||
false));
|
||||
}
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
short x = (short) vh.get(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
short x = (short) vh.get(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
short x = (short) vh.get(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.get(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.set(null, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.set(Void.class, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(recv, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
short x = (short) vh.getVolatile(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
short x = (short) vh.getVolatile(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
short x = (short) vh.getVolatile(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getVolatile(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setVolatile(null, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setVolatile(Void.class, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(recv, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
short x = (short) vh.getOpaque(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
short x = (short) vh.getOpaque(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
short x = (short) vh.getOpaque(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getOpaque(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setOpaque(null, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setOpaque(Void.class, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(recv, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
short x = (short) vh.getAcquire(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
short x = (short) vh.getAcquire(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
short x = (short) vh.getAcquire(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getAcquire(recv, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
vh.setRelease(null, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
vh.setRelease(Void.class, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(recv, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, Handles hs) throws Throwable {
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
short x = (short) hs.get(am, methodType(short.class, Void.class)).
|
||||
invoke(null);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
short x = (short) hs.get(am, methodType(short.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
short x = (short) hs.get(am, methodType(short.class, int.class)).
|
||||
invoke(0);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class)).
|
||||
invoke(recv);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) hs.get(am, methodType(short.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null receiver
|
||||
hs.get(am, methodType(void.class, Void.class, short.class)).
|
||||
invoke(null, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // receiver reference class
|
||||
hs.get(am, methodType(void.class, Class.class, short.class)).
|
||||
invoke(Void.class, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, Class.class)).
|
||||
invoke(recv, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, short.class)).
|
||||
invoke(0, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)).
|
||||
invoke(recv, (short)1, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
|
||||
// Get
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.get(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set((short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getVolatile(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile((short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getOpaque(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque((short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getAcquire(Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease((short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
|
||||
int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class)).
|
||||
invoke();
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) hs.get(am, methodType(Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, Class.class)).
|
||||
invoke(Void.class);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, short.class, Class.class)).
|
||||
invoke((short)1, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
|
||||
short[] array = new short[10];
|
||||
Arrays.fill(array, (short)1);
|
||||
|
||||
// Get
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
short x = (short) vh.get(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
short x = (short) vh.get(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
short x = (short) vh.get(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
short x = (short) vh.get(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.get(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.get(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.get();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.get(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// Set
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.set(null, 0, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.set(Void.class, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.set(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.set(0, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.set(array, Void.class, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.set();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.set(array, 0, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
short x = (short) vh.getVolatile(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
short x = (short) vh.getVolatile(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
short x = (short) vh.getVolatile(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
short x = (short) vh.getVolatile(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getVolatile(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getVolatile(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.getVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getVolatile(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetVolatile
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setVolatile(null, 0, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setVolatile(Void.class, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setVolatile(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setVolatile(0, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setVolatile(array, Void.class, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setVolatile();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setVolatile(array, 0, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
short x = (short) vh.getOpaque(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
short x = (short) vh.getOpaque(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
short x = (short) vh.getOpaque(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
short x = (short) vh.getOpaque(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getOpaque(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getOpaque(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.getOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getOpaque(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetOpaque
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setOpaque(null, 0, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setOpaque(Void.class, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setOpaque(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setOpaque(0, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setOpaque(array, Void.class, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setOpaque();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setOpaque(array, 0, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// GetAcquire
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
short x = (short) vh.getAcquire(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
short x = (short) vh.getAcquire(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
short x = (short) vh.getAcquire(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
short x = (short) vh.getAcquire(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) vh.getAcquire(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) vh.getAcquire(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) vh.getAcquire();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) vh.getAcquire(array, 0, Void.class);
|
||||
});
|
||||
|
||||
|
||||
// SetRelease
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
vh.setRelease(null, 0, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
vh.setRelease(Void.class, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
vh.setRelease(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
vh.setRelease(0, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
vh.setRelease(array, Void.class, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
vh.setRelease();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
vh.setRelease(array, 0, (short)1, Void.class);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testArrayWrongMethodType(Handles hs) throws Throwable {
|
||||
short[] array = new short[10];
|
||||
Arrays.fill(array, (short)1);
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
short x = (short) hs.get(am, methodType(short.class, Void.class, int.class)).
|
||||
invoke(null, 0);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
short x = (short) hs.get(am, methodType(short.class, Class.class, int.class)).
|
||||
invoke(Void.class, 0);
|
||||
});
|
||||
checkWMTE(() -> { // array primitive class
|
||||
short x = (short) hs.get(am, methodType(short.class, int.class, int.class)).
|
||||
invoke(0, 0);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class)).
|
||||
invoke(array, Void.class);
|
||||
});
|
||||
// Incorrect return type
|
||||
checkWMTE(() -> { // reference class
|
||||
Void x = (Void) hs.get(am, methodType(Void.class, short[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
checkWMTE(() -> { // primitive class
|
||||
boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class)).
|
||||
invoke(array, 0);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
short x = (short) hs.get(am, methodType(short.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
// Incorrect argument types
|
||||
checkNPE(() -> { // null array
|
||||
hs.get(am, methodType(void.class, Void.class, int.class, short.class)).
|
||||
invoke(null, 0, (short)1);
|
||||
});
|
||||
checkCCE(() -> { // array reference class
|
||||
hs.get(am, methodType(void.class, Class.class, int.class, short.class)).
|
||||
invoke(Void.class, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // value reference class
|
||||
hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
|
||||
invoke(array, 0, Void.class);
|
||||
});
|
||||
checkWMTE(() -> { // receiver primitive class
|
||||
hs.get(am, methodType(void.class, int.class, int.class, short.class)).
|
||||
invoke(0, 0, (short)1);
|
||||
});
|
||||
checkWMTE(() -> { // index reference class
|
||||
hs.get(am, methodType(void.class, short[].class, Class.class, short.class)).
|
||||
invoke(array, Void.class, (short)1);
|
||||
});
|
||||
// Incorrect arity
|
||||
checkWMTE(() -> { // 0
|
||||
hs.get(am, methodType(void.class)).
|
||||
invoke();
|
||||
});
|
||||
checkWMTE(() -> { // >
|
||||
hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
|
||||
invoke(array, 0, (short)1, Void.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng VarHandleTestReflection
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class VarHandleTestReflection extends VarHandleBaseTest {
|
||||
String string;
|
||||
|
||||
@DataProvider
|
||||
public static Object[][] accessModesProvider() {
|
||||
return Stream.of(VarHandle.AccessMode.values()).
|
||||
map(am -> new Object[]{am}).
|
||||
toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
static VarHandle handle() throws Exception {
|
||||
return MethodHandles.lookup().
|
||||
findVarHandle(VarHandleTestReflection.class, "string", String.class);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
|
||||
public void methodInvocation(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a Method
|
||||
|
||||
Method vhm = VarHandle.class.getMethod(accessMode.name(), Object[].class);
|
||||
vhm.invoke(v, new Object[]{});
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = UnsupportedOperationException.class)
|
||||
public void methodHandleInvoke(VarHandle.AccessMode accessMode) throws Throwable {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a MethodHandle
|
||||
|
||||
MethodHandle mh = MethodHandles.lookup().unreflect(
|
||||
VarHandle.class.getMethod(accessMode.name(), Object[].class));
|
||||
// Use invoke to avoid WrongMethodTypeException for
|
||||
// non-signature-polymorphic return types
|
||||
Object o = (Object) mh.invoke(v, new Object[]{});
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
|
||||
public void methodInvocationFromMethodInfo(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a Method obtained from cracking
|
||||
// a MethodHandle
|
||||
|
||||
MethodHandle mh = MethodHandles.lookup().unreflect(
|
||||
VarHandle.class.getMethod(accessMode.name(), Object[].class));
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
Method im = info.reflectAs(Method.class, MethodHandles.lookup());
|
||||
im.invoke(v, new Object[]{});
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
|
||||
public void reflectAsFromVarHandleInvoker(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
MethodHandle mh = MethodHandles.varHandleInvoker(
|
||||
accessMode, v.accessModeType(accessMode));
|
||||
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
|
||||
info.reflectAs(Method.class, MethodHandles.lookup());
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
|
||||
public void reflectAsFromFindVirtual(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
MethodHandle mh = MethodHandles.publicLookup().findVirtual(
|
||||
VarHandle.class, accessMode.name(), v.accessModeType(accessMode));
|
||||
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
|
||||
info.reflectAs(Method.class, MethodHandles.lookup());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,667 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccess$Type$
|
||||
*/
|
||||
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest {
|
||||
static final $type$ static_final_v = $value1$;
|
||||
|
||||
static $type$ static_v;
|
||||
|
||||
final $type$ final_v = $value1$;
|
||||
|
||||
$type$ v;
|
||||
|
||||
VarHandle vhFinalField;
|
||||
|
||||
VarHandle vhField;
|
||||
|
||||
VarHandle vhStaticField;
|
||||
|
||||
VarHandle vhStaticFinalField;
|
||||
|
||||
VarHandle vhArray;
|
||||
|
||||
@BeforeClass
|
||||
public void setup() throws Exception {
|
||||
vhFinalField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccess$Type$.class, "final_v", $type$.class);
|
||||
|
||||
vhField = MethodHandles.lookup().findVarHandle(
|
||||
VarHandleTestMethodHandleAccess$Type$.class, "v", $type$.class);
|
||||
|
||||
vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccess$Type$.class, "static_final_v", $type$.class);
|
||||
|
||||
vhStaticField = MethodHandles.lookup().findStaticVarHandle(
|
||||
VarHandleTestMethodHandleAccess$Type$.class, "static_v", $type$.class);
|
||||
|
||||
vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider
|
||||
public Object[][] accessTestCaseProvider() throws Exception {
|
||||
List<AccessTestCase<?>> cases = new ArrayList<>();
|
||||
|
||||
for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field",
|
||||
vhField, f, hs -> testInstanceField(this, hs)));
|
||||
cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
|
||||
vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Static field",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticField));
|
||||
cases.add(new MethodHandleAccessTestCase("Static field unsupported",
|
||||
vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticFieldUnsupported,
|
||||
false));
|
||||
|
||||
cases.add(new MethodHandleAccessTestCase("Array",
|
||||
vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArray));
|
||||
cases.add(new MethodHandleAccessTestCase("Array unsupported",
|
||||
vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayUnsupported,
|
||||
false));
|
||||
cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
|
||||
vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayIndexOutOfBounds,
|
||||
false));
|
||||
}
|
||||
|
||||
// Work around issue with jtreg summary reporting which truncates
|
||||
// the String result of Object.toString to 30 characters, hence
|
||||
// the first dummy argument
|
||||
return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "accessTestCaseProvider")
|
||||
public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
|
||||
T t = atc.get();
|
||||
int iters = atc.requiresLoop() ? ITERS : 1;
|
||||
for (int c = 0; c < iters; c++) {
|
||||
atc.testAccess(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testInstanceField(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, $value1$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "set $type$ value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(recv, $value2$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getVolatile).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "setVolatile $type$ value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(recv, $value1$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getAcquire).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "setRelease $type$ value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(recv, $value2$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getOpaque).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "setOpaque $type$ value");
|
||||
}
|
||||
|
||||
#if[CAS]
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, $value1$);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, $value1$, $value2$);
|
||||
assertEquals(r, true, "success compareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "success compareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(recv, $value1$, $value3$);
|
||||
assertEquals(r, false, "failing compareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "failing compareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, $value2$, $value1$);
|
||||
assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(recv, $value2$, $value3$);
|
||||
assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, $value1$, $value2$);
|
||||
assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(recv, $value1$, $value3$);
|
||||
assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, $value2$, $value1$);
|
||||
assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(recv, $value2$, $value3$);
|
||||
assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(recv, $value1$, $value2$);
|
||||
assertEquals(r, true, "weakCompareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(recv, $value2$, $value1$);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(recv, $value1$, $value2$);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
$type$ o = ($type$) hs.get(TestAccessMode.getAndSet).invokeExact(recv, $value1$);
|
||||
assertEquals(o, $value2$, "getAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(recv);
|
||||
assertEquals(x, $value1$, "getAndSet $type$ value");
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[AtomicAdd]
|
||||
hs.get(TestAccessMode.set).invokeExact(recv, $value1$);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
$type$ o = ($type$) hs.get(TestAccessMode.getAndAdd).invokeExact(recv, $value3$);
|
||||
assertEquals(o, $value1$, "getAndAdd $type$");
|
||||
$type$ c = ($type$) hs.get(TestAccessMode.addAndGet).invokeExact(recv, $value3$);
|
||||
assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable {
|
||||
#if[!CAS]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(recv, $value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
|
||||
});
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[!AtomicAdd]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
|
||||
});
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static void testStaticField(Handles hs) throws Throwable {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact($value1$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "set $type$ value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact($value2$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getVolatile).invokeExact();
|
||||
assertEquals(x, $value2$, "setVolatile $type$ value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact($value1$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getAcquire).invokeExact();
|
||||
assertEquals(x, $value1$, "setRelease $type$ value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact($value2$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getOpaque).invokeExact();
|
||||
assertEquals(x, $value2$, "setOpaque $type$ value");
|
||||
}
|
||||
|
||||
#if[CAS]
|
||||
hs.get(TestAccessMode.set).invokeExact($value1$);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact($value1$, $value2$);
|
||||
assertEquals(r, true, "success compareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value2$, "success compareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact($value1$, $value3$);
|
||||
assertEquals(r, false, "failing compareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value2$, "failing compareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact($value2$, $value1$);
|
||||
assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact($value2$, $value3$);
|
||||
assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact($value1$, $value2$);
|
||||
assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact($value1$, $value3$);
|
||||
assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact($value2$, $value1$);
|
||||
assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact($value2$, $value3$);
|
||||
assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact($value1$, $value2$);
|
||||
assertEquals(r, true, "weakCompareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact($value2$, $value1$);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact( $value1$, $value2$);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
$type$ o = ($type$) hs.get(TestAccessMode.getAndSet).invokeExact( $value1$);
|
||||
assertEquals(o, $value2$, "getAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact();
|
||||
assertEquals(x, $value1$, "getAndSet $type$ value");
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[AtomicAdd]
|
||||
hs.get(TestAccessMode.set).invokeExact($value1$);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
$type$ o = ($type$) hs.get(TestAccessMode.getAndAdd).invokeExact( $value3$);
|
||||
assertEquals(o, $value1$, "getAndAdd $type$");
|
||||
$type$ c = ($type$) hs.get(TestAccessMode.addAndGet).invokeExact($value3$);
|
||||
assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
#if[!CAS]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact($value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact($value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact($value1$);
|
||||
});
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[!AtomicAdd]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact($value1$);
|
||||
});
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
|
||||
static void testArray(Handles hs) throws Throwable {
|
||||
$type$[] array = new $type$[10];
|
||||
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
// Plain
|
||||
{
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, $value1$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "get $type$ value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.setVolatile).invokeExact(array, i, $value2$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getVolatile).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "setVolatile $type$ value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.setRelease).invokeExact(array, i, $value1$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getAcquire).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "setRelease $type$ value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.setOpaque).invokeExact(array, i, $value2$);
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.getOpaque).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "setOpaque $type$ value");
|
||||
}
|
||||
|
||||
#if[CAS]
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, $value1$);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, $value1$, $value2$);
|
||||
assertEquals(r, true, "success compareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "success compareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.compareAndSet).invokeExact(array, i, $value1$, $value3$);
|
||||
assertEquals(r, false, "failing compareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "failing compareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, $value2$, $value1$);
|
||||
assertEquals(r, $value2$, "success compareAndExchangeVolatile $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "success compareAndExchangeVolatile $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeVolatile).invokeExact(array, i, $value2$, $value3$);
|
||||
assertEquals(r, $value1$, "failing compareAndExchangeVolatile $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "failing compareAndExchangeVolatile $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, $value1$, $value2$);
|
||||
assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeAcquire).invokeExact(array, i, $value1$, $value3$);
|
||||
assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, $value2$, $value1$);
|
||||
assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
$type$ r = ($type$) hs.get(TestAccessMode.compareAndExchangeRelease).invokeExact(array, i, $value2$, $value3$);
|
||||
assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSet).invokeExact(array, i, $value1$, $value2$);
|
||||
assertEquals(r, true, "weakCompareAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "weakCompareAndSet $type$ value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetAcquire).invokeExact(array, i, $value2$, $value1$);
|
||||
assertEquals(r, true, "weakCompareAndSetAcquire $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.weakCompareAndSetRelease).invokeExact(array, i, $value1$, $value2$);
|
||||
assertEquals(r, true, "weakCompareAndSetRelease $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
$type$ o = ($type$) hs.get(TestAccessMode.getAndSet).invokeExact(array, i, $value1$);
|
||||
assertEquals(o, $value2$, "getAndSet $type$");
|
||||
$type$ x = ($type$) hs.get(TestAccessMode.get).invokeExact(array, i);
|
||||
assertEquals(x, $value1$, "getAndSet $type$ value");
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[AtomicAdd]
|
||||
hs.get(TestAccessMode.set).invokeExact(array, i, $value1$);
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
$type$ o = ($type$) hs.get(TestAccessMode.getAndAdd).invokeExact(array, i, $value3$);
|
||||
assertEquals(o, $value1$, "getAndAdd $type$");
|
||||
$type$ c = ($type$) hs.get(TestAccessMode.addAndGet).invokeExact(array, i, $value3$);
|
||||
assertEquals(c, $value1$ + $value3$ + $value3$, "getAndAdd $type$ value");
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
$type$[] array = new $type$[10];
|
||||
|
||||
final int i = 0;
|
||||
#if[!CAS]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, i, $value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$);
|
||||
});
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[!AtomicAdd]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkUOE(am, () -> {
|
||||
$type$ o = ($type$) hs.get(am).invokeExact(array, i, $value1$);
|
||||
});
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
|
||||
static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
|
||||
$type$[] array = new $type$[10];
|
||||
|
||||
for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
|
||||
final int ci = i;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.get)) {
|
||||
checkIOOBE(am, () -> {
|
||||
$type$ x = ($type$) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.set)) {
|
||||
checkIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, $value1$);
|
||||
});
|
||||
}
|
||||
|
||||
#if[CAS]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, $value1$, $value2$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.compareAndExchange)) {
|
||||
checkIOOBE(am, () -> {
|
||||
$type$ r = ($type$) hs.get(am).invokeExact(array, ci, $value2$, $value1$);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndSet)) {
|
||||
checkIOOBE(am, () -> {
|
||||
$type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value1$);
|
||||
});
|
||||
}
|
||||
#end[CAS]
|
||||
|
||||
#if[AtomicAdd]
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.getAndAdd)) {
|
||||
checkIOOBE(am, () -> {
|
||||
$type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value3$);
|
||||
});
|
||||
}
|
||||
#end[AtomicAdd]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
155
jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
Normal file
155
jdk/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
Normal file
@ -0,0 +1,155 @@
|
||||
#!/bin/bash
|
||||
|
||||
javac -d . ../../../../../make/src/classes/build/tools/spp/Spp.java
|
||||
|
||||
SPP=build.tools.spp.Spp
|
||||
|
||||
# Generates variable handle tests for objects and all primitive types
|
||||
# This is likely to be a temporary testing approach as it may be more
|
||||
# desirable to generate code using ASM which will allow more flexibility
|
||||
# in the kinds of tests that are generated.
|
||||
|
||||
for type in boolean byte short char int long float double String
|
||||
do
|
||||
Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
|
||||
args="-K$type -Dtype=$type -DType=$Type"
|
||||
|
||||
case $type in
|
||||
String|int|long)
|
||||
args="$args -KCAS"
|
||||
;;
|
||||
esac
|
||||
|
||||
case $type in
|
||||
int|long)
|
||||
args="$args -KAtomicAdd"
|
||||
;;
|
||||
esac
|
||||
|
||||
wrong_primitive_type=boolean
|
||||
|
||||
case $type in
|
||||
boolean)
|
||||
value1=true
|
||||
value2=false
|
||||
value3=false
|
||||
wrong_primitive_type=int
|
||||
;;
|
||||
byte)
|
||||
value1=(byte)1
|
||||
value2=(byte)2
|
||||
value3=(byte)3
|
||||
;;
|
||||
short)
|
||||
value1=(short)1
|
||||
value2=(short)2
|
||||
value3=(short)3
|
||||
;;
|
||||
char)
|
||||
value1=\'a\'
|
||||
value2=\'b\'
|
||||
value3=\'c\'
|
||||
;;
|
||||
int)
|
||||
value1=1
|
||||
value2=2
|
||||
value3=3
|
||||
;;
|
||||
long)
|
||||
value1=1L
|
||||
value2=2L
|
||||
value3=3L
|
||||
;;
|
||||
float)
|
||||
value1=1.0f
|
||||
value2=2.0f
|
||||
value3=3.0f
|
||||
;;
|
||||
double)
|
||||
value1=1.0d
|
||||
value2=2.0d
|
||||
value3=3.0d
|
||||
;;
|
||||
String)
|
||||
value1=\"foo\"
|
||||
value2=\"bar\"
|
||||
value3=\"baz\"
|
||||
;;
|
||||
esac
|
||||
|
||||
args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3 -Dwrong_primitive_type=$wrong_primitive_type"
|
||||
|
||||
echo $args
|
||||
java $SPP -nel $args < X-VarHandleTestAccess.java.template > VarHandleTestAccess${Type}.java
|
||||
java $SPP -nel $args < X-VarHandleTestMethodHandleAccess.java.template > VarHandleTestMethodHandleAccess${Type}.java
|
||||
java $SPP -nel $args < X-VarHandleTestMethodType.java.template > VarHandleTestMethodType${Type}.java
|
||||
done
|
||||
|
||||
for type in short char int long float double
|
||||
do
|
||||
Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
|
||||
args="-K$type -Dtype=$type -DType=$Type"
|
||||
|
||||
BoxType=$Type
|
||||
case $type in
|
||||
char)
|
||||
BoxType=Character
|
||||
;;
|
||||
int)
|
||||
BoxType=Integer
|
||||
;;
|
||||
esac
|
||||
args="$args -DBoxType=$BoxType"
|
||||
|
||||
case $type in
|
||||
int|long|float|double)
|
||||
args="$args -KCAS"
|
||||
;;
|
||||
esac
|
||||
|
||||
case $type in
|
||||
int|long)
|
||||
args="$args -KAtomicAdd"
|
||||
;;
|
||||
esac
|
||||
|
||||
case $type in
|
||||
short)
|
||||
value1=(short)0x0102
|
||||
value2=(short)0x1112
|
||||
value3=(short)0x2122
|
||||
;;
|
||||
char)
|
||||
value1=(char)0x0102
|
||||
value2=(char)0x1112
|
||||
value3=(char)0x2122
|
||||
;;
|
||||
int)
|
||||
value1=0x01020304
|
||||
value2=0x11121314
|
||||
value3=0x21222324
|
||||
;;
|
||||
long)
|
||||
value1=0x0102030405060708L
|
||||
value2=0x1112131415161718L
|
||||
value3=0x2122232425262728L
|
||||
;;
|
||||
float)
|
||||
value1=0x01020304
|
||||
value2=0x11121314
|
||||
value3=0x21222324
|
||||
;;
|
||||
double)
|
||||
value1=0x0102030405060708L
|
||||
value2=0x1112131415161718L
|
||||
value3=0x2122232425262728L
|
||||
;;
|
||||
esac
|
||||
|
||||
args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3"
|
||||
|
||||
echo $args
|
||||
java $SPP -nel $args < X-VarHandleTestByteArrayView.java.template > VarHandleTestByteArrayAs${Type}.java
|
||||
done
|
||||
|
||||
rm -fr build
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -336,6 +336,103 @@ public class Basic$Type$
|
||||
|
||||
}
|
||||
|
||||
private static void testAlign(final ByteBuffer b, boolean direct) {
|
||||
// index out-of bounds
|
||||
tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
|
||||
|
||||
// unit size values
|
||||
tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
|
||||
for (int us = 1; us < 65; us++) {
|
||||
int _us = us;
|
||||
if ((us & (us - 1)) != 0) {
|
||||
// unit size not a power of two
|
||||
tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
|
||||
} else {
|
||||
if (direct || us <= 8) {
|
||||
b.alignmentOffset(0, us);
|
||||
} else {
|
||||
// unit size > 8 with non-direct buffer
|
||||
tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Probe for long misalignment at index zero for a newly created buffer
|
||||
ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
|
||||
int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
|
||||
|
||||
if (direct) {
|
||||
// Freshly created direct byte buffers should be aligned at index 0
|
||||
// for ref and primitive values (see Unsafe.allocateMemory)
|
||||
if (longMisalignmentAtZero != 0)
|
||||
fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
|
||||
} else {
|
||||
// For heap byte buffers misalignment may occur on 32-bit systems
|
||||
// where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
|
||||
// Note the GC will preserve alignment of the base address of the
|
||||
// array
|
||||
if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
|
||||
fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
|
||||
}
|
||||
|
||||
// Ensure test buffer is correctly aligned at index 0
|
||||
if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
|
||||
fail("Test input buffer not correctly aligned at index 0", b);
|
||||
|
||||
// Test misalignment values
|
||||
for (int us : new int[]{1, 2, 4, 8}) {
|
||||
for (int i = 0; i < us * 2; i++) {
|
||||
int am = b.alignmentOffset(i, us);
|
||||
int expectedAm = (longMisalignmentAtZero + i) % us;
|
||||
|
||||
if (am != expectedAm)
|
||||
fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
|
||||
}
|
||||
}
|
||||
|
||||
// Created aligned slice to test against
|
||||
int ap = 8 - longMisalignmentAtZero;
|
||||
int al = b.limit() - b.alignmentOffset(b.limit(), 8);
|
||||
ByteBuffer ab = b.position(ap).limit(al).
|
||||
slice();
|
||||
if (ab.limit() == 0)
|
||||
fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
|
||||
if (ab.alignmentOffset(0, 8) != 0)
|
||||
fail("Aligned test input buffer not correctly aligned at index 0", ab);
|
||||
|
||||
for (int us : new int[]{1, 2, 4, 8}) {
|
||||
for (int p = 1; p < 16; p++) {
|
||||
int l = ab.limit() - p;
|
||||
|
||||
ByteBuffer as = ab.slice().position(p).limit(l).
|
||||
alignedSlice(us);
|
||||
|
||||
ck(as, 0, as.position());
|
||||
ck(as, as.capacity(), as.limit());
|
||||
if (b.isDirect() != as.isDirect())
|
||||
fail("Lost direction", as);
|
||||
if (b.isReadOnly() != as.isReadOnly())
|
||||
fail("Lost read-only", as);
|
||||
|
||||
if (as.alignmentOffset(0, us) != 0)
|
||||
fail("Buffer not correctly aligned at index 0", as);
|
||||
|
||||
if (as.alignmentOffset(as.limit(), us) != 0)
|
||||
fail("Buffer not correctly aligned at limit", as);
|
||||
|
||||
int p_mod = ab.alignmentOffset(p, us);
|
||||
int l_mod = ab.alignmentOffset(l, us);
|
||||
// Round up position
|
||||
p = (p_mod > 0) ? p + (us - p_mod) : p;
|
||||
// Round down limit
|
||||
l = l - l_mod;
|
||||
|
||||
int ec = l - p;
|
||||
if (as.limit() != ec)
|
||||
fail("Buffer capacity incorrect, expected: " + ec, as);
|
||||
}
|
||||
}
|
||||
}
|
||||
#end[byte]
|
||||
|
||||
private static void fail(String problem,
|
||||
@ -854,6 +951,11 @@ public class Basic$Type$
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
#if[byte]
|
||||
// Test alignment
|
||||
|
||||
testAlign(b, direct);
|
||||
#end[byte]
|
||||
}
|
||||
|
||||
#if[char]
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
* @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
|
||||
* 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
|
||||
* 6221101 6234263 6535542 6591971 6593946 6795561 7190219 7199551 8065556
|
||||
* 8149469
|
||||
* @author Mark Reinhold
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -336,6 +336,103 @@ public class BasicByte
|
||||
|
||||
}
|
||||
|
||||
private static void testAlign(final ByteBuffer b, boolean direct) {
|
||||
// index out-of bounds
|
||||
tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
|
||||
|
||||
// unit size values
|
||||
tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
|
||||
for (int us = 1; us < 65; us++) {
|
||||
int _us = us;
|
||||
if ((us & (us - 1)) != 0) {
|
||||
// unit size not a power of two
|
||||
tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
|
||||
} else {
|
||||
if (direct || us <= 8) {
|
||||
b.alignmentOffset(0, us);
|
||||
} else {
|
||||
// unit size > 8 with non-direct buffer
|
||||
tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Probe for long misalignment at index zero for a newly created buffer
|
||||
ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
|
||||
int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
|
||||
|
||||
if (direct) {
|
||||
// Freshly created direct byte buffers should be aligned at index 0
|
||||
// for ref and primitive values (see Unsafe.allocateMemory)
|
||||
if (longMisalignmentAtZero != 0)
|
||||
fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
|
||||
} else {
|
||||
// For heap byte buffers misalignment may occur on 32-bit systems
|
||||
// where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
|
||||
// Note the GC will preserve alignment of the base address of the
|
||||
// array
|
||||
if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
|
||||
fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
|
||||
}
|
||||
|
||||
// Ensure test buffer is correctly aligned at index 0
|
||||
if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
|
||||
fail("Test input buffer not correctly aligned at index 0", b);
|
||||
|
||||
// Test misalignment values
|
||||
for (int us : new int[]{1, 2, 4, 8}) {
|
||||
for (int i = 0; i < us * 2; i++) {
|
||||
int am = b.alignmentOffset(i, us);
|
||||
int expectedAm = (longMisalignmentAtZero + i) % us;
|
||||
|
||||
if (am != expectedAm)
|
||||
fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
|
||||
}
|
||||
}
|
||||
|
||||
// Created aligned slice to test against
|
||||
int ap = 8 - longMisalignmentAtZero;
|
||||
int al = b.limit() - b.alignmentOffset(b.limit(), 8);
|
||||
ByteBuffer ab = b.position(ap).limit(al).
|
||||
slice();
|
||||
if (ab.limit() == 0)
|
||||
fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
|
||||
if (ab.alignmentOffset(0, 8) != 0)
|
||||
fail("Aligned test input buffer not correctly aligned at index 0", ab);
|
||||
|
||||
for (int us : new int[]{1, 2, 4, 8}) {
|
||||
for (int p = 1; p < 16; p++) {
|
||||
int l = ab.limit() - p;
|
||||
|
||||
ByteBuffer as = ab.slice().position(p).limit(l).
|
||||
alignedSlice(us);
|
||||
|
||||
ck(as, 0, as.position());
|
||||
ck(as, as.capacity(), as.limit());
|
||||
if (b.isDirect() != as.isDirect())
|
||||
fail("Lost direction", as);
|
||||
if (b.isReadOnly() != as.isReadOnly())
|
||||
fail("Lost read-only", as);
|
||||
|
||||
if (as.alignmentOffset(0, us) != 0)
|
||||
fail("Buffer not correctly aligned at index 0", as);
|
||||
|
||||
if (as.alignmentOffset(as.limit(), us) != 0)
|
||||
fail("Buffer not correctly aligned at limit", as);
|
||||
|
||||
int p_mod = ab.alignmentOffset(p, us);
|
||||
int l_mod = ab.alignmentOffset(l, us);
|
||||
// Round up position
|
||||
p = (p_mod > 0) ? p + (us - p_mod) : p;
|
||||
// Round down limit
|
||||
l = l - l_mod;
|
||||
|
||||
int ec = l - p;
|
||||
if (as.limit() != ec)
|
||||
fail("Buffer capacity incorrect, expected: " + ec, as);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void fail(String problem,
|
||||
@ -854,6 +951,11 @@ public class BasicByte
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
// Test alignment
|
||||
|
||||
testAlign(b, direct);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -317,6 +317,103 @@ public class BasicChar
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -854,6 +951,11 @@ public class BasicChar
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -317,6 +317,103 @@ public class BasicDouble
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -854,6 +951,11 @@ public class BasicDouble
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -317,6 +317,103 @@ public class BasicFloat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -854,6 +951,11 @@ public class BasicFloat
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -317,6 +317,103 @@ public class BasicInt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -854,6 +951,11 @@ public class BasicInt
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -317,6 +317,103 @@ public class BasicLong
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -854,6 +951,11 @@ public class BasicLong
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -317,6 +317,103 @@ public class BasicShort
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -854,6 +951,11 @@ public class BasicShort
|
||||
|
||||
relPut(b); // Required by testViews
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user