Prune method access info collection

Bug: b/313365881
Change-Id: I35170faee13fd255505b218a822764662b0202c8
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 e61ec53..14c4975 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -558,7 +558,7 @@
   @SuppressWarnings("ReferenceEquality")
   public DexEncodedMethod lookupSignaturePolymorphicMethod(
       DexString methodName, DexItemFactory factory) {
-    if (type != factory.methodHandleType && type != factory.varHandleType) {
+    if (!isClassWithSignaturePolymorphicMethods(factory)) {
       return null;
     }
     DexEncodedMethod matchingName = null;
@@ -579,15 +579,17 @@
     return signaturePolymorphicMethod;
   }
 
-  @SuppressWarnings("ReferenceEquality")
-  public static boolean isSignaturePolymorphicMethod(
-      DexEncodedMethod method, DexItemFactory factory) {
-    assert method.getHolderType() == factory.methodHandleType
-        || method.getHolderType() == factory.varHandleType;
-    return method.accessFlags.isVarargs()
-        && method.accessFlags.isNative()
-        && method.getReference().proto.parameters.size() == 1
-        && method.getReference().proto.parameters.values[0] == factory.objectArrayType;
+  public boolean isClassWithSignaturePolymorphicMethods(DexItemFactory dexItemFactory) {
+    return type.isIdenticalTo(dexItemFactory.methodHandleType)
+        || type.isIdenticalTo(dexItemFactory.varHandleType);
+  }
+
+  public boolean isSignaturePolymorphicMethod(DexEncodedMethod method, DexItemFactory factory) {
+    assert isClassWithSignaturePolymorphicMethods(factory);
+    return method.isVarargs()
+        && method.isNative()
+        && method.getParameters().size() == 1
+        && method.getParameter(0).isIdenticalTo(factory.objectArrayType);
   }
 
   public boolean canBeInstantiatedByNewInstance() {
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 40bdbe2..7465b0a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -450,6 +450,10 @@
     return accessFlags.isSynchronized();
   }
 
+  public boolean isVarargs() {
+    return accessFlags.isVarargs();
+  }
+
   public boolean isInitializer() {
     checkIfObsolete();
     return isInstanceInitializer() || isClassInitializer();
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
index beb2fb3..2671841 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
@@ -20,6 +20,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.function.Supplier;
 
 public class MethodAccessInfoCollection {
@@ -334,6 +335,18 @@
       }
     }
 
+    public void removeIf(Predicate<DexMethod> predicate) {
+      removeIf(predicate, directInvokes);
+      removeIf(predicate, interfaceInvokes);
+      removeIf(predicate, staticInvokes);
+      removeIf(predicate, superInvokes);
+      removeIf(predicate, virtualInvokes);
+    }
+
+    private static void removeIf(Predicate<DexMethod> predicate, Map<DexMethod, ?> invokes) {
+      invokes.keySet().removeIf(predicate);
+    }
+
     public MethodAccessInfoCollection build() {
       return new MethodAccessInfoCollection(
           directInvokes, interfaceInvokes, staticInvokes, superInvokes, virtualInvokes);
diff --git a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
index 8e04491..ab17919 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodArrayBacking.java
@@ -403,22 +403,18 @@
   public void replaceAllDirectMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
     DexEncodedMethod[] oldMethods = directMethods;
     clearDirectMethods();
-    DexEncodedMethod[] newMethods = new DexEncodedMethod[oldMethods.length];
-    for (int i = 0; i < oldMethods.length; i++) {
-      newMethods[i] = replacement.apply(oldMethods[i]);
-    }
-    directMethods = newMethods;
+    directMethods =
+        ArrayUtils.initialize(
+            new DexEncodedMethod[oldMethods.length], i -> replacement.apply(oldMethods[i]));
   }
 
   @Override
   public void replaceAllVirtualMethods(Function<DexEncodedMethod, DexEncodedMethod> replacement) {
     DexEncodedMethod[] oldMethods = virtualMethods;
     clearVirtualMethods();
-    DexEncodedMethod[] newMethods = new DexEncodedMethod[oldMethods.length];
-    for (int i = 0; i < oldMethods.length; i++) {
-      newMethods[i] = replacement.apply(oldMethods[i]);
-    }
-    virtualMethods = newMethods;
+    virtualMethods =
+        ArrayUtils.initialize(
+            new DexEncodedMethod[oldMethods.length], i -> replacement.apply(oldMethods[i]));
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index 6dbdc35..710666b 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -53,6 +53,15 @@
     return this;
   }
 
+  public boolean isSignaturePolymorphicResolution(DexMethod method, DexItemFactory dexItemFactory) {
+    if (isSingleResolution() && !method.match(getResolvedMethod())) {
+      assert getResolvedHolder().isClassWithSignaturePolymorphicMethods(dexItemFactory);
+      assert getResolvedHolder().isSignaturePolymorphicMethod(getResolvedMethod(), dexItemFactory);
+      return true;
+    }
+    return false;
+  }
+
   /**
    * Returns true if resolution succeeded *and* the resolved method has a known definition.
    *
@@ -179,8 +188,8 @@
       DexProgramClass context, AppView<? extends AppInfoWithClassHierarchy> appView);
 
   public final DexClassAndMethod lookupInvokeSuperTarget(
-      DexProgramClass context, AppView<? extends AppInfoWithClassHierarchy> appView) {
-    return lookupInvokeSuperTarget(context, appView, appView.appInfo());
+      ProgramDefinition context, AppView<? extends AppInfoWithClassHierarchy> appView) {
+    return lookupInvokeSuperTarget(context.getContextClass(), appView, appView.appInfo());
   }
 
   /** Lookup the single target of an invoke-super on this resolution result if possible. */
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 30d6e81..ea7cbf5 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1509,11 +1509,9 @@
     invokeAnalyses.forEach(analysis -> analysis.traceInvokeStatic(invokedMethod, context));
   }
 
-  @SuppressWarnings("UnusedVariable")
   void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context) {
     // We have to revisit super invokes based on the context they are found in. The same
     // method descriptor will hit different targets, depending on the context it is used in.
-    DexMethod actualTarget = getInvokeSuperTarget(invokedMethod, context);
     if (!registerMethodWithTargetAndContext(
         methodAccessInfoCollection::registerInvokeSuperInContext, invokedMethod, context)) {
       return;
@@ -1963,20 +1961,6 @@
         });
   }
 
-  private DexMethod getInvokeSuperTarget(DexMethod method, ProgramMethod currentMethod) {
-    DexClass methodHolderClass = appView.definitionFor(method.holder);
-    if (methodHolderClass != null && methodHolderClass.isInterface()) {
-      return method;
-    }
-    DexProgramClass holderClass = currentMethod.getHolder();
-    if (holderClass.superType == null || holderClass.isInterface()) {
-      // We do not know better or this call is made from an interface.
-      return method;
-    }
-    // Return the invoked method on the supertype.
-    return appView.dexItemFactory().createMethod(holderClass.superType, method.proto, method.name);
-  }
-
   //
   // Actual actions performed.
   //
@@ -4225,6 +4209,15 @@
     assert fieldAccessInfoCollection.verifyMappingIsOneToOne();
     timing.end();
 
+    // Remove mappings for methods that don't resolve in the method access info collection.
+    // TODO(b/313365881): Should use non-legacy resolution, but this fails.
+    methodAccessInfoCollection.removeIf(
+        method -> {
+          MethodResolutionResult result = appInfo.unsafeResolveMethodDueToDexFormatLegacy(method);
+          return result.isFailedResolution()
+              || result.isSignaturePolymorphicResolution(method, appView.dexItemFactory());
+        });
+
     // Verify all references on the input app before synthesizing definitions.
     assert verifyReferences(appInfo.app());
 
diff --git a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
index f35f32b..8b3a049 100644
--- a/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
+++ b/src/main/java/com/android/tools/r8/tracereferences/Tracer.java
@@ -298,7 +298,7 @@
                     }
                   });
           if (seenMethod.isFalse()) {
-            handleRewrittenMethodReference(rewrittenMethod, (DexClassAndMethod) null);
+            handleRewrittenMethodReference(rewrittenMethod, null);
           }
         }
       }
@@ -368,7 +368,8 @@
                     .forEachFailureDependency(
                         type -> addType(type, referencedFrom),
                         methodCausingFailure ->
-                            handleRewrittenMethodReference(method, methodCausingFailure));
+                            handleRewrittenMethodReference(
+                                method, methodCausingFailure.asDexClassAndMethod(appView)));
                 return;
               }
               seenSingleResult.set();
@@ -379,33 +380,27 @@
               failingResult -> {
                 assert failingResult.isFailedResolution();
                 if (!failingResult.asFailedResolution().hasMethodsCausingError()) {
-                  handleRewrittenMethodReference(method, (DexEncodedMethod) null);
+                  handleRewrittenMethodReference(method, null);
                 }
               });
         }
       }
 
-      private void handleRewrittenMethodReference(
-          DexMethod method, DexClassAndMethod resolvedMethod) {
-        handleRewrittenMethodReference(
-            method, resolvedMethod == null ? null : resolvedMethod.getDefinition());
-      }
-
       @SuppressWarnings("ReferenceEquality")
       private void handleRewrittenMethodReference(
-          DexMethod method, DexEncodedMethod resolvedMethod) {
-        assert resolvedMethod == null
-            || resolvedMethod.getReference().match(method)
-            || DexClass.isSignaturePolymorphicMethod(resolvedMethod, factory);
+          DexMethod method, DexClassAndMethod resolvedMethod) {
         addType(method.getHolderType(), referencedFrom);
         addTypes(method.getParameters(), referencedFrom);
         addType(method.getReturnType(), referencedFrom);
         if (resolvedMethod != null) {
+          DexEncodedMethod definition = resolvedMethod.getDefinition();
+          assert resolvedMethod.getReference().match(method)
+              || resolvedMethod.getHolder().isSignaturePolymorphicMethod(definition, factory);
           if (isTargetType(resolvedMethod.getHolderType())) {
             if (resolvedMethod.getHolderType() != method.getHolderType()) {
               addType(resolvedMethod.getHolderType(), referencedFrom);
             }
-            TracedMethodImpl tracedMethod = new TracedMethodImpl(resolvedMethod, referencedFrom);
+            TracedMethodImpl tracedMethod = new TracedMethodImpl(definition, referencedFrom);
             consumer.acceptMethod(tracedMethod, diagnostics);
             if (resolvedMethod.getAccessFlags().isVisibilityDependingOnPackage()) {
               consumer.acceptPackage(