Skip to content
Permalink
Browse files

8245227: VarHandle adaptation fails when non-crackable direct method …

…handles are used as adapters

Reviewed-by: psandoz
  • Loading branch information
mcimadamore committed May 18, 2020
1 parent e2d2dba commit 645021438aae3c7ae2ea21695445d574787ac0f4
@@ -542,17 +542,23 @@ public static VarHandle dropCoordinates(VarHandle target, int pos, Class<?>... v
private static void noCheckedExceptions(MethodHandle handle) {
if (handle instanceof DirectMethodHandle) {
DirectMethodHandle directHandle = (DirectMethodHandle)handle;
MethodHandleInfo info = MethodHandles.Lookup.IMPL_LOOKUP.revealDirect(directHandle);
Class<?>[] exceptionTypes = switch (info.getReferenceKind()) {
case MethodHandleInfo.REF_invokeInterface, MethodHandleInfo.REF_invokeSpecial,
MethodHandleInfo.REF_invokeStatic, MethodHandleInfo.REF_invokeVirtual ->
info.reflectAs(Method.class, MethodHandles.Lookup.IMPL_LOOKUP).getExceptionTypes();
case MethodHandleInfo.REF_newInvokeSpecial ->
info.reflectAs(Constructor.class, MethodHandles.Lookup.IMPL_LOOKUP).getExceptionTypes();
case MethodHandleInfo.REF_getField, MethodHandleInfo.REF_getStatic,
MethodHandleInfo.REF_putField, MethodHandleInfo.REF_putStatic -> null;
default -> throw new AssertionError("Cannot get here");
};
byte refKind = directHandle.member.getReferenceKind();
MethodHandleInfo info = new InfoFromMemberName(
MethodHandles.Lookup.IMPL_LOOKUP,
directHandle.member,
refKind);
final Class<?>[] exceptionTypes;
if (MethodHandleNatives.refKindIsMethod(refKind)) {
exceptionTypes = info.reflectAs(Method.class, MethodHandles.Lookup.IMPL_LOOKUP)
.getExceptionTypes();
} else if (MethodHandleNatives.refKindIsField(refKind)) {
exceptionTypes = null;
} else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
exceptionTypes = info.reflectAs(Constructor.class, MethodHandles.Lookup.IMPL_LOOKUP)
.getExceptionTypes();
} else {
throw new AssertionError("Cannot get here");
}
if (exceptionTypes != null) {
if (Stream.of(exceptionTypes).anyMatch(VarHandles::isCheckedException)) {
throw newIllegalArgumentException("Cannot adapt a var handle with a method handle which throws checked exceptions");
@@ -49,6 +49,8 @@

static MethodHandle S2I;
static MethodHandle I2S;
static MethodHandle O2I;
static MethodHandle I2O;
static MethodHandle S2L;
static MethodHandle S2L_EX;
static MethodHandle S2I_EX;
@@ -61,6 +63,8 @@
try {
S2I = MethodHandles.lookup().findStatic(TestAdaptVarHandles.class, "stringToInt", MethodType.methodType(int.class, String.class));
I2S = MethodHandles.lookup().findStatic(TestAdaptVarHandles.class, "intToString", MethodType.methodType(String.class, int.class));
O2I = MethodHandles.explicitCastArguments(S2I, MethodType.methodType(int.class, Object.class));
I2O = MethodHandles.explicitCastArguments(I2S, MethodType.methodType(Object.class, int.class));
S2L = MethodHandles.lookup().findStatic(TestAdaptVarHandles.class, "stringToLong", MethodType.methodType(long.class, String.class));
S2L_EX = MethodHandles.lookup().findStatic(TestAdaptVarHandles.class, "stringToLongException", MethodType.methodType(long.class, String.class));
BASE_ADDR = MethodHandles.lookup().findStatic(TestAdaptVarHandles.class, "baseAddress", MethodType.methodType(MemoryAddress.class, MemorySegment.class));
@@ -98,6 +102,25 @@ public void testFilterValue() throws Throwable {
assertEquals(value, "42");
}

@Test
public void testFilterValueLoose() throws Throwable {
ValueLayout layout = MemoryLayouts.JAVA_INT;
MemorySegment segment = MemorySegment.allocateNative(layout);
VarHandle intHandle = layout.varHandle(int.class);
VarHandle i2SHandle = MemoryHandles.filterValue(intHandle, O2I, I2O);
i2SHandle.set(segment.baseAddress(), "1");
String oldValue = (String)i2SHandle.getAndAdd(segment.baseAddress(), "42");
assertEquals(oldValue, "1");
String value = (String)i2SHandle.get(segment.baseAddress());
assertEquals(value, "43");
boolean swapped = (boolean)i2SHandle.compareAndSet(segment.baseAddress(), "43", "12");
assertTrue(swapped);
oldValue = (String)i2SHandle.compareAndExchange(segment.baseAddress(), "12", "42");
assertEquals(oldValue, "12");
value = (String)(Object)i2SHandle.toMethodHandle(VarHandle.AccessMode.GET).invokeExact(segment.baseAddress());
assertEquals(value, "42");
}

@Test(expectedExceptions = NullPointerException.class)
public void testBadFilterNullTarget() {
MemoryHandles.filterValue(null, S2I, I2S);

0 comments on commit 6450214

Please sign in to comment.
You can’t perform that action at this time.