Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8245227: VarHandle adaptation fails when non-crackable direct method handles are used as adapters #177

Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -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);
ProTip! Use n and p to navigate between commits in a pull request.