undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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
|
||||
* @bug 8307508
|
||||
* @run junit IndirectVarHandleTest
|
||||
* @summary Test VarHandle::isAccessModeSupported on indirect VarHandle
|
||||
* produced by MethodHandles.filterCoordinates
|
||||
*/
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class IndirectVarHandleTest {
|
||||
@Test
|
||||
public void testIsAccessModeTypeSupported() throws Throwable {
|
||||
var lookup = MethodHandles.lookup();
|
||||
var intArrayVh = MethodHandles.arrayElementVarHandle(int[].class);
|
||||
var addOne = lookup.bind((IntUnaryOperator) a -> a + 1, "applyAsInt",
|
||||
MethodType.methodType(int.class, int.class));
|
||||
var offsetIntArrayVh = MethodHandles.filterCoordinates(intArrayVh, 1, addOne);
|
||||
|
||||
for (var mode : VarHandle.AccessMode.values()) {
|
||||
assertEquals(intArrayVh.isAccessModeSupported(mode),
|
||||
offsetIntArrayVh.isAccessModeSupported(mode), mode.toString());
|
||||
}
|
||||
|
||||
var stringArrayVh = MethodHandles.arrayElementVarHandle(String[].class);
|
||||
var offsetStringArrayVh = MethodHandles.filterCoordinates(stringArrayVh, 1, addOne);
|
||||
|
||||
for (var mode : VarHandle.AccessMode.values()) {
|
||||
assertEquals(stringArrayVh.isAccessModeSupported(mode),
|
||||
offsetStringArrayVh.isAccessModeSupported(mode), mode.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
217
test/jdk/java/lang/invoke/VarHandles/LazyInitializingTest.java
Normal file
217
test/jdk/java/lang/invoke/VarHandles/LazyInitializingTest.java
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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
|
||||
* @bug 8291065
|
||||
* @summary Checks interaction of static field VarHandle with class
|
||||
* initialization mechanism..
|
||||
* @run junit LazyInitializingTest
|
||||
* @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true LazyInitializingTest
|
||||
* @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false LazyInitializingTest
|
||||
* @run junit/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false LazyInitializingTest
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class LazyInitializingTest {
|
||||
|
||||
record SampleData(Runnable callback, int initialValue) {
|
||||
private static final Runnable FAIL_ON_CLINIT_CALLBACK = () -> {
|
||||
throw new AssertionError("Class shouldn't be initialized");
|
||||
};
|
||||
static final SampleData FAIL_ON_CLINIT = new SampleData();
|
||||
|
||||
SampleData() {
|
||||
this(FAIL_ON_CLINIT_CALLBACK, 0);
|
||||
}
|
||||
}
|
||||
record ClassInfo(MethodHandles.Lookup definingLookup, VarHandle vh) {}
|
||||
|
||||
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||
|
||||
/**
|
||||
* Meta test to ensure the testing mechanism to check initialization is correct.
|
||||
*/
|
||||
@Test
|
||||
public void testMeta() throws IllegalAccessException {
|
||||
boolean[] val = new boolean[1];
|
||||
var v0 = createSampleClass(new SampleData(() -> val[0] = true, 0));
|
||||
assertFalse(val[0], "callback run before class init");
|
||||
v0.definingLookup.ensureInitialized(v0.definingLookup.lookupClass());
|
||||
assertTrue(val[0], "callback not run at class init");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUninitializedOperations() {
|
||||
var ci = createSampleClass(SampleData.FAIL_ON_CLINIT);
|
||||
var vh = ci.vh;
|
||||
vh.describeConstable();
|
||||
vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE);
|
||||
vh.withInvokeExactBehavior();
|
||||
vh.withInvokeBehavior();
|
||||
vh.toMethodHandle(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE);
|
||||
vh.hasInvokeExactBehavior();
|
||||
vh.accessModeType(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializationOnVarHandleUse() {
|
||||
var initialized = new boolean[1];
|
||||
var ci = createSampleClass(new SampleData(() -> initialized[0] = true, 42));
|
||||
var vh = ci.vh;
|
||||
|
||||
assertEquals(42, (int) vh.get(), "VH does not read value set in class initializer");
|
||||
assertTrue(initialized[0], "class initialization not captured");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializationOnToMethodHandleUse() throws Throwable {
|
||||
var initialized = new boolean[1];
|
||||
var ci = createSampleClass(new SampleData(() -> initialized[0] = true, 42));
|
||||
var mh = ci.vh.toMethodHandle(VarHandle.AccessMode.GET);
|
||||
|
||||
assertEquals(42, (int) mh.invokeExact(), "VH does not read value set in class initializer");
|
||||
assertTrue(initialized[0], "class initialization not captured");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParentChildLoading() throws Throwable {
|
||||
// ChildSample: ensure only ParentSample (field declarer) is initialized
|
||||
var l = new ParentChildLoader();
|
||||
var childSampleClass = l.childClass();
|
||||
var lookup = MethodHandles.privateLookupIn(childSampleClass, LOOKUP);
|
||||
var childVh = lookup.findStaticVarHandle(childSampleClass, "f", int.class);
|
||||
|
||||
assertEquals(3, (int) childVh.get(), "Child class initialized unnecessarily");
|
||||
|
||||
lookup.ensureInitialized(childSampleClass);
|
||||
|
||||
assertEquals(6, (int) childVh.get(), "Child class was not initialized");
|
||||
}
|
||||
|
||||
static ClassInfo createSampleClass(SampleData sampleData) {
|
||||
try {
|
||||
var lookup = LOOKUP.defineHiddenClassWithClassData(sampleClassBytes(), sampleData, false);
|
||||
var vh = lookup.findStaticVarHandle(lookup.lookupClass(), "f", int.class);
|
||||
return new ClassInfo(lookup, vh);
|
||||
} catch (IllegalAccessException | NoSuchFieldException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] sampleClassBytes;
|
||||
|
||||
private static byte[] sampleClassBytes() {
|
||||
var bytes = sampleClassBytes;
|
||||
if (bytes != null)
|
||||
return bytes;
|
||||
|
||||
try (var in = LazyInitializingTest.class.getResourceAsStream("LazyInitializingSample.class")) {
|
||||
if (in == null)
|
||||
throw new AssertionError("class file not found");
|
||||
return sampleClassBytes = in.readAllBytes();
|
||||
} catch (IOException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is used as a template class, whose bytes are used to define
|
||||
// hidden classes instead
|
||||
class LazyInitializingSample {
|
||||
static int f;
|
||||
|
||||
static {
|
||||
try {
|
||||
var data = MethodHandles.classData(MethodHandles.lookup(), ConstantDescs.DEFAULT_NAME,
|
||||
LazyInitializingTest.SampleData.class);
|
||||
Objects.requireNonNull(data);
|
||||
|
||||
data.callback().run();
|
||||
f = data.initialValue();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ParentChildLoader extends ClassLoader {
|
||||
ParentChildLoader() {
|
||||
super(LazyInitializingTest.class.getClassLoader().getParent());
|
||||
}
|
||||
|
||||
Class<?> parentClass() {
|
||||
try {
|
||||
return loadClass("ParentSample");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> childClass() {
|
||||
try {
|
||||
return loadClass("ChildSample");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
try (var stream = switch (name) {
|
||||
case "ParentSample", "ChildSample" -> LazyInitializingTest.class.getResourceAsStream(name + ".class");
|
||||
default -> throw new ClassNotFoundException(name);
|
||||
}) {
|
||||
if (stream == null)
|
||||
throw new AssertionError();
|
||||
var b = stream.readAllBytes();
|
||||
return defineClass(name, b, 0, b.length);
|
||||
} catch (IOException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ParentSample {
|
||||
static int f;
|
||||
|
||||
static {
|
||||
f = 3;
|
||||
}
|
||||
}
|
||||
|
||||
class ChildSample extends ParentSample {
|
||||
static {
|
||||
f = 6;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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.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;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
||||
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> {
|
||||
final boolean supportsAtomicAccess;
|
||||
|
||||
VarHandleSource(VarHandle vh, boolean supportsAtomicAccess, MemoryMode... modes) {
|
||||
super(vh, modes);
|
||||
this.supportsAtomicAccess = supportsAtomicAccess;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public void setup() {
|
||||
setupByteSources();
|
||||
vhss = setupVarHandleSources(true);
|
||||
}
|
||||
|
||||
abstract List<VarHandleSource> setupVarHandleSources(boolean same);
|
||||
|
||||
public Object[][] varHandlesProvider() throws Exception {
|
||||
return vhss.stream().map(cvh -> new Object[]{cvh}).toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
509
test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java
Normal file
509
test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2026, 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.junit.jupiter.api.Assertions.*;
|
||||
|
||||
abstract class VarHandleBaseTest {
|
||||
static final int ITERS = Integer.getInteger("iters", 1);
|
||||
|
||||
// More resilience for Weak* tests. These operations may spuriously
|
||||
// fail, and so we do several attempts with delay on failure.
|
||||
// Be mindful of worst-case total time on test, which would be at
|
||||
// roughly (delay*attempts) milliseconds.
|
||||
//
|
||||
static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 100);
|
||||
static final int WEAK_DELAY_MS = Math.max(1, Integer.getInteger("weakDelay", 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 checkAIOOBE(ThrowingRunnable r) {
|
||||
checkWithThrowable(ArrayIndexOutOfBoundsException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkAIOOBE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(ArrayIndexOutOfBoundsException.class, message, r);
|
||||
}
|
||||
|
||||
static void checkASE(ThrowingRunnable r) {
|
||||
checkWithThrowable(ArrayStoreException.class, null, r);
|
||||
}
|
||||
|
||||
static void checkASE(Object message, ThrowingRunnable r) {
|
||||
checkWithThrowable(ArrayStoreException.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) {
|
||||
assertThrows(re, r::run, message == null ? null : message.toString());
|
||||
}
|
||||
|
||||
|
||||
enum TestAccessType {
|
||||
GET,
|
||||
SET,
|
||||
COMPARE_AND_SET,
|
||||
COMPARE_AND_EXCHANGE,
|
||||
GET_AND_SET,
|
||||
GET_AND_ADD,
|
||||
GET_AND_BITWISE;
|
||||
}
|
||||
|
||||
enum TestAccessMode {
|
||||
GET(TestAccessType.GET),
|
||||
SET(TestAccessType.SET),
|
||||
GET_VOLATILE(TestAccessType.GET),
|
||||
SET_VOLATILE(TestAccessType.SET),
|
||||
GET_ACQUIRE(TestAccessType.GET),
|
||||
SET_RELEASE(TestAccessType.SET),
|
||||
GET_OPAQUE(TestAccessType.GET),
|
||||
SET_OPAQUE(TestAccessType.SET),
|
||||
COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
|
||||
COMPARE_AND_EXCHANGE(TestAccessType.COMPARE_AND_EXCHANGE),
|
||||
COMPARE_AND_EXCHANGE_ACQUIRE(TestAccessType.COMPARE_AND_EXCHANGE),
|
||||
COMPARE_AND_EXCHANGE_RELEASE(TestAccessType.COMPARE_AND_EXCHANGE),
|
||||
WEAK_COMPARE_AND_SET_PLAIN(TestAccessType.COMPARE_AND_SET),
|
||||
WEAK_COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
|
||||
WEAK_COMPARE_AND_SET_ACQUIRE(TestAccessType.COMPARE_AND_SET),
|
||||
WEAK_COMPARE_AND_SET_RELEASE(TestAccessType.COMPARE_AND_SET),
|
||||
GET_AND_SET(TestAccessType.GET_AND_SET),
|
||||
GET_AND_SET_ACQUIRE(TestAccessType.GET_AND_SET),
|
||||
GET_AND_SET_RELEASE(TestAccessType.GET_AND_SET),
|
||||
GET_AND_ADD(TestAccessType.GET_AND_ADD),
|
||||
GET_AND_ADD_ACQUIRE(TestAccessType.GET_AND_ADD),
|
||||
GET_AND_ADD_RELEASE(TestAccessType.GET_AND_ADD),
|
||||
GET_AND_BITWISE_OR(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_OR_ACQUIRE(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_OR_RELEASE(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_AND(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_AND_ACQUIRE(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_AND_RELEASE(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_XOR(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_XOR_ACQUIRE(TestAccessType.GET_AND_BITWISE),
|
||||
GET_AND_BITWISE_XOR_RELEASE(TestAccessType.GET_AND_BITWISE),
|
||||
;
|
||||
|
||||
final TestAccessType at;
|
||||
final boolean isPolyMorphicInReturnType;
|
||||
final Class<?> returnType;
|
||||
|
||||
TestAccessMode(TestAccessType at) {
|
||||
this.at = at;
|
||||
|
||||
try {
|
||||
VarHandle.AccessMode vh_am = toAccessMode();
|
||||
Method m = VarHandle.class.getMethod(vh_am.methodName(), 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());
|
||||
return s.filter(e -> Stream.of(ats).anyMatch(e::isOfType))
|
||||
.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());
|
||||
return s.filter(e -> Stream.of(ats).anyMatch(e::isOfType))
|
||||
.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) {
|
||||
MethodHandle mh;
|
||||
try {
|
||||
mh = MethodHandles.publicLookup().
|
||||
findVirtual(VarHandle.class,
|
||||
tam.toAccessMode().methodName(),
|
||||
mt);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return bind(vh, mh, mt);
|
||||
}
|
||||
|
||||
static MethodHandle varHandleInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
MethodHandle mh = MethodHandles.varHandleInvoker(
|
||||
tam.toAccessMode(),
|
||||
mt);
|
||||
|
||||
return bind(vh, mh, mt);
|
||||
}
|
||||
|
||||
static MethodHandle varHandleExactInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) {
|
||||
MethodHandle mh = MethodHandles.varHandleExactInvoker(
|
||||
tam.toAccessMode(),
|
||||
mt);
|
||||
|
||||
return bind(vh, mh, mt);
|
||||
}
|
||||
|
||||
private static MethodHandle bind(VarHandle vh, MethodHandle mh, MethodType emt) {
|
||||
assertEquals(emt.insertParameterTypes(0, VarHandle.class), mh.type(),
|
||||
"MethodHandle type differs from access mode type");
|
||||
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
assertEquals(emt, info.getMethodType(),
|
||||
"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",
|
||||
true,
|
||||
VarHandleBaseTest::toMethodHandle),
|
||||
METHOD_HANDLES_LOOKUP_FIND_VIRTUAL(
|
||||
"Lookup.findVirtual",
|
||||
false,
|
||||
VarHandleBaseTest::findVirtual),
|
||||
METHOD_HANDLES_VAR_HANDLE_INVOKER(
|
||||
"MethodHandles.varHandleInvoker",
|
||||
false,
|
||||
VarHandleBaseTest::varHandleInvoker),
|
||||
METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER(
|
||||
"MethodHandles.varHandleExactInvoker",
|
||||
true,
|
||||
VarHandleBaseTest::varHandleExactInvoker);
|
||||
|
||||
final String desc;
|
||||
final boolean isExact;
|
||||
final TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f;
|
||||
|
||||
VarHandleToMethodHandle(String desc, boolean isExact,
|
||||
TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
|
||||
this.desc = desc;
|
||||
this.f = f;
|
||||
this.isExact = isExact;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
Class<? extends Throwable> getWMTEOOrOther(Class<? extends Throwable> c) {
|
||||
return f.isExact ? WrongMethodTypeException.class : c;
|
||||
}
|
||||
|
||||
void checkWMTEOrCCE(ThrowingRunnable r) {
|
||||
checkWithThrowable(getWMTEOOrOther(ClassCastException.class), null, r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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(pts, amt.parameterList().subList(0, pts.size()));
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.GET)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(vh.varType(), mt.returnType());
|
||||
assertEquals(pts, mt.parameterList());
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.SET)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(void.class, mt.returnType());
|
||||
assertEquals(vh.varType(), mt.parameterType(mt.parameterCount() - 1));
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(boolean.class, mt.returnType());
|
||||
assertEquals(vh.varType(), mt.parameterType(mt.parameterCount() - 1));
|
||||
assertEquals(vh.varType(), mt.parameterType(mt.parameterCount() - 2));
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(vh.varType(), mt.returnType());
|
||||
assertEquals(vh.varType(), mt.parameterType(mt.parameterCount() - 1));
|
||||
assertEquals(vh.varType(), mt.parameterType(mt.parameterCount() - 2));
|
||||
}
|
||||
|
||||
for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.GET_AND_SET, TestAccessType.GET_AND_ADD)) {
|
||||
MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
|
||||
assertEquals(vh.varType(), mt.returnType());
|
||||
assertEquals(vh.varType(), mt.parameterType(mt.parameterCount() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void weakDelay() {
|
||||
try {
|
||||
if (WEAK_DELAY_MS > 0) {
|
||||
Thread.sleep(WEAK_DELAY_MS);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 2025, 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
|
||||
* @bug 8195650
|
||||
* @summary Test linking of method references to VarHandle access methods.
|
||||
* @run junit VarHandleMethodReferenceTest
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.invoke.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class VarHandleMethodReferenceTest {
|
||||
|
||||
interface R {
|
||||
void apply();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodReferences() {
|
||||
VarHandle vh = MethodHandles.arrayElementVarHandle(int[].class);
|
||||
|
||||
// The compilation of these method references will result in the
|
||||
// placement of MethodHandles in the constant pool that reference
|
||||
// VarHandle signature polymorphic methods.
|
||||
// When those constant method handles are loaded the VarHandle invoker
|
||||
// mechanism will be used where the first argument to invocation will be
|
||||
// the bound VarHandle instance
|
||||
|
||||
// VarHandle invokers are tested by other test classes so here it
|
||||
// is just necessary to check that functional objects can be successfully
|
||||
// obtained, it does not matter about the signature of the functional
|
||||
// interface
|
||||
|
||||
R r;
|
||||
r = vh::get;
|
||||
r = vh::set;
|
||||
r = vh::getVolatile;
|
||||
r = vh::setVolatile;
|
||||
r = vh::getOpaque;
|
||||
r = vh::setOpaque;
|
||||
r = vh::getAcquire;
|
||||
r = vh::setRelease;
|
||||
|
||||
r = vh::compareAndSet;
|
||||
r = vh::compareAndExchange;
|
||||
r = vh::compareAndExchangeAcquire;
|
||||
r = vh::compareAndExchangeRelease;
|
||||
r = vh::weakCompareAndSetPlain;
|
||||
r = vh::weakCompareAndSet;
|
||||
r = vh::weakCompareAndSetAcquire;
|
||||
r = vh::weakCompareAndSetRelease;
|
||||
|
||||
r = vh::getAndSet;
|
||||
r = vh::getAndSetAcquire;
|
||||
r = vh::getAndSetRelease;
|
||||
r = vh::getAndAdd;
|
||||
r = vh::getAndAddAcquire;
|
||||
r = vh::getAndAddRelease;
|
||||
r = vh::getAndBitwiseOr;
|
||||
r = vh::getAndBitwiseOrAcquire;
|
||||
r = vh::getAndBitwiseOrRelease;
|
||||
r = vh::getAndBitwiseAnd;
|
||||
r = vh::getAndBitwiseAndAcquire;
|
||||
r = vh::getAndBitwiseAndRelease;
|
||||
r = vh::getAndBitwiseXor;
|
||||
r = vh::getAndBitwiseXorAcquire;
|
||||
r = vh::getAndBitwiseXorRelease;
|
||||
}
|
||||
}
|
||||
1418
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
Normal file
1418
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
Normal file
File diff suppressed because it is too large
Load diff
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
Normal file
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
Normal file
File diff suppressed because it is too large
Load diff
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
Normal file
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
Normal file
File diff suppressed because it is too large
Load diff
1346
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
Normal file
1346
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
Normal file
File diff suppressed because it is too large
Load diff
1346
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
Normal file
1346
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
Normal file
File diff suppressed because it is too large
Load diff
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
Normal file
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
Normal file
File diff suppressed because it is too large
Load diff
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
Normal file
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2025, 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 junit VarHandleTestAccessModeMethodNames
|
||||
* @modules java.base/java.lang.invoke:open
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class VarHandleTestAccessModeMethodNames {
|
||||
|
||||
public static Object[][] accessModesProvider() {
|
||||
return Stream.of(VarHandle.AccessMode.values()).
|
||||
map(am -> new Object[]{am}).
|
||||
toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
public void testMethodName(VarHandle.AccessMode am) {
|
||||
assertEquals(toMethodName(am.name()), am.methodName());
|
||||
}
|
||||
|
||||
private static String toMethodName(String name) {
|
||||
StringBuilder s = new StringBuilder(name.toLowerCase());
|
||||
int i;
|
||||
while ((i = s.indexOf("_")) != -1) {
|
||||
s.deleteCharAt(i);
|
||||
s.setCharAt(i, Character.toUpperCase(s.charAt(i)));
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
public void testReturnType(VarHandle.AccessMode am) throws Exception {
|
||||
assertEquals(getAccessModeReturnType(am), getReturnType(am.methodName()));
|
||||
}
|
||||
|
||||
private static Class<?> getReturnType(String name) throws Exception {
|
||||
return VarHandle.class.getMethod(name, Object[].class).getReturnType();
|
||||
}
|
||||
|
||||
private static Class<?> getAccessModeReturnType(VarHandle.AccessMode am) throws Exception {
|
||||
Field field_am_at = VarHandle.AccessMode.class.getDeclaredField("at");
|
||||
field_am_at.setAccessible(true);
|
||||
Field field_at_returnType = field_am_at.getType().getDeclaredField("returnType");
|
||||
field_at_returnType.setAccessible(true);
|
||||
return (Class<?>) field_at_returnType.get(field_am_at.get(am));
|
||||
}
|
||||
}
|
||||
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
Normal file
1455
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
Normal file
File diff suppressed because it is too large
Load diff
1396
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
Normal file
1396
test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,836 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
* @bug 8154556
|
||||
* @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations
|
||||
* to hit compilation thresholds
|
||||
* @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
|
||||
* @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsChar
|
||||
* @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsChar
|
||||
*/
|
||||
|
||||
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.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
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)0xFFFE;
|
||||
|
||||
|
||||
@Override
|
||||
public List<VarHandleSource> setupVarHandleSources(boolean same) {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
List<VarHandleSource> vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
|
||||
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
|
||||
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
|
||||
|
||||
Class<?> arrayType;
|
||||
if (same) {
|
||||
arrayType = char[].class;
|
||||
}
|
||||
else {
|
||||
arrayType = int[].class;
|
||||
}
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
return vhss;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
VarHandle[] vhs1 = setupVarHandleSources(true).stream().
|
||||
map(vhs -> vhs.s).toArray(VarHandle[]::new);
|
||||
VarHandle[] vhs2 = setupVarHandleSources(true).stream().
|
||||
map(vhs -> vhs.s).toArray(VarHandle[]::new);
|
||||
|
||||
for (int i = 0; i < vhs1.length; i++) {
|
||||
for (int j = 0; j < vhs1.length; j++) {
|
||||
if (i != j) {
|
||||
assertNotEquals(vhs1[i], vhs1[j]);
|
||||
assertNotEquals(vhs1[i], vhs2[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VarHandle[] vhs3 = setupVarHandleSources(false).stream().
|
||||
map(vhs -> vhs.s).toArray(VarHandle[]::new);
|
||||
for (int i = 0; i < vhs1.length; i++) {
|
||||
assertNotEquals(vhs1[i], vhs3[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("VarHandleBaseByteArrayTest#varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
|
||||
|
||||
if (vhs.supportsAtomicAccess) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
|
||||
} else {
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
|
||||
}
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
|
||||
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(char.class, vh.varType());
|
||||
|
||||
assertEquals(pts, vh.coordinateTypes());
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
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(
|
||||
"null array", bav, vh, h -> testArrayNPE(bas, h),
|
||||
false));
|
||||
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));
|
||||
}
|
||||
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(
|
||||
"null buffer", bav, vh, h -> testArrayNPE(bbs, h),
|
||||
false));
|
||||
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));
|
||||
if (bbs.s.isDirect()) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("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 testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = null;
|
||||
int ci = 1;
|
||||
|
||||
checkNPE(() -> {
|
||||
char x = (char) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = null;
|
||||
int ci = 1;
|
||||
|
||||
checkNPE(() -> {
|
||||
char x = (char) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
char x = (char) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
char x = (char) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
char x = (char) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
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.compareAndExchange(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.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
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.getAndSetAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXorRelease(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 && array.isDirect()) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (array.isDirect()) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchange(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.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
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.getAndSetAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
|
||||
});
|
||||
} else {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char r = (char) vh.compareAndExchange(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.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
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.getAndSetAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
char o = (char) vh.getAndBitwiseXorRelease(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;
|
||||
|
||||
checkAIOOBE(() -> {
|
||||
char x = (char) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkAIOOBE(() -> {
|
||||
vh.set(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);
|
||||
});
|
||||
}
|
||||
|
||||
if (array.isDirect()) {
|
||||
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(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;
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
char x = (char) vh.get(array, i);
|
||||
assertEquals(VALUE_1, x, "get char value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
char x = (char) vh.get(array, i);
|
||||
assertEquals(VALUE_1, x, "get char value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
char x = (char) vh.getVolatile(array, i);
|
||||
assertEquals(VALUE_2, x, "setVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
char x = (char) vh.getAcquire(array, i);
|
||||
assertEquals(VALUE_1, x, "setRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
char x = (char) vh.getOpaque(array, i);
|
||||
assertEquals(VALUE_2, x, "setOpaque char value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
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 = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
|
||||
|
||||
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(v, x, "get char value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
char x = (char) vh.getVolatile(array, i);
|
||||
assertEquals(v, x, "getVolatile char value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
char x = (char) vh.getAcquire(array, i);
|
||||
assertEquals(v, x, "getRelease char value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
char x = (char) vh.getOpaque(array, i);
|
||||
assertEquals(v, x, "getOpaque char value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,836 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
* @bug 8154556
|
||||
* @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations
|
||||
* to hit compilation thresholds
|
||||
* @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort
|
||||
* @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestByteArrayAsShort
|
||||
* @run junit/othervm/timeout=360 -Diters=2000 -XX:CompileThresholdScaling=0.1 -XX:-TieredCompilation VarHandleTestByteArrayAsShort
|
||||
*/
|
||||
|
||||
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.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
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)0xFFFE;
|
||||
|
||||
|
||||
@Override
|
||||
public List<VarHandleSource> setupVarHandleSources(boolean same) {
|
||||
// Combinations of VarHandle byte[] or ByteBuffer
|
||||
List<VarHandleSource> vhss = new ArrayList<>();
|
||||
for (MemoryMode endianess : List.of(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
|
||||
|
||||
ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
|
||||
? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
|
||||
|
||||
Class<?> arrayType;
|
||||
if (same) {
|
||||
arrayType = short[].class;
|
||||
}
|
||||
else {
|
||||
arrayType = int[].class;
|
||||
}
|
||||
VarHandleSource aeh = new VarHandleSource(
|
||||
MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(aeh);
|
||||
|
||||
VarHandleSource bbh = new VarHandleSource(
|
||||
MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
|
||||
endianess, MemoryMode.READ_WRITE);
|
||||
vhss.add(bbh);
|
||||
}
|
||||
return vhss;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
VarHandle[] vhs1 = setupVarHandleSources(true).stream().
|
||||
map(vhs -> vhs.s).toArray(VarHandle[]::new);
|
||||
VarHandle[] vhs2 = setupVarHandleSources(true).stream().
|
||||
map(vhs -> vhs.s).toArray(VarHandle[]::new);
|
||||
|
||||
for (int i = 0; i < vhs1.length; i++) {
|
||||
for (int j = 0; j < vhs1.length; j++) {
|
||||
if (i != j) {
|
||||
assertNotEquals(vhs1[i], vhs1[j]);
|
||||
assertNotEquals(vhs1[i], vhs2[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VarHandle[] vhs3 = setupVarHandleSources(false).stream().
|
||||
map(vhs -> vhs.s).toArray(VarHandle[]::new);
|
||||
for (int i = 0; i < vhs1.length; i++) {
|
||||
assertNotEquals(vhs1[i], vhs3[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("VarHandleBaseByteArrayTest#varHandlesProvider")
|
||||
public void testIsAccessModeSupported(VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
|
||||
|
||||
if (vhs.supportsAtomicAccess) {
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
|
||||
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
|
||||
} else {
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
|
||||
}
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
|
||||
|
||||
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
|
||||
assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("typesProvider")
|
||||
public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
|
||||
assertEquals(short.class, vh.varType());
|
||||
|
||||
assertEquals(pts, vh.coordinateTypes());
|
||||
|
||||
testTypes(vh);
|
||||
}
|
||||
|
||||
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(
|
||||
"null array", bav, vh, h -> testArrayNPE(bas, h),
|
||||
false));
|
||||
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));
|
||||
}
|
||||
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(
|
||||
"null buffer", bav, vh, h -> testArrayNPE(bbs, h),
|
||||
false));
|
||||
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));
|
||||
if (bbs.s.isDirect()) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("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 testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
byte[] array = null;
|
||||
int ci = 1;
|
||||
|
||||
checkNPE(() -> {
|
||||
short x = (short) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
}
|
||||
|
||||
static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = null;
|
||||
int ci = 1;
|
||||
|
||||
checkNPE(() -> {
|
||||
short x = (short) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.set(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
short x = (short) vh.getVolatile(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
short x = (short) vh.getAcquire(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
short x = (short) vh.getOpaque(array, ci);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkNPE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
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.compareAndExchange(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.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
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.getAndSetAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAddAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAnd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXor(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXorRelease(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 && array.isDirect()) {
|
||||
checkROBE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkROBE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (array.isDirect()) {
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchange(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.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
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.getAndSetAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAddAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAnd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXor(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
|
||||
});
|
||||
} else {
|
||||
checkISE(() -> {
|
||||
vh.setVolatile(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkISE(() -> {
|
||||
vh.setOpaque(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short r = (short) vh.compareAndExchange(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.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
|
||||
});
|
||||
|
||||
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.getAndSetAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAddAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
|
||||
});
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAnd(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXor(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
|
||||
});
|
||||
|
||||
checkUOE(() -> {
|
||||
short o = (short) vh.getAndBitwiseXorRelease(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;
|
||||
|
||||
checkAIOOBE(() -> {
|
||||
short x = (short) vh.get(array, ci);
|
||||
});
|
||||
|
||||
checkAIOOBE(() -> {
|
||||
vh.set(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);
|
||||
});
|
||||
}
|
||||
|
||||
if (array.isDirect()) {
|
||||
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(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;
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.length - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
short x = (short) vh.get(array, i);
|
||||
assertEquals(VALUE_1, x, "get short value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
bs.fill((byte) 0xff);
|
||||
int length = array.limit() - SIZE + 1;
|
||||
for (int i = 0; i < length; i++) {
|
||||
boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
|
||||
|
||||
// Plain
|
||||
{
|
||||
vh.set(array, i, VALUE_1);
|
||||
short x = (short) vh.get(array, i);
|
||||
assertEquals(VALUE_1, x, "get short value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
vh.setVolatile(array, i, VALUE_2);
|
||||
short x = (short) vh.getVolatile(array, i);
|
||||
assertEquals(VALUE_2, x, "setVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
vh.setRelease(array, i, VALUE_1);
|
||||
short x = (short) vh.getAcquire(array, i);
|
||||
assertEquals(VALUE_1, x, "setRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
vh.setOpaque(array, i, VALUE_2);
|
||||
short x = (short) vh.getOpaque(array, i);
|
||||
assertEquals(VALUE_2, x, "setOpaque short value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
|
||||
VarHandle vh = vhs.s;
|
||||
ByteBuffer array = bs.s;
|
||||
|
||||
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 = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
|
||||
|
||||
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(v, x, "get short value");
|
||||
}
|
||||
|
||||
if (iAligned) {
|
||||
// Volatile
|
||||
{
|
||||
short x = (short) vh.getVolatile(array, i);
|
||||
assertEquals(v, x, "getVolatile short value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
short x = (short) vh.getAcquire(array, i);
|
||||
assertEquals(v, x, "getRelease short value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
short x = (short) vh.getOpaque(array, i);
|
||||
assertEquals(v, x, "getOpaque short value");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
395
test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java
Normal file
395
test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, 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
|
||||
* @modules java.base/jdk.internal.access.foreign
|
||||
* @modules java.base/jdk.internal.foreign.layout
|
||||
*
|
||||
* @run junit/othervm -Xverify:all
|
||||
* -Djdk.internal.foreign.SHOULD_ADAPT_HANDLES=false
|
||||
* VarHandleTestExact
|
||||
* @run junit/othervm -Xverify:all
|
||||
* -Djdk.internal.foreign.SHOULD_ADAPT_HANDLES=false
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true
|
||||
* VarHandleTestExact
|
||||
* @run junit/othervm -Xverify:all
|
||||
* -Djdk.internal.foreign.SHOULD_ADAPT_HANDLES=false
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false
|
||||
* VarHandleTestExact
|
||||
* @run junit/othervm -Xverify:all
|
||||
* -Djdk.internal.foreign.SHOULD_ADAPT_HANDLES=false
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false
|
||||
* -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true
|
||||
* VarHandleTestExact
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
import jdk.internal.foreign.layout.ValueLayouts;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.invoke.WrongMethodTypeException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class VarHandleTestExact {
|
||||
|
||||
private static class Widget {
|
||||
static Object objectField_SRW;
|
||||
static long longField_SRW;
|
||||
static double doubleField_SRW;
|
||||
static Long aLongField_SRW;
|
||||
|
||||
Object objectField_RW;
|
||||
long longField_RW;
|
||||
double doubleField_RW;
|
||||
Long aLongField_RW;
|
||||
|
||||
final static Object objectField_SRO = new Object();
|
||||
final static long longField_SRO = 1234L;
|
||||
final static double doubleField_SRO = 1234D;
|
||||
final static Long aLongField_SRO = 1234L;
|
||||
|
||||
final Object objectField_RO = new Object();
|
||||
final long longField_RO = 1234L;
|
||||
final double doubleField_RO = 1234D;
|
||||
final Long aLongField_RO = 1234L;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataObjectAccess")
|
||||
public void testExactSet(String fieldBaseName, Class<?> fieldType, boolean ro, Object testValue,
|
||||
SetX setter, GetX getter,
|
||||
SetStaticX staticSetter, GetStaticX staticGetter)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Assumptions.assumeFalse(ro, "Can not test setter with read only field");
|
||||
VarHandle vh = MethodHandles.lookup().findVarHandle(Widget.class, fieldBaseName + "_RW", fieldType);
|
||||
Widget w = new Widget();
|
||||
|
||||
doTest(vh,
|
||||
tvh -> tvh.set(w, testValue),
|
||||
tvh -> setter.set(tvh, w, testValue),
|
||||
".*\\Qhandle's method type (Widget," + fieldType.getSimpleName() + ")void \\E.*");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataObjectAccess")
|
||||
public void testExactGet(String fieldBaseName, Class<?> fieldType, boolean ro, Object testValue,
|
||||
SetX setter, GetX getter,
|
||||
SetStaticX staticSetter, GetStaticX staticGetter)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
VarHandle vh = MethodHandles.lookup().findVarHandle(Widget.class, fieldBaseName + (ro ? "_RO" : "_RW"), fieldType);
|
||||
Widget w = new Widget();
|
||||
|
||||
doTest(vh,
|
||||
tvh -> tvh.get(w),
|
||||
tvh -> getter.get(tvh, w),
|
||||
".*\\Qhandle's method type (Widget)" + fieldType.getSimpleName() + " \\E.*");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataObjectAccess")
|
||||
public void testExactSetStatic(String fieldBaseName, Class<?> fieldType, boolean ro, Object testValue,
|
||||
SetX setter, GetX getter,
|
||||
SetStaticX staticSetter, GetStaticX staticGetter)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Assumptions.assumeFalse(ro, "Can not test setter with read only field");
|
||||
VarHandle vh = MethodHandles.lookup().findStaticVarHandle(Widget.class, fieldBaseName + "_SRW", fieldType);
|
||||
|
||||
doTest(vh,
|
||||
tvh -> tvh.set(testValue),
|
||||
tvh -> staticSetter.set(tvh, testValue),
|
||||
".*\\Qhandle's method type (" + fieldType.getSimpleName() + ")void \\E.*");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataObjectAccess")
|
||||
public void testExactGetStatic(String fieldBaseName, Class<?> fieldType, boolean ro, Object testValue,
|
||||
SetX setter, GetX getter,
|
||||
SetStaticX staticSetter, GetStaticX staticGetter)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
VarHandle vh = MethodHandles.lookup().findStaticVarHandle(Widget.class, fieldBaseName + (ro ? "_SRO" : "_SRW"), fieldType);
|
||||
|
||||
doTest(vh,
|
||||
tvh -> tvh.get(),
|
||||
tvh -> staticGetter.get(tvh),
|
||||
".*\\Qhandle's method type ()" + fieldType.getSimpleName() + " \\E.*");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataSetArray")
|
||||
public void testExactArraySet(Class<?> arrayClass, Object testValue, SetArrayX setter) {
|
||||
VarHandle vh = MethodHandles.arrayElementVarHandle(arrayClass);
|
||||
Object arr = Array.newInstance(arrayClass.componentType(), 1);
|
||||
|
||||
doTest(vh,
|
||||
tvh -> tvh.set(arr, 0, testValue),
|
||||
tvh -> setter.set(tvh, arr, testValue),
|
||||
".*\\Qhandle's method type (" + arrayClass.getSimpleName() + ",int," + arrayClass.componentType().getSimpleName() + ")void \\E.*");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataSetBuffer")
|
||||
public void testExactBufferSet(Class<?> arrayClass, Object testValue, SetBufferX setter) {
|
||||
VarHandle vh = MethodHandles.byteBufferViewVarHandle(arrayClass, ByteOrder.nativeOrder());
|
||||
ByteBuffer buff = ByteBuffer.allocateDirect(8);
|
||||
|
||||
doTest(vh,
|
||||
tvh -> tvh.set(buff, 0, testValue),
|
||||
tvh -> setter.set(tvh, buff, testValue),
|
||||
".*\\Qhandle's method type (ByteBuffer,int," + arrayClass.componentType().getSimpleName() + ")void \\E.*");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataSetMemorySegment")
|
||||
public void testExactSegmentSet(Class<?> carrier, Object testValue, SetSegmentX setter) {
|
||||
VarHandle vh = ValueLayouts.valueLayout(carrier, ByteOrder.nativeOrder()).varHandle();
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment seg = arena.allocate(8);
|
||||
doTest(vh,
|
||||
tvh -> tvh.set(seg, 0L, testValue),
|
||||
tvh -> setter.set(tvh, seg, 0L, testValue),
|
||||
".*\\Qhandle's method type (MemorySegment,long," + carrier.getSimpleName() + ")void \\E.*");
|
||||
}
|
||||
}
|
||||
|
||||
private static void doTest(VarHandle invokeHandle, Consumer<VarHandle> invokeTest,
|
||||
Consumer<VarHandle> invokeExactTest, String expectedMessage) {
|
||||
assertFalse(invokeHandle.hasInvokeExactBehavior());
|
||||
assertSame(invokeHandle, invokeHandle.withInvokeBehavior());
|
||||
try {
|
||||
invokeTest.accept(invokeHandle);
|
||||
} catch (WrongMethodTypeException wmte) {
|
||||
fail("Unexpected exception", wmte);
|
||||
}
|
||||
|
||||
VarHandle invokeExactHandle = invokeHandle.withInvokeExactBehavior();
|
||||
assertTrue(invokeExactHandle.hasInvokeExactBehavior());
|
||||
assertSame(invokeExactHandle, invokeExactHandle.withInvokeExactBehavior());
|
||||
try {
|
||||
invokeExactTest.accept(invokeExactHandle); // should throw
|
||||
fail("Exception expected");
|
||||
} catch (WrongMethodTypeException wmte) {
|
||||
assertMatches(wmte.getMessage(), expectedMessage);
|
||||
}
|
||||
|
||||
// try going back
|
||||
VarHandle invokeHandle2 = invokeExactHandle.withInvokeBehavior();
|
||||
assertFalse(invokeHandle2.hasInvokeExactBehavior());
|
||||
try {
|
||||
invokeTest.accept(invokeHandle2);
|
||||
} catch (WrongMethodTypeException wmte) {
|
||||
fail("Unexpected exception", wmte);
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertMatches(String str, String pattern) {
|
||||
if (!str.matches(pattern)) {
|
||||
throw new AssertionError("'" + str + "' did not match the pattern '" + pattern + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
private interface SetX {
|
||||
void set(VarHandle vh, Widget w, Object testValue);
|
||||
}
|
||||
|
||||
private interface SetStaticX {
|
||||
void set(VarHandle vh, Object testValue);
|
||||
}
|
||||
|
||||
private interface GetX {
|
||||
void get(VarHandle vh, Widget w);
|
||||
}
|
||||
|
||||
private interface GetStaticX {
|
||||
void get(VarHandle vh);
|
||||
}
|
||||
|
||||
private interface SetArrayX {
|
||||
void set(VarHandle vh, Object array, Object testValue);
|
||||
}
|
||||
|
||||
private interface SetBufferX {
|
||||
void set(VarHandle vh, ByteBuffer buff, Object testValue);
|
||||
}
|
||||
|
||||
private interface SetSegmentX {
|
||||
void set(VarHandle vh, MemorySegment segment, long offset, Object testValue);
|
||||
}
|
||||
|
||||
private static void consume(Object o) {}
|
||||
|
||||
private static void testCaseObjectAccess(List<Object[]> cases, String fieldBaseName, Class<?> fieldType, Object testValue,
|
||||
SetX setter, GetX getter,
|
||||
SetStaticX staticSetter, GetStaticX staticGetter) {
|
||||
cases.add(new Object[] { fieldBaseName, fieldType, false, testValue, setter, getter, staticSetter, staticGetter });
|
||||
cases.add(new Object[] { fieldBaseName, fieldType, true, testValue, setter, getter, staticSetter, staticGetter });
|
||||
}
|
||||
|
||||
private static void testCaseArraySet(List<Object[]> cases, Class<?> arrayType, Object testValue, SetArrayX setter) {
|
||||
cases.add(new Object[] { arrayType, testValue, setter });
|
||||
}
|
||||
|
||||
private static void testCaseBufferSet(List<Object[]> cases, Class<?> arrayType, Object testValue, SetBufferX setter) {
|
||||
cases.add(new Object[] { arrayType, testValue, setter });
|
||||
}
|
||||
|
||||
private static void testCaseSegmentSet(List<Object[]> cases, Class<?> carrier, Object testValue, SetSegmentX setter) {
|
||||
cases.add(new Object[] { carrier, testValue, setter });
|
||||
}
|
||||
|
||||
public static Object[][] dataObjectAccess() {
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// create a bunch of different sig-poly call sites
|
||||
testCaseObjectAccess(cases, "objectField", Object.class, "abcd",
|
||||
(vh, w, tv) -> vh.set(w, (String) tv),
|
||||
(vh, w) -> consume((String) vh.get(w)),
|
||||
(vh, tv) -> vh.set((String) tv),
|
||||
(vh) -> consume((String) vh.get()));
|
||||
testCaseObjectAccess(cases, "objectField", Object.class, Integer.valueOf(1234),
|
||||
(vh, w, tv) -> vh.set(w, (Integer) tv),
|
||||
(vh, w) -> consume((Integer) vh.get(w)),
|
||||
(vh, tv) -> vh.set((Integer) tv),
|
||||
(vh) -> consume((Integer) vh.get()));
|
||||
testCaseObjectAccess(cases, "longField", long.class, 1234,
|
||||
(vh, w, tv) -> vh.set(w, (int) tv),
|
||||
(vh, w) -> consume((int) vh.get(w)),
|
||||
(vh, tv) -> vh.set((int) tv),
|
||||
(vh) -> consume((int) vh.get()));
|
||||
testCaseObjectAccess(cases, "longField", long.class, (short) 1234,
|
||||
(vh, w, tv) -> vh.set(w, (short) tv),
|
||||
(vh, w) -> consume((short) vh.get(w)),
|
||||
(vh, tv) -> vh.set((short) tv),
|
||||
(vh) -> consume((short) vh.get()));
|
||||
testCaseObjectAccess(cases, "longField", long.class, (char) 1234,
|
||||
(vh, w, tv) -> vh.set(w, (char) tv),
|
||||
(vh, w) -> consume((char) vh.get(w)),
|
||||
(vh, tv) -> vh.set((char) tv),
|
||||
(vh) -> consume((char) vh.get()));
|
||||
testCaseObjectAccess(cases, "longField", long.class, (byte) 1234,
|
||||
(vh, w, tv) -> vh.set(w, (byte) tv),
|
||||
(vh, w) -> consume((byte) vh.get(w)),
|
||||
(vh, tv) -> vh.set((byte) tv),
|
||||
(vh) -> consume((byte) vh.get()));
|
||||
testCaseObjectAccess(cases, "longField", long.class, Long.valueOf(1234L),
|
||||
(vh, w, tv) -> vh.set(w, (Long) tv),
|
||||
(vh, w) -> consume((Long) vh.get(w)),
|
||||
(vh, tv) -> vh.set((Long) tv),
|
||||
(vh) -> consume((Long) vh.get()));
|
||||
testCaseObjectAccess(cases, "doubleField", double.class, 1234F,
|
||||
(vh, w, tv) -> vh.set(w, (float) tv),
|
||||
(vh, w) -> consume((float) vh.get(w)),
|
||||
(vh, tv) -> vh.set((float) tv),
|
||||
(vh) -> consume((float) vh.get()));
|
||||
testCaseObjectAccess(cases, "doubleField", double.class, 1234,
|
||||
(vh, w, tv) -> vh.set(w, (int) tv),
|
||||
(vh, w) -> consume((int) vh.get(w)),
|
||||
(vh, tv) -> vh.set((int) tv),
|
||||
(vh) -> consume((int) vh.get()));
|
||||
testCaseObjectAccess(cases, "doubleField", double.class, 1234L,
|
||||
(vh, w, tv) -> vh.set(w, (long) tv),
|
||||
(vh, w) -> consume((long) vh.get(w)),
|
||||
(vh, tv) -> vh.set((long) tv),
|
||||
(vh) -> consume((long) vh.get()));
|
||||
testCaseObjectAccess(cases, "doubleField", double.class, Double.valueOf(1234D),
|
||||
(vh, w, tv) -> vh.set(w, (Double) tv),
|
||||
(vh, w) -> consume((Double) vh.get(w)),
|
||||
(vh, tv) -> vh.set((Double) tv),
|
||||
(vh) -> consume((Double) vh.get()));
|
||||
testCaseObjectAccess(cases, "aLongField", Long.class, 1234L,
|
||||
(vh, w, tv) -> vh.set(w, (long) tv),
|
||||
(vh, w) -> consume((long) vh.get(w)),
|
||||
(vh, tv) -> vh.set((long) tv),
|
||||
(vh) -> consume((long) vh.get()));
|
||||
|
||||
return cases.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
public static Object[][] dataSetArray() {
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// create a bunch of different sig-poly call sites
|
||||
testCaseArraySet(cases, Object[].class, "abcd", (vh, arr, tv) -> vh.set((Object[]) arr, 0, (String) tv));
|
||||
testCaseArraySet(cases, Object[].class, Integer.valueOf(1234), (vh, arr, tv) -> vh.set((Object[]) arr, (Integer) tv));
|
||||
testCaseArraySet(cases, long[].class, 1234, (vh, arr, tv) -> vh.set((long[]) arr, 0, (int) tv));
|
||||
testCaseArraySet(cases, long[].class, (short) 1234, (vh, arr, tv) -> vh.set((long[]) arr, 0, (short) tv));
|
||||
testCaseArraySet(cases, long[].class, (char) 1234, (vh, arr, tv) -> vh.set((long[]) arr, 0, (char) tv));
|
||||
testCaseArraySet(cases, long[].class, (byte) 1234, (vh, arr, tv) -> vh.set((long[]) arr, 0, (byte) tv));
|
||||
testCaseArraySet(cases, long[].class, Long.valueOf(1234L), (vh, arr, tv) -> vh.set((long[]) arr, 0, (Long) tv));
|
||||
testCaseArraySet(cases, double[].class, 1234F, (vh, arr, tv) -> vh.set((double[]) arr, 0, (float) tv));
|
||||
testCaseArraySet(cases, double[].class, 1234, (vh, arr, tv) -> vh.set((double[]) arr, 0, (int) tv));
|
||||
testCaseArraySet(cases, double[].class, 1234L, (vh, arr, tv) -> vh.set((double[]) arr, 0, (long) tv));
|
||||
testCaseArraySet(cases, double[].class, Double.valueOf(1234D), (vh, arr, tv) -> vh.set((double[]) arr, 0, (Double) tv));
|
||||
testCaseArraySet(cases, Long[].class, 1234L, (vh, arr, tv) -> vh.set((Long[]) arr, 0, (long) tv));
|
||||
|
||||
return cases.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
public static Object[][] dataSetBuffer() {
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// create a bunch of different sig-poly call sites
|
||||
testCaseBufferSet(cases, long[].class, 1234, (vh, buff, tv) -> vh.set(buff, 0, (int) tv));
|
||||
testCaseBufferSet(cases, long[].class, (short) 1234, (vh, buff, tv) -> vh.set(buff, 0, (short) tv));
|
||||
testCaseBufferSet(cases, long[].class, (char) 1234, (vh, buff, tv) -> vh.set(buff, 0, (char) tv));
|
||||
testCaseBufferSet(cases, long[].class, (byte) 1234, (vh, buff, tv) -> vh.set(buff, 0, (byte) tv));
|
||||
testCaseBufferSet(cases, long[].class, Long.valueOf(1234L), (vh, buff, tv) -> vh.set(buff, 0, (Long) tv));
|
||||
testCaseBufferSet(cases, double[].class, 1234F, (vh, buff, tv) -> vh.set(buff, 0, (float) tv));
|
||||
testCaseBufferSet(cases, double[].class, 1234, (vh, buff, tv) -> vh.set(buff, 0, (int) tv));
|
||||
testCaseBufferSet(cases, double[].class, 1234L, (vh, buff, tv) -> vh.set(buff, 0, (long) tv));
|
||||
testCaseBufferSet(cases, double[].class, Double.valueOf(1234D), (vh, buff, tv) -> vh.set(buff, 0, (Double) tv));
|
||||
|
||||
return cases.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
public static Object[][] dataSetMemorySegment() {
|
||||
List<Object[]> cases = new ArrayList<>();
|
||||
|
||||
// create a bunch of different sig-poly call sites
|
||||
testCaseSegmentSet(cases, long.class, 1234, (vh, seg, off, tv) -> vh.set((MemorySegment) seg, off, (int) tv));
|
||||
testCaseSegmentSet(cases, long.class, (char) 1234, (vh, seg, off, tv) -> vh.set((MemorySegment) seg, off, (char) tv));
|
||||
testCaseSegmentSet(cases, long.class, (short) 1234, (vh, seg, off, tv) -> vh.set((MemorySegment) seg, off, (short) tv));
|
||||
testCaseSegmentSet(cases, long.class, (byte) 1234, (vh, seg, off, tv) -> vh.set((MemorySegment) seg, off, (byte) tv));
|
||||
testCaseSegmentSet(cases, double.class, 1234F, (vh, seg, off, tv) -> vh.set((MemorySegment) seg, off, (float) tv));
|
||||
|
||||
return cases.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,858 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
* @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations
|
||||
* to hit compilation thresholds
|
||||
* @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessDouble
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
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;
|
||||
|
||||
@BeforeAll
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("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(1.0d, x, "set double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, 1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "setOpaque double value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0d, 2.0d);
|
||||
assertEquals(r, true, "success compareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "success compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0d, 3.0d);
|
||||
assertEquals(r, false, "failing compareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "failing compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0d, 1.0d);
|
||||
assertEquals(r, 2.0d, "success compareAndExchange double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "success compareAndExchange double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0d, 3.0d);
|
||||
assertEquals(r, 1.0d, "failing compareAndExchange double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "failing compareAndExchange double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0d, 2.0d);
|
||||
assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "success compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0d, 3.0d);
|
||||
assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "failing compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0d, 1.0d);
|
||||
assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "success compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0d, 3.0d);
|
||||
assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "failing compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 1.0d, 2.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "success weakCompareAndSetPlain double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "failing weakCompareAndSetPlain double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 2.0d, 1.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "success weakCompareAndSetAcquire double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "failing weakCompareAndSetAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 1.0d, 2.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "success weakCompareAndSetRelease double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "failing weakCompareAndSetRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = false;
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 2.0d, 1.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "success weakCompareAndSet double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0d, x, "failing weakCompareAndSet double value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0d, x, "getAndSet double value");
|
||||
}
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndAdd double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAdd double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndAddAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAddAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndAddRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAddRelease double value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
|
||||
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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(1.0d, x, "set double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
|
||||
assertEquals(2.0d, x, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
|
||||
assertEquals(1.0d, x, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
|
||||
assertEquals(2.0d, x, "setOpaque double value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0d, 2.0d);
|
||||
assertEquals(r, true, "success compareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "success compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0d, 3.0d);
|
||||
assertEquals(r, false, "failing compareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "failing compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0d, 1.0d);
|
||||
assertEquals(r, 2.0d, "success compareAndExchange double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "success compareAndExchange double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0d, 3.0d);
|
||||
assertEquals(r, 1.0d, "failing compareAndExchange double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "failing compareAndExchange double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0d, 2.0d);
|
||||
assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "success compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0d, 3.0d);
|
||||
assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "failing compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0d, 1.0d);
|
||||
assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "success compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0d, 3.0d);
|
||||
assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "failing compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(1.0d, 2.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "success weakCompareAndSetPlain double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "failing weakCompareAndSetPlain double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(2.0d, 1.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "success weakCompareAndSetAcquire double");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = (boolean) mh.invokeExact(2.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "failing weakCompareAndSetAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(1.0d, 2.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "success weakCompareAndSetRelease double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "failing weakCompareAndSetRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(2.0d, 1.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "success weakCompareAndSet double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0d, x, "failing weakCompareAndSetRe double value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2.0d);
|
||||
assertEquals(1.0d, o, "getAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "getAndSet double value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(2.0d);
|
||||
assertEquals(1.0d, o, "getAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "getAndSetAcquire double value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(2.0d);
|
||||
assertEquals(1.0d, o, "getAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0d, x, "getAndSetRelease double value");
|
||||
}
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(2.0d);
|
||||
assertEquals(1.0d, o, "getAndAdd double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAdd double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(2.0d);
|
||||
assertEquals(1.0d, o, "getAndAddAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAddAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(2.0d);
|
||||
assertEquals(1.0d, o, "getAndAddRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAddRelease double value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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(1.0d, x, "get double value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "setVolatile double value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 1.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "setRelease double value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 2.0d);
|
||||
double x = (double) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "setOpaque double value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0d, 2.0d);
|
||||
assertEquals(r, true, "success compareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "success compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0d, 3.0d);
|
||||
assertEquals(r, false, "failing compareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "failing compareAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0d, 1.0d);
|
||||
assertEquals(r, 2.0d, "success compareAndExchange double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "success compareAndExchange double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0d, 3.0d);
|
||||
assertEquals(r, 1.0d, "failing compareAndExchange double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "failing compareAndExchange double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0d, 2.0d);
|
||||
assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "success compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0d, 3.0d);
|
||||
assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "failing compareAndExchangeAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0d, 1.0d);
|
||||
assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "success compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0d, 3.0d);
|
||||
assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "failing compareAndExchangeRelease double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 1.0d, 2.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "success weakCompareAndSetPlain double value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "failing weakCompareAndSetPlain double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 2.0d, 1.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "success weakCompareAndSetAcquire double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "failing weakCompareAndSetAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 1.0d, 2.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "success weakCompareAndSetRelease double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 1.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "failing weakCompareAndSetAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 2.0d, 1.0d);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "success weakCompareAndSet double");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0d, 3.0d);
|
||||
assertEquals(success, false, "failing weakCompareAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0d, x, "failing weakCompareAndSet double value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndSet double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "getAndSet double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndSetAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "getAndSetAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndSetRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0d, x, "getAndSetRelease double value");
|
||||
}
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndAdd double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAdd double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndAddAcquire double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAddAcquire double value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
|
||||
|
||||
double o = (double) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 2.0d);
|
||||
assertEquals(1.0d, o, "getAndAddRelease double");
|
||||
double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals((double)(1.0d + 2.0d), x, "getAndAddRelease double value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
double[] array = new double[10];
|
||||
|
||||
final int i = 0;
|
||||
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
double x = (double) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1.0d, 2.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
double r = (double) hs.get(am).invokeExact(array, ci, 2.0d, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
double o = (double) hs.get(am).invokeExact(array, ci, 1.0d);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
double o = (double) hs.get(am).invokeExact(array, ci, 3.0d);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,858 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
* @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations
|
||||
* to hit compilation thresholds
|
||||
* @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessFloat
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
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;
|
||||
|
||||
@BeforeAll
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("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(1.0f, x, "set float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, 1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "setOpaque float value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0f, 2.0f);
|
||||
assertEquals(r, true, "success compareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "success compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0f, 3.0f);
|
||||
assertEquals(r, false, "failing compareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "failing compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0f, 1.0f);
|
||||
assertEquals(r, 2.0f, "success compareAndExchange float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "success compareAndExchange float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0f, 3.0f);
|
||||
assertEquals(r, 1.0f, "failing compareAndExchange float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "failing compareAndExchange float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0f, 2.0f);
|
||||
assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "success compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0f, 3.0f);
|
||||
assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "failing compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0f, 1.0f);
|
||||
assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "success compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0f, 3.0f);
|
||||
assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "failing compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 1.0f, 2.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "success weakCompareAndSetPlain float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "failing weakCompareAndSetPlain float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 2.0f, 1.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "success weakCompareAndSetAcquire float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "failing weakCompareAndSetAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 1.0f, 2.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "success weakCompareAndSetRelease float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "failing weakCompareAndSetRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = false;
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, 2.0f, 1.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "success weakCompareAndSet float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(1.0f, x, "failing weakCompareAndSet float value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals(2.0f, x, "getAndSet float value");
|
||||
}
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndAdd float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAdd float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndAddAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAddAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndAddRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAddRelease float value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
|
||||
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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(1.0f, x, "set float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
|
||||
assertEquals(2.0f, x, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
|
||||
assertEquals(1.0f, x, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
|
||||
assertEquals(2.0f, x, "setOpaque float value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0f, 2.0f);
|
||||
assertEquals(r, true, "success compareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "success compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0f, 3.0f);
|
||||
assertEquals(r, false, "failing compareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "failing compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0f, 1.0f);
|
||||
assertEquals(r, 2.0f, "success compareAndExchange float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "success compareAndExchange float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0f, 3.0f);
|
||||
assertEquals(r, 1.0f, "failing compareAndExchange float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "failing compareAndExchange float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0f, 2.0f);
|
||||
assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "success compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0f, 3.0f);
|
||||
assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "failing compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0f, 1.0f);
|
||||
assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "success compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0f, 3.0f);
|
||||
assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "failing compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(1.0f, 2.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "success weakCompareAndSetPlain float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "failing weakCompareAndSetPlain float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(2.0f, 1.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "success weakCompareAndSetAcquire float");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = (boolean) mh.invokeExact(2.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "failing weakCompareAndSetAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(1.0f, 2.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "success weakCompareAndSetRelease float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "failing weakCompareAndSetRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(2.0f, 1.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "success weakCompareAndSet float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(1.0f, x, "failing weakCompareAndSetRe float value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2.0f);
|
||||
assertEquals(1.0f, o, "getAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "getAndSet float value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(2.0f);
|
||||
assertEquals(1.0f, o, "getAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "getAndSetAcquire float value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(2.0f);
|
||||
assertEquals(1.0f, o, "getAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals(2.0f, x, "getAndSetRelease float value");
|
||||
}
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(2.0f);
|
||||
assertEquals(1.0f, o, "getAndAdd float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAdd float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(2.0f);
|
||||
assertEquals(1.0f, o, "getAndAddAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAddAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(2.0f);
|
||||
assertEquals(1.0f, o, "getAndAddRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAddRelease float value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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(1.0f, x, "get float value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "setVolatile float value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 1.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "setRelease float value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 2.0f);
|
||||
float x = (float) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "setOpaque float value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0f, 2.0f);
|
||||
assertEquals(r, true, "success compareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "success compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0f, 3.0f);
|
||||
assertEquals(r, false, "failing compareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "failing compareAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0f, 1.0f);
|
||||
assertEquals(r, 2.0f, "success compareAndExchange float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "success compareAndExchange float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0f, 3.0f);
|
||||
assertEquals(r, 1.0f, "failing compareAndExchange float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "failing compareAndExchange float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0f, 2.0f);
|
||||
assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "success compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0f, 3.0f);
|
||||
assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "failing compareAndExchangeAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0f, 1.0f);
|
||||
assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "success compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0f, 3.0f);
|
||||
assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "failing compareAndExchangeRelease float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 1.0f, 2.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "success weakCompareAndSetPlain float value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "failing weakCompareAndSetPlain float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 2.0f, 1.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "success weakCompareAndSetAcquire float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "failing weakCompareAndSetAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 1.0f, 2.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "success weakCompareAndSetRelease float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 1.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "failing weakCompareAndSetAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, 2.0f, 1.0f);
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "success weakCompareAndSet float");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0f, 3.0f);
|
||||
assertEquals(success, false, "failing weakCompareAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(1.0f, x, "failing weakCompareAndSet float value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndSet float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "getAndSet float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndSetAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "getAndSetAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndSetRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals(2.0f, x, "getAndSetRelease float value");
|
||||
}
|
||||
|
||||
// get and add, add and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndAdd float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAdd float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndAddAcquire float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAddAcquire float value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
|
||||
|
||||
float o = (float) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 2.0f);
|
||||
assertEquals(1.0f, o, "getAndAddRelease float");
|
||||
float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals((float)(1.0f + 2.0f), x, "getAndAddRelease float value");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
float[] array = new float[10];
|
||||
|
||||
final int i = 0;
|
||||
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
float x = (float) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1.0f, 2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
float r = (float) hs.get(am).invokeExact(array, ci, 2.0f, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
float o = (float) hs.get(am).invokeExact(array, ci, 1.0f);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
float o = (float) hs.get(am).invokeExact(array, ci, 3.0f);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,787 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2025, 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
|
||||
* @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations
|
||||
* to hit compilation thresholds
|
||||
* @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessString
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
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;
|
||||
|
||||
@BeforeAll
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("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("foo", x, "set String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
|
||||
assertEquals("bar", x, "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, "foo");
|
||||
String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
|
||||
assertEquals("foo", x, "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
|
||||
assertEquals("bar", x, "setOpaque String value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(recv, "foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, "foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, "foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchange String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "success compareAndExchange String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchange String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "failing compareAndExchange String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, "foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, "foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, "foo", "bar");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "success weakCompareAndSetPlain String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, "foo", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "failing weakCompareAndSetPlain String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, "bar", "foo");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "success weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "failing weakCompareAndSetAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, "foo", "bar");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "success weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "failing weakCompareAndSetRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = false;
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(recv, "bar", "foo");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "success weakCompareAndSet String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "bar", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("foo", x, "failing weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar");
|
||||
assertEquals("foo", o, "getAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
|
||||
assertEquals("bar", x, "getAndSet String value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
|
||||
checkUOE(am, () -> {
|
||||
String r = (String) hs.get(am).invokeExact(recv, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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("foo", x, "set String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact("bar");
|
||||
String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
|
||||
assertEquals("bar", x, "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact("foo");
|
||||
String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
|
||||
assertEquals("foo", x, "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact("bar");
|
||||
String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
|
||||
assertEquals("bar", x, "setOpaque String value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact("foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact("foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact("foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact("bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchange String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "success compareAndExchange String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact("bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchange String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "failing compareAndExchange String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact("foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact("foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact("bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact("bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact("foo", "bar");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "success weakCompareAndSetPlain String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact("foo", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "failing weakCompareAndSetPlain String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact("bar", "foo");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "success weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = (boolean) mh.invokeExact("bar", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "failing weakCompareAndSetAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact("foo", "bar");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "success weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "failing weakCompareAndSetRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact("bar", "foo");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "success weakCompareAndSet String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("bar", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("foo", x, "failing weakCompareAndSetRe String value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact("foo");
|
||||
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar");
|
||||
assertEquals("foo", o, "getAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "getAndSet String value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact("foo");
|
||||
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact("bar");
|
||||
assertEquals("foo", o, "getAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "getAndSetAcquire String value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact("foo");
|
||||
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact("bar");
|
||||
assertEquals("foo", o, "getAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact();
|
||||
assertEquals("bar", x, "getAndSetRelease String value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void testStaticFieldUnsupported(Handles hs) throws Throwable {
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
|
||||
checkUOE(am, () -> {
|
||||
String r = (String) hs.get(am).invokeExact("foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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("foo", x, "get String value");
|
||||
}
|
||||
|
||||
|
||||
// Volatile
|
||||
{
|
||||
hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
|
||||
assertEquals("bar", x, "setVolatile String value");
|
||||
}
|
||||
|
||||
// Lazy
|
||||
{
|
||||
hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, "foo");
|
||||
String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
|
||||
assertEquals("foo", x, "setRelease String value");
|
||||
}
|
||||
|
||||
// Opaque
|
||||
{
|
||||
hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, "bar");
|
||||
String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
|
||||
assertEquals("bar", x, "setOpaque String value");
|
||||
}
|
||||
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
|
||||
|
||||
// Compare
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, "foo", "bar");
|
||||
assertEquals(r, true, "success compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "success compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, "foo", "baz");
|
||||
assertEquals(r, false, "failing compareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "failing compareAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchange String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "success compareAndExchange String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchange String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "failing compareAndExchange String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, "foo", "bar");
|
||||
assertEquals(r, "foo", "success compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "success compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, "foo", "baz");
|
||||
assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "failing compareAndExchangeAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, "bar", "foo");
|
||||
assertEquals(r, "bar", "success compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "success compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, "bar", "baz");
|
||||
assertEquals(r, "foo", "failing compareAndExchangeRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "failing compareAndExchangeRelease String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, "foo", "bar");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetPlain String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "success weakCompareAndSetPlain String value");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, "foo", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetPlain String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "failing weakCompareAndSetPlain String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, "bar", "foo");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "success weakCompareAndSetAcquire String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "failing weakCompareAndSetAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, "foo", "bar");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "success weakCompareAndSetRelease String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "foo", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "failing weakCompareAndSetAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
|
||||
boolean success = false;
|
||||
for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
|
||||
success = (boolean) mh.invokeExact(array, i, "bar", "foo");
|
||||
if (!success) weakDelay();
|
||||
}
|
||||
assertEquals(success, true, "success weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "success weakCompareAndSet String");
|
||||
}
|
||||
|
||||
{
|
||||
boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "bar", "baz");
|
||||
assertEquals(success, false, "failing weakCompareAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("foo", x, "failing weakCompareAndSet String value");
|
||||
}
|
||||
|
||||
// Compare set and get
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
|
||||
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "bar");
|
||||
assertEquals("foo", o, "getAndSet String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "getAndSet String value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
|
||||
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, "bar");
|
||||
assertEquals("foo", o, "getAndSetAcquire String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "getAndSetAcquire String value");
|
||||
}
|
||||
|
||||
{
|
||||
hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
|
||||
|
||||
String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, "bar");
|
||||
assertEquals("foo", o, "getAndSetRelease String");
|
||||
String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
|
||||
assertEquals("bar", x, "getAndSetRelease String value");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void testArrayUnsupported(Handles hs) throws Throwable {
|
||||
String[] array = new String[10];
|
||||
|
||||
final int i = 0;
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
|
||||
checkUOE(am, () -> {
|
||||
String o = (String) hs.get(am).invokeExact(array, i, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
|
||||
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)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
String x = (String) hs.get(am).invokeExact(array, ci);
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
hs.get(am).invokeExact(array, ci, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
boolean r = (boolean) hs.get(am).invokeExact(array, ci, "foo", "bar");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
String r = (String) hs.get(am).invokeExact(array, ci, "bar", "foo");
|
||||
});
|
||||
}
|
||||
|
||||
for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
|
||||
checkAIOOBE(am, () -> {
|
||||
String o = (String) hs.get(am).invokeExact(array, ci, "foo");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
3255
test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
Normal file
3255
test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2026, 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 junit VarHandleTestReflection
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class VarHandleTestReflection extends VarHandleBaseTest {
|
||||
String string;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
public void methodInvocationArgumentMismatch(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a Method, with no arguments
|
||||
|
||||
Method vhm = VarHandle.class.getMethod(accessMode.methodName(), Object[].class);
|
||||
assertThrows(IllegalArgumentException.class, () -> vhm.invoke(v, new Object[]{}));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
public void methodInvocationMatchingArguments(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
// Try a reflective invoke using a Method, with the minimal required arguments
|
||||
|
||||
Method vhm = VarHandle.class.getMethod(accessMode.methodName(), Object[].class);
|
||||
Object arg = new Object[0];
|
||||
var e = assertThrows(InvocationTargetException.class, () -> vhm.invoke(v, arg));
|
||||
if (!(e.getCause() instanceof UnsupportedOperationException)) {
|
||||
throw new RuntimeException("expected UnsupportedOperationException but got: "
|
||||
+ e.getCause().getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
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.methodName(), Object[].class));
|
||||
// Use invoke to avoid WrongMethodTypeException for
|
||||
// non-signature-polymorphic return types
|
||||
assertThrows(UnsupportedOperationException.class, () -> {
|
||||
Object o = (Object) mh.invoke(v, new Object[]{});
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
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.methodName(), Object[].class));
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
Method im = info.reflectAs(Method.class, MethodHandles.lookup());
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
im.invoke(v, new Object[]{});
|
||||
});
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
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);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> info.reflectAs(Method.class, MethodHandles.lookup()));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("accessModesProvider")
|
||||
public void reflectAsFromFindVirtual(VarHandle.AccessMode accessMode) throws Exception {
|
||||
VarHandle v = handle();
|
||||
|
||||
MethodHandle mh = MethodHandles.publicLookup().findVirtual(
|
||||
VarHandle.class, accessMode.methodName(), v.accessModeType(accessMode));
|
||||
|
||||
MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> 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
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2026, 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
|
||||
* @bug 8152645 8216558
|
||||
* @summary test field lookup accessibility of MethodHandles and VarHandles
|
||||
* @compile TestFieldLookupAccessibility.java
|
||||
* pkg/A.java pkg/B_extends_A.java pkg/C.java
|
||||
* pkg/subpkg/B_extends_A.java pkg/subpkg/C.java
|
||||
* @run junit/othervm --enable-final-field-mutation=ALL-UNNAMED -DwriteAccess=true TestFieldLookupAccessibility
|
||||
* @run junit/othervm --illegal-final-field-mutation=deny -DwriteAccess=false TestFieldLookupAccessibility
|
||||
*/
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import pkg.B_extends_A;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class TestFieldLookupAccessibility {
|
||||
static boolean writeAccess;
|
||||
|
||||
@BeforeAll
|
||||
static void setup() {
|
||||
String s = System.getProperty("writeAccess");
|
||||
assertNotNull(s);
|
||||
writeAccess = Boolean.valueOf(s);
|
||||
}
|
||||
|
||||
// The set of possible field lookup mechanisms
|
||||
enum FieldLookup {
|
||||
MH_GETTER() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.findGetter(f.getDeclaringClass(), f.getName(), f.getType());
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return !Modifier.isStatic(f.getModifiers());
|
||||
}
|
||||
},
|
||||
MH_SETTER() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.findSetter(f.getDeclaringClass(), f.getName(), f.getType());
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return !Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers());
|
||||
}
|
||||
},
|
||||
MH_STATIC_GETTER() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.findStaticGetter(f.getDeclaringClass(), f.getName(), f.getType());
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return Modifier.isStatic(f.getModifiers());
|
||||
}
|
||||
},
|
||||
MH_STATIC_SETTER() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.findStaticSetter(f.getDeclaringClass(), f.getName(), f.getType());
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers());
|
||||
}
|
||||
},
|
||||
MH_UNREFLECT_GETTER() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.unreflectGetter(f);
|
||||
}
|
||||
},
|
||||
MH_UNREFLECT_GETTER_ACCESSIBLE() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.unreflectGetter(cloneAndSetAccessible(f));
|
||||
}
|
||||
|
||||
// Setting the accessibility bit of a Field grants access under
|
||||
// all conditions for MethodHandle getters.
|
||||
Set<String> inaccessibleFields(Set<String> inaccessibleFields) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
},
|
||||
MH_UNREFLECT_SETTER() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.unreflectSetter(f);
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return f.isAccessible() && !Modifier.isStatic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers());
|
||||
}
|
||||
},
|
||||
MH_UNREFLECT_SETTER_ACCESSIBLE() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.unreflectSetter(cloneAndSetAccessible(f));
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
if (Modifier.isFinal(f.getModifiers())) {
|
||||
return !Modifier.isStatic(f.getModifiers()) && writeAccess;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Setting the accessibility bit of a Field grants access to non-static
|
||||
// final fields for MethodHandle setters.
|
||||
Set<String> inaccessibleFields(Set<String>inaccessibleFields) {
|
||||
Set<String> result = new HashSet<>();
|
||||
inaccessibleFields.stream()
|
||||
.filter(f -> (f.contains("static") && f.contains("final")))
|
||||
.forEach(result::add);
|
||||
return result;
|
||||
}
|
||||
},
|
||||
VH() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.findVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return !Modifier.isStatic(f.getModifiers());
|
||||
}
|
||||
},
|
||||
VH_STATIC() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.findStaticVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
|
||||
}
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return Modifier.isStatic(f.getModifiers());
|
||||
}
|
||||
},
|
||||
VH_UNREFLECT() {
|
||||
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
|
||||
return l.unreflectVarHandle(f);
|
||||
}
|
||||
};
|
||||
|
||||
// Look up a handle to a field
|
||||
abstract Object lookup(MethodHandles.Lookup l, Field f) throws Exception;
|
||||
|
||||
boolean isAccessible(Field f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Set<String> inaccessibleFields(Set<String> inaccessibleFields) {
|
||||
return new HashSet<>(inaccessibleFields);
|
||||
}
|
||||
|
||||
static Field cloneAndSetAccessible(Field f) throws Exception {
|
||||
// Clone to avoid mutating source field
|
||||
f = f.getDeclaringClass().getDeclaredField(f.getName());
|
||||
f.setAccessible(true);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object[][] lookupProvider() throws Exception {
|
||||
Stream<List<Object>> baseCases = Stream.of(
|
||||
// Look up from same package
|
||||
List.of(pkg.A.class, pkg.A.lookup(), pkg.A.inaccessibleFields()),
|
||||
List.of(pkg.A.class, pkg.A.lookup(), pkg.A.inaccessibleFields()),
|
||||
List.of(pkg.A.class, B_extends_A.lookup(), B_extends_A.inaccessibleFields()),
|
||||
List.of(pkg.A.class, pkg.C.lookup(), pkg.C.inaccessibleFields()),
|
||||
|
||||
// Look up from sub-package
|
||||
List.of(pkg.A.class, pkg.subpkg.B_extends_A.lookup(), pkg.subpkg.B_extends_A.inaccessibleFields()),
|
||||
List.of(pkg.A.class, pkg.subpkg.C.lookup(), pkg.subpkg.C.inaccessibleFields())
|
||||
);
|
||||
|
||||
// Cross product base cases with the field lookup classes
|
||||
return baseCases.
|
||||
flatMap(l -> Stream.of(FieldLookup.values()).map(fl -> prepend(fl, l))).
|
||||
toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
private static Object[] prepend(Object o, List<Object> l) {
|
||||
List<Object> pl = new ArrayList<>();
|
||||
pl.add(o);
|
||||
pl.addAll(l);
|
||||
return pl.toArray();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("lookupProvider")
|
||||
public void test(FieldLookup fl, Class<?> src, MethodHandles.Lookup l, Set<String> inaccessibleFields) {
|
||||
// Add to the expected failures all inaccessible fields due to accessibility modifiers
|
||||
Set<String> expected = fl.inaccessibleFields(inaccessibleFields);
|
||||
Map<Field, Throwable> actual = new HashMap<>();
|
||||
|
||||
for (Field f : fields(src)) {
|
||||
// Add to the expected failures all inaccessible fields due to static/final modifiers
|
||||
if (!fl.isAccessible(f)) {
|
||||
expected.add(f.getName());
|
||||
}
|
||||
|
||||
try {
|
||||
fl.lookup(l, f);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Lookup failed, add to the actual failures
|
||||
actual.put(f, t);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> actualFieldNames = actual.keySet().stream().map(Field::getName).
|
||||
collect(Collectors.toSet());
|
||||
if (!actualFieldNames.equals(expected)) {
|
||||
if (actualFieldNames.isEmpty()) {
|
||||
assertEquals(expected, actualFieldNames, "No accessibility failures:");
|
||||
}
|
||||
else {
|
||||
assertEquals(expected, actualFieldNames, "Accessibility failures differ:");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!actual.values().stream().allMatch(IllegalAccessException.class::isInstance)) {
|
||||
fail("Expecting an IllegalArgumentException for all failures " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static List<Field> fields(Class<?> src) {
|
||||
return List.of(src.getDeclaredFields());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package pkg;
|
||||
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Set;
|
||||
|
||||
public class A {
|
||||
public static Object f_public_static;
|
||||
protected static Object f_protected_static;
|
||||
static /*package*/ Object f_package_static;
|
||||
private static Object f_private_static;
|
||||
|
||||
public static final Object f_public_static_final = null;
|
||||
protected static final Object f_protected_static_final = null;
|
||||
static /*package*/ final Object f_package_static_final = null;
|
||||
private static final Object f_private_static_final = null;
|
||||
|
||||
public Object f_public;
|
||||
protected Object f_protected;
|
||||
/*package*/ Object f_package;
|
||||
private Object f_private;
|
||||
|
||||
public final Object f_public_final = null;
|
||||
protected final Object f_protected_final = null;
|
||||
/*package*/ final Object f_package_final = null;
|
||||
private final Object f_private_final = null;
|
||||
|
||||
//
|
||||
|
||||
public static MethodHandles.Lookup lookup() {
|
||||
return MethodHandles.lookup();
|
||||
}
|
||||
|
||||
public static Set<String> inaccessibleFields() {
|
||||
// All fields of pkg.A are accessible to itself
|
||||
return Set.of();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package pkg;
|
||||
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Set;
|
||||
|
||||
public class B_extends_A extends A {
|
||||
public static MethodHandles.Lookup lookup() {
|
||||
return MethodHandles.lookup();
|
||||
}
|
||||
|
||||
public static Set<String> inaccessibleFields() {
|
||||
// Only private fields of pkg.A are not accessible to subclass pkg.B
|
||||
// Note: protected fields are also package accessible
|
||||
return Set.of(
|
||||
"f_private",
|
||||
"f_private_final",
|
||||
"f_private_static",
|
||||
"f_private_static_final"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package pkg;
|
||||
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Set;
|
||||
|
||||
public class C {
|
||||
public static MethodHandles.Lookup lookup() {
|
||||
return MethodHandles.lookup();
|
||||
}
|
||||
|
||||
public static Set<String> inaccessibleFields() {
|
||||
// Only private fields of pkg.A are not accessible to independent
|
||||
// class pkg.C
|
||||
// Note: protected fields are also package accessible
|
||||
return Set.of(
|
||||
"f_private",
|
||||
"f_private_final",
|
||||
"f_private_static",
|
||||
"f_private_static_final"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package pkg.subpkg;
|
||||
|
||||
|
||||
import pkg.A;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Set;
|
||||
|
||||
public class B_extends_A extends A {
|
||||
public static MethodHandles.Lookup lookup() {
|
||||
return MethodHandles.lookup();
|
||||
}
|
||||
|
||||
public static Set<String> inaccessibleFields() {
|
||||
// Only public and protected fields of pkg.A are accessible to subclass
|
||||
// pkg.subpkg.B
|
||||
return Set.of(
|
||||
"f_private",
|
||||
"f_private_final",
|
||||
"f_package",
|
||||
"f_package_final",
|
||||
"f_private_static",
|
||||
"f_private_static_final",
|
||||
"f_package_static",
|
||||
"f_package_static_final"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package pkg.subpkg;
|
||||
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Set;
|
||||
|
||||
public class C {
|
||||
public static MethodHandles.Lookup lookup() {
|
||||
return MethodHandles.lookup();
|
||||
}
|
||||
|
||||
public static Set<String> inaccessibleFields() {
|
||||
// Only public fields of pkg.A are accessible to independent
|
||||
// class pkg.subpkg.C
|
||||
return Set.of(
|
||||
"f_private",
|
||||
"f_private_final",
|
||||
"f_protected",
|
||||
"f_protected_final",
|
||||
"f_package",
|
||||
"f_package_final",
|
||||
"f_private_static",
|
||||
"f_private_static_final",
|
||||
"f_protected_static",
|
||||
"f_protected_static_final",
|
||||
"f_package_static",
|
||||
"f_package_static_final"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 2025, 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
|
||||
* @bug 8302260 8372002
|
||||
* @build p.C p.D p.I p.q.Q
|
||||
* @run junit DescribeConstableTest
|
||||
* @summary Test VarHandle::describeConstable on static fields
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.VarHandle.VarHandleDesc;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class DescribeConstableTest {
|
||||
private static final Lookup LOOKUP = MethodHandles.lookup();
|
||||
private static Stream<Arguments> staticTestCases() {
|
||||
return Stream.of(
|
||||
// static field defined in p.C only
|
||||
Arguments.of(p.C.class, "cString", String.class, p.C.class, "CClass"),
|
||||
// static fields defined in both superinterface p.I and superclass p.q.Q
|
||||
// resolved to the one defined in the direct superinterface of C
|
||||
Arguments.of(p.C.class, "stringField", String.class, p.I.class, "I"),
|
||||
Arguments.of(p.C.class, "longField", long.class, p.I.class, 10L),
|
||||
// static fields defined in superclass p.q.Q only
|
||||
Arguments.of(p.C.class, "stringField2", String.class, p.q.Q.class, "QClass2"),
|
||||
Arguments.of(p.C.class, "longField2", long.class, p.q.Q.class, 102L),
|
||||
// static fields defined in superinterface p.I only
|
||||
Arguments.of(p.C.class, "stringField3", String.class, p.I.class, "I3"),
|
||||
Arguments.of(p.C.class, "longField3", long.class, p.I.class, 13L),
|
||||
// static fields defined in p.D only
|
||||
Arguments.of(p.D.class, "dString", String.class, p.D.class, "DClass"),
|
||||
Arguments.of(p.D.class, "dLong", long.class, p.D.class, 1L),
|
||||
// static fields defined in both superinterface p.I and superclass p.q.Q
|
||||
// resolved to the one defined in the direct superinterface of D
|
||||
Arguments.of(p.D.class, "stringField", String.class, p.I.class, "I"),
|
||||
Arguments.of(p.D.class, "longField", long.class, p.I.class, 10L)
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("staticTestCases")
|
||||
void testStatic(Class<?> refc, String name, Class<?> type, Class<?> declaringClass, Object value) throws Throwable {
|
||||
var vh = LOOKUP.findStaticVarHandle(refc, name, type);
|
||||
assertEquals(value, vh.get());
|
||||
|
||||
var refcDesc = refc.describeConstable().orElseThrow();
|
||||
var typeDesc = type.describeConstable().orElseThrow();
|
||||
var vhd = vh.describeConstable().orElseThrow();
|
||||
var vhd2 = VarHandleDesc.ofStaticField(refcDesc, name, typeDesc);
|
||||
|
||||
assertEquals(value, vhd.resolveConstantDesc(LOOKUP).get());
|
||||
assertEquals(value, vhd2.resolveConstantDesc(LOOKUP).get());
|
||||
|
||||
assertEquals(vhd.toString(), varHandleDescString(declaringClass, name, type, true));
|
||||
}
|
||||
|
||||
private static Arguments[] instanceTestCases() {
|
||||
return new Arguments[] {
|
||||
// Basic instance field in p.q.Q
|
||||
Arguments.of(p.q.Q.class, "instanceIntField", int.class, new p.q.Q(), 42),
|
||||
// p.C.instanceIntField hides the superclass instanceIntField, but it still exists
|
||||
Arguments.of(p.C.class, "instanceIntField", int.class, new p.C(), 76),
|
||||
Arguments.of(p.q.Q.class, "instanceIntField", int.class, new p.C(), 42),
|
||||
// p.D.instanceIntField points to that of p.q.Q
|
||||
Arguments.of(p.D.class, "instanceIntField", int.class, new p.D(), 42),
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("instanceTestCases")
|
||||
void testInstance(Class<?> refc, String name, Class<?> type, Object instance, Object value) throws Throwable {
|
||||
var vh = LOOKUP.findVarHandle(refc, name, type).withInvokeBehavior();
|
||||
assertEquals(value, vh.get(instance));
|
||||
|
||||
var refcDesc = refc.describeConstable().orElseThrow();
|
||||
var typeDesc = type.describeConstable().orElseThrow();
|
||||
var vhd = vh.describeConstable().orElseThrow();
|
||||
var vhd2 = VarHandleDesc.ofField(refcDesc, name, typeDesc);
|
||||
|
||||
assertEquals(value, vhd.resolveConstantDesc(LOOKUP).get(instance));
|
||||
assertEquals(value, vhd2.resolveConstantDesc(LOOKUP).get(instance));
|
||||
|
||||
// The string does not use the declaring class because
|
||||
// receiver is restricted on the handle
|
||||
assertEquals(vhd.toString(), varHandleDescString(refc, name, type, false));
|
||||
}
|
||||
|
||||
static String varHandleDescString(Class<?> declaringClass, String name, Class<?> type, boolean staticField) {
|
||||
return String.format("VarHandleDesc[%s%s.%s:%s]",
|
||||
staticField ? "static " : "",
|
||||
declaringClass.describeConstable().orElseThrow().displayName(), name,
|
||||
type.describeConstable().orElseThrow().displayName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 2025, 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.
|
||||
*/
|
||||
|
||||
package p;
|
||||
|
||||
public class C extends p.q.Q implements I {
|
||||
public static String cString = "CClass";
|
||||
|
||||
public int instanceIntField = 76; // Hides the field from Q
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
package p;
|
||||
|
||||
public class D extends p.q.Q implements I {
|
||||
public static String dString = "DClass";
|
||||
public static long dLong = 1L;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
package p;
|
||||
|
||||
public interface I {
|
||||
String stringField = "I";
|
||||
long longField = 10l;
|
||||
|
||||
String stringField3 = "I3";
|
||||
long longField3 = 13L;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 2025, 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.
|
||||
*/
|
||||
|
||||
package p.q;
|
||||
|
||||
public class Q {
|
||||
public static String stringField = "QClass";
|
||||
public static long longField = 100L;
|
||||
|
||||
public static String stringField2 = "QClass2";
|
||||
public static long longField2 = 102L;
|
||||
|
||||
public int instanceIntField = 42;
|
||||
}
|
||||
175
test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh
Normal file
175
test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#!/bin/bash
|
||||
|
||||
javac -d . ../../../../../../make/jdk/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"
|
||||
|
||||
args="$args -KCAS"
|
||||
|
||||
case $type in
|
||||
byte|short|char|int|long|float|double)
|
||||
args="$args -KAtomicAdd"
|
||||
;;
|
||||
esac
|
||||
|
||||
case $type in
|
||||
boolean|byte|short|char|int|long)
|
||||
args="$args -KBitwise"
|
||||
;;
|
||||
esac
|
||||
|
||||
wrong_primitive_type=boolean
|
||||
|
||||
case $type in
|
||||
boolean)
|
||||
value1=true
|
||||
value2=false
|
||||
value3=false
|
||||
wrong_primitive_type=int
|
||||
;;
|
||||
byte)
|
||||
value1=(byte)0x01
|
||||
value2=(byte)0x23
|
||||
value3=(byte)0x45
|
||||
;;
|
||||
short)
|
||||
value1=(short)0x0123
|
||||
value2=(short)0x4567
|
||||
value3=(short)0x89AB
|
||||
;;
|
||||
char)
|
||||
value1=\'\\\\u0123\'
|
||||
value2=\'\\\\u4567\'
|
||||
value3=\'\\\\u89AB\'
|
||||
;;
|
||||
int)
|
||||
value1=0x01234567
|
||||
value2=0x89ABCDEF
|
||||
value3=0xCAFEBABE
|
||||
;;
|
||||
long)
|
||||
value1=0x0123456789ABCDEFL
|
||||
value2=0xCAFEBABECAFEBABEL
|
||||
value3=0xDEADBEEFDEADBEEFL
|
||||
;;
|
||||
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
|
||||
out=VarHandleTestAccess${Type}.java
|
||||
rm -f $out
|
||||
java $SPP -nel $args -iX-VarHandleTestAccess.java.template -o$out
|
||||
out=VarHandleTestMethodHandleAccess${Type}.java
|
||||
rm -f $out
|
||||
java $SPP -nel $args -iX-VarHandleTestMethodHandleAccess.java.template -o$out
|
||||
out=VarHandleTestMethodType${Type}.java
|
||||
rm -f $out
|
||||
java $SPP -nel $args -iX-VarHandleTestMethodType.java.template -o$out
|
||||
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
|
||||
int|long)
|
||||
args="$args -KBitwise"
|
||||
;;
|
||||
esac
|
||||
|
||||
# The value of `value3` is chosen such that when added to `value1` or `value2`
|
||||
# it will result in carrying of bits over to the next byte, thereby detecting
|
||||
# possible errors in endianness conversion e.g. if say for atomic addition the
|
||||
# augend is incorrectly processed
|
||||
case $type in
|
||||
short)
|
||||
value1=(short)0x0102
|
||||
value2=(short)0x1112
|
||||
value3=(short)0xFFFE
|
||||
;;
|
||||
char)
|
||||
value1=(char)0x0102
|
||||
value2=(char)0x1112
|
||||
value3=(char)0xFFFE
|
||||
;;
|
||||
int)
|
||||
value1=0x01020304
|
||||
value2=0x11121314
|
||||
value3=0xFFFEFDFC
|
||||
;;
|
||||
long)
|
||||
value1=0x0102030405060708L
|
||||
value2=0x1112131415161718L
|
||||
value3=0xFFFEFDFCFBFAF9F8L
|
||||
;;
|
||||
float)
|
||||
value1=0x01020304
|
||||
value2=0x11121314
|
||||
value3=0xFFFEFDFC
|
||||
;;
|
||||
double)
|
||||
value1=0x0102030405060708L
|
||||
value2=0x1112131415161718L
|
||||
value3=0xFFFEFDFCFBFAF9F8L
|
||||
;;
|
||||
esac
|
||||
|
||||
args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3"
|
||||
|
||||
echo $args
|
||||
out=VarHandleTestByteArrayAs${Type}.java
|
||||
rm -f $out
|
||||
java $SPP -nel $args -iX-VarHandleTestByteArrayView.java.template -o$out
|
||||
done
|
||||
|
||||
rm -fr build
|
||||
Loading…
Add table
Add a link
Reference in a new issue