Treat non-lambda metafactory argument method handles specially.
They can reach MethodHandle.invokeExact calls which match exact
method signatures. Therefore, we cannot perform member rebinding
on the methods in method handles because that could (and likely
would) change the receiver type making the matching fail.
Therefore, we keep the original receiver type for all such
method handles. That also means that we need to keep those
receiver types in the output and cannot perform merging or
other operations that would make those types disappear.
R=christofferqa@google.com, sgjesse@google.com, tamaskenez@google.com
Change-Id: Ic31373f574493b6941acca176f39decf0ef12182
diff --git a/src/test/examplesAndroidO/invokecustom/InvokeCustom.java b/src/test/examplesAndroidO/invokecustom/InvokeCustom.java
index 449d426..64405bb 100644
--- a/src/test/examplesAndroidO/invokecustom/InvokeCustom.java
+++ b/src/test/examplesAndroidO/invokecustom/InvokeCustom.java
@@ -9,6 +9,20 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+class ClassWithLongName {
+ @Override
+ public String toString() {
+ return getClass().getName();
+ }
+}
+
+class AnotherClassWithALongName {
+ @Override
+ public String toString() {
+ return getClass().getName();
+ }
+}
+
interface J {
default void targetMethodTest8() {
@@ -38,6 +52,11 @@
default void targetMethodTest10() {
System.out.println("targetMethodTest10 from I");
}
+
+ default AnotherClassWithALongName targetMethodTest11(ClassWithLongName a) {
+ System.out.println("targetMethodTest11 from I");
+ return new AnotherClassWithALongName();
+ }
}
abstract class Super {
diff --git a/src/test/examplesAndroidO/invokecustom/TestGenerator.java b/src/test/examplesAndroidO/invokecustom/TestGenerator.java
index e42b9c9..05a6f28 100644
--- a/src/test/examplesAndroidO/invokecustom/TestGenerator.java
+++ b/src/test/examplesAndroidO/invokecustom/TestGenerator.java
@@ -57,6 +57,7 @@
generateMethodTest11(cw);
generateMethodTest12(cw);
generateMethodTest13(cw);
+ generateMethodTest14(cw);
generateMethodMain(cw);
super.visitEnd();
}
@@ -97,6 +98,8 @@
Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test12", "()V", false);
mv.visitMethodInsn(
Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test13", "()V", false);
+ mv.visitMethodInsn(
+ Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test14", "()V", false);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(-1, -1);
}
@@ -424,4 +427,43 @@
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(-1, -1);
}
+
+ /**
+ * Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+ * MethodHandle of kind invoke instance taking an argument and returning a result. This should
+ * work through renaming.
+ */
+ private void generateMethodTest14(ClassVisitor cv) {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test14", "()V",
+ null, null);
+ MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+ MethodType.class, MethodHandle.class);
+ Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+ "bsmCreateCallSite", mt.toMethodDescriptorString(), false);
+ mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitMethodInsn(
+ Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+ mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(ClassWithLongName.class));
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitMethodInsn(
+ Opcodes.INVOKESPECIAL,
+ Type.getInternalName(ClassWithLongName.class),
+ "<init>",
+ "()V",
+ false);
+ mv.visitInvokeDynamicInsn(
+ "targetMethodTest11",
+ "(Linvokecustom/InvokeCustom;Linvokecustom/ClassWithLongName;)"
+ + "Linvokecustom/AnotherClassWithALongName;",
+ bootstrap,
+ new Handle(
+ Opcodes.H_INVOKEVIRTUAL,
+ Type.getInternalName(InvokeCustom.class),
+ "targetMethodTest11",
+ "(Linvokecustom/ClassWithLongName;)Linvokecustom/AnotherClassWithALongName;",
+ false));
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(-1, -1);
+ }
}
diff --git a/src/test/examplesAndroidO/invokecustom/keep-rules.txt b/src/test/examplesAndroidO/invokecustom/keep-rules.txt
index bcefc4b..54a5682 100644
--- a/src/test/examplesAndroidO/invokecustom/keep-rules.txt
+++ b/src/test/examplesAndroidO/invokecustom/keep-rules.txt
@@ -8,7 +8,7 @@
public static void main(...);
}
--keepclasseswithmembers class * {
+-keepclassmembers class * {
*** targetMethodTest*(...);
}
diff --git a/src/test/examplesAndroidO/invokecustom2/keep-rules.txt b/src/test/examplesAndroidO/invokecustom2/keep-rules.txt
new file mode 100644
index 0000000..629ec41
--- /dev/null
+++ b/src/test/examplesAndroidO/invokecustom2/keep-rules.txt
@@ -0,0 +1,15 @@
+# Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Keep the application entry point and the methods that are targets for invoke custom invocations.
+# Get rid of everything that is not reachable from there.
+-keep public class invokecustom2.InvokeCustom {
+ public static void main(...);
+}
+
+-keepclassmembers class * {
+ *** targetMethodTest*(...);
+}
+
+-allowaccessmodification