This commit is contained in:
Alejandro Murillo 2016-04-05 20:02:21 -07:00
commit 9f3b6be989
96 changed files with 38771 additions and 96 deletions

View File

@ -33,6 +33,7 @@ include GensrcCharsetMapping.gmk
include GensrcCharsetCoder.gmk
include GensrcBuffer.gmk
include GensrcExceptions.gmk
include GensrcVarHandles.gmk
include GensrcModuleLoaderMap.gmk
################################################################################

View 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)

View File

@ -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;

View File

@ -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)

View File

@ -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));

View File

@ -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() { }

View File

@ -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,

View File

@ -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,

View File

@ -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.

View File

@ -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");

View File

@ -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();

View File

@ -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

View 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);
}
}
};
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View 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());
// }
// }
// }
}

View File

@ -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]
}
}

View File

@ -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]
}
}

View File

@ -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.

View File

@ -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;

View File

@ -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(),

View File

@ -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]

View File

@ -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() {

View File

@ -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

View File

@ -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);
}
/**

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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));
}
/**

View File

@ -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);
}
/**

View File

@ -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);
}
/**

View File

@ -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) {

View File

@ -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);
}
/**

View File

@ -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);
}
/**

View File

@ -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) {

View File

@ -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);
}
/**

View File

@ -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);
}
/**

View File

@ -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")

View File

@ -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

View File

@ -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) {

View File

@ -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);
}
/**

View File

@ -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);
}
}

View 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());
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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');
});
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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);
});
}
}
}

View 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);
});
}
}
}

View 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 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);
});
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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");
});
}
}
}

View File

@ -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");
}
}
}
}
}

View File

@ -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");
}
}
}
}
}

View File

@ -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");
}
}
}
}
}

View File

@ -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");
}
}
}
}
}

View File

@ -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");
}
}
}
}
}

View File

@ -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");
}
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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');
});
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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);
});
}
}
}
}

View File

@ -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");
});
}
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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);
});
}
}
}

View File

@ -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);
});
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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]

View File

@ -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
*/

View File

@ -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);
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}