MethodHandles: Implement MethodHandle.asType.
Tracks libcore change 16fa583fb5ee489.
Test: make test-art-host
Bug: 30550796
Change-Id: I2457b563f67a183c4eebf94ddbe74cc55f772ee0
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index d824c60..780513f 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -64,6 +64,7 @@
testExceptionDetailMessages();
testfindVirtual();
testUnreflects();
+ testAsType();
}
public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -428,6 +429,54 @@
assertEquals("updatedStaticValue2", (String) privateStaticField.get(null));
}
+ // This method only exists to fool Jack's handling of types. See b/32536744.
+ public static CharSequence getSequence() {
+ return "foo";
+ }
+
+ public static void testAsType() throws Throwable {
+ // The type of this handle is (String, String)String.
+ MethodHandle mh = MethodHandles.lookup().findVirtual(String.class,
+ "concat", MethodType.methodType(String.class, String.class));
+
+ // Change it to (CharSequence, String)Object.
+ MethodHandle asType = mh.asType(
+ MethodType.methodType(Object.class, CharSequence.class, String.class));
+
+ Object obj = asType.invokeExact((CharSequence) getSequence(), "bar");
+ assertEquals("foobar", (String) obj);
+
+ // Should fail due to a wrong return type.
+ try {
+ String str = (String) asType.invokeExact((CharSequence) getSequence(), "bar");
+ fail();
+ } catch (WrongMethodTypeException expected) {
+ }
+
+ // Should fail due to a wrong argument type (String instead of Charsequence).
+ try {
+ String str = (String) asType.invokeExact("baz", "bar");
+ fail();
+ } catch (WrongMethodTypeException expected) {
+ }
+
+ // Calls to asType should fail if the types are not convertible.
+ //
+ // Bad return type conversion.
+ try {
+ mh.asType(MethodType.methodType(int.class, String.class, String.class));
+ fail();
+ } catch (WrongMethodTypeException expected) {
+ }
+
+ // Bad argument conversion.
+ try {
+ mh.asType(MethodType.methodType(String.class, int.class, String.class));
+ fail();
+ } catch (WrongMethodTypeException expected) {
+ }
+ }
+
public static void assertEquals(String s1, String s2) {
if (s1 == s2) {
return;
diff --git a/test/957-methodhandle-transforms/expected.txt b/test/957-methodhandle-transforms/expected.txt
index fc4fdd6..7540ef7 100644
--- a/test/957-methodhandle-transforms/expected.txt
+++ b/test/957-methodhandle-transforms/expected.txt
@@ -4,6 +4,7 @@
Message: foo, Message2: 42
Message: foo, Message2: 42
Message: foo, Message2: 42
+Message: foo, Message2: 42
Target: Arg1: foo, Arg2: 42
Target: Arg1: foo, Arg2: 42
Handler: java.lang.IllegalArgumentException: exceptionMessage, Arg1: foo, Arg2: 42, ExMsg: exceptionMessage
@@ -14,3 +15,4 @@
target: target, 42, 56
fallback: fallback, 42, 56
target: target, 42, 56
+target: target, 42, 56
diff --git a/test/957-methodhandle-transforms/src/Main.java b/test/957-methodhandle-transforms/src/Main.java
index 4a27086..e50391b 100644
--- a/test/957-methodhandle-transforms/src/Main.java
+++ b/test/957-methodhandle-transforms/src/Main.java
@@ -90,6 +90,12 @@
// it's IAE and should be WMTE instead.
}
+ // Check that asType works as expected.
+ transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class);
+ transform = transform.asType(MethodType.methodType(void.class,
+ new Class<?>[] { short.class, Object.class, String.class, long.class }));
+ transform.invokeExact((short) 45, new Object(), "foo", 42l);
+
// Invalid argument location, should not be allowed.
try {
MethodHandles.dropArguments(delegate, -1, int.class, Object.class);
@@ -183,6 +189,14 @@
assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage2");
assertEquals("java.lang.IllegalArgumentException: exceptionMessage2", returnVal);
+
+ // Check that asType works as expected.
+ adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
+ handler);
+ adapter = adapter.asType(MethodType.methodType(String.class,
+ new Class<?>[] { String.class, int.class, String.class }));
+ returnVal = (String) adapter.invokeExact("foo", 42, "exceptionMessage");
+ assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
}
public static boolean testGuardWithTest_test(String arg1, long arg2) {
@@ -225,6 +239,12 @@
assertEquals("fallback", returnVal);
returnVal = (String) adapter.invokeExact("target", 42l, 56);
assertEquals("target", returnVal);
+
+ // Check that asType works as expected.
+ adapter = adapter.asType(MethodType.methodType(String.class,
+ new Class<?>[] { String.class, int.class, int.class }));
+ returnVal = (String) adapter.invokeExact("target", 42, 56);
+ assertEquals("target", returnVal);
}
public static void fail() {