Implement custom lookup for signature polymorphic methods.
Bug: 144339115
Change-Id: I1afc314a9264717619d3f8bdcebbc68474ae3be3
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 14d41ea..6eb6a94 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -369,25 +369,15 @@
* Section 5.4.3.3 of the JVM Spec</a>.
*/
private DexEncodedMethod resolveMethodOnClassStep2(DexClass clazz, DexMethod method) {
- // Pt. 1: Signature polymorphic method check. Those are only allowed on
- // java.lang.invoke.MethodHandle, so we only need to look for it if we are looking at
- // that type.
+ // Pt. 1: Signature polymorphic method check.
// See also <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">
// Section 2.9 of the JVM Spec</a>.
- if (clazz.type == dexItemFactory.methodHandleType) {
- DexMethod signaturePolymorphic = dexItemFactory.createMethod(clazz.type,
- dexItemFactory.createProto(
- dexItemFactory.objectType, dexItemFactory.objectArrayType),
- method.name);
- DexEncodedMethod result = clazz.lookupMethod(signaturePolymorphic);
- // Check we found a result and that it has the required access flags for signature polymorphic
- // functions.
- if (result != null && result.accessFlags.isNative() && result.accessFlags.isVarargs()) {
- return result;
- }
+ DexEncodedMethod result = clazz.lookupSignaturePolymorphicMethod(method.name, dexItemFactory);
+ if (result != null) {
+ return result;
}
// Pt 2: Find a method that matches the descriptor.
- DexEncodedMethod result = clazz.lookupMethod(method);
+ result = clazz.lookupMethod(method);
if (result != null) {
return result;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 0acef70..ccc2eed 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -581,6 +581,38 @@
return result == null ? lookupVirtualMethod(method) : result;
}
+ public DexEncodedMethod lookupSignaturePolymorphicMethod(
+ DexString methodName, DexItemFactory factory) {
+ if (type != factory.methodHandleType && type != factory.varHandleType) {
+ return null;
+ }
+ DexEncodedMethod matchingName = null;
+ DexEncodedMethod signaturePolymorphicMethod = null;
+ for (DexEncodedMethod method : virtualMethods) {
+ if (method.method.name == methodName) {
+ if (matchingName != null) {
+ // The jvm spec, section 5.4.3.3 details that there must be exactly one method with the
+ // given name only.
+ return null;
+ }
+ matchingName = method;
+ if (isSignaturePolymorphicMethod(method, factory)) {
+ signaturePolymorphicMethod = method;
+ }
+ }
+ }
+ return signaturePolymorphicMethod;
+ }
+
+ private boolean isSignaturePolymorphicMethod(DexEncodedMethod method, DexItemFactory factory) {
+ assert method.method.holder == factory.methodHandleType
+ || method.method.holder == factory.varHandleType;
+ return method.accessFlags.isVarargs()
+ && method.accessFlags.isNative()
+ && method.method.proto.parameters.size() == 1
+ && method.method.proto.parameters.values[0] != factory.objectArrayType;
+ }
+
private <T extends DexItem, S extends Descriptor<T, S>> T lookupTarget(T[] items, S descriptor) {
for (T entry : items) {
if (descriptor.match(entry)) {
diff --git a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
index 02cb585..7d93488 100644
--- a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
@@ -98,10 +98,6 @@
if (renamed != null) {
return renamed;
}
- // TODO(b/144339115): Don't allocate in the item factory during resolution!
- if (method.holder == appView.dexItemFactory().methodHandleType) {
- return method.name;
- }
// If the method does not have a direct renaming, return the resolutions mapping.
ResolutionResult resolutionResult = appView.appInfo().resolveMethod(method.holder, method);
if (resolutionResult.hasSingleTarget()) {