Avoid resolution in naming lens

Fixes: 167385969
Change-Id: Icec1f2b2749756cec51da6498d8de5c587ea9fc9
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index dc34e88..60e9559 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -493,7 +493,6 @@
           @Override
           public void fixup(DexEncodedField field, MutableFieldOptimizationInfo optimizationInfo) {
             optimizationInfo
-                .asMutableFieldOptimizationInfo()
                 .fixupClassTypeReferences(appView, appView.graphLens())
                 .fixupAbstractValue(appView, appView.graphLens());
           }
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index 0f50ecb..6ca2736 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -9,16 +9,24 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessInfoCollection;
+import com.android.tools.r8.graph.ResolutionResult;
 import com.android.tools.r8.graph.SubtypingInfo;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
 import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
 import java.util.function.Function;
 
 /**
@@ -87,8 +95,10 @@
   // from the method name minifier to the interface method name minifier.
   class State {
 
-    void putRenaming(DexEncodedMethod key, DexString value) {
-      renaming.put(key.getReference(), value);
+    void putRenaming(DexEncodedMethod key, DexString newName) {
+      if (newName != key.getName()) {
+        renaming.put(key.getReference(), newName);
+      }
     }
 
     MethodReservationState<?> getReservationState(DexType type) {
@@ -173,7 +183,9 @@
     }
   }
 
-  MethodRenaming computeRenaming(Iterable<DexClass> interfaces, Timing timing) {
+  MethodRenaming computeRenaming(
+      Iterable<DexClass> interfaces, ExecutorService executorService, Timing timing)
+      throws ExecutionException {
     // Phase 1: Reserve all the names that need to be kept and allocate linked state in the
     //          library part.
     timing.begin("Phase 1");
@@ -193,6 +205,9 @@
     timing.begin("Phase 4");
     assignNamesToClassesMethods(appView.dexItemFactory().objectType, rootNamingState);
     timing.end();
+    timing.begin("Phase 5: non-rebound references");
+    renameNonReboundReferences(executorService);
+    timing.end();
 
     return new MethodRenaming(renaming);
   }
@@ -322,6 +337,60 @@
     return reservationState;
   }
 
+  private void renameNonReboundReferences(ExecutorService executorService)
+      throws ExecutionException {
+    Map<DexMethod, DexString> nonReboundRenamings = new ConcurrentHashMap<>();
+    MethodAccessInfoCollection methodAccessInfoCollection =
+        appView.appInfo().getMethodAccessInfoCollection();
+    ThreadUtils.processItems(
+        methodAccessInfoCollection::forEachMethodReference,
+        method -> renameNonReboundMethodReference(method, nonReboundRenamings),
+        executorService);
+    renaming.putAll(nonReboundRenamings);
+  }
+
+  private void renameNonReboundMethodReference(
+      DexMethod method, Map<DexMethod, DexString> nonReboundRenamings) {
+    if (method.getHolderType().isArrayType()) {
+      return;
+    }
+
+    DexClass holder = appView.contextIndependentDefinitionFor(method.getHolderType());
+    if (holder == null) {
+      return;
+    }
+
+    ResolutionResult resolutionResult = appView.appInfo().resolveMethodOn(holder, method);
+    if (resolutionResult.isSingleResolution()) {
+      DexEncodedMethod resolvedMethod = resolutionResult.getSingleTarget();
+      if (resolvedMethod.getReference() == method) {
+        return;
+      }
+
+      DexString newName = renaming.get(resolvedMethod.getReference());
+      if (newName != null) {
+        assert newName != resolvedMethod.getName();
+        nonReboundRenamings.put(method, newName);
+      }
+      return;
+    }
+
+    // If resolution fails, the method must be renamed consistently with the targets that give rise
+    // to the failure.
+    assert resolutionResult.isFailedResolution();
+
+    List<DexEncodedMethod> targets = new ArrayList<>();
+    resolutionResult.asFailedResolution().forEachFailureDependency(targets::add);
+    if (!targets.isEmpty()) {
+      DexString newName = renaming.get(targets.get(0).getReference());
+      assert targets.stream().allMatch(target -> renaming.get(target.getReference()) == newName);
+      if (newName != null) {
+        assert newName != targets.get(0).getName();
+        nonReboundRenamings.put(method, newName);
+      }
+    }
+  }
+
   // Shuffles the given methods if assertions are enabled and deterministic debugging is disabled.
   // Used to ensure that the generated output is deterministic.
   private static Iterable<DexEncodedMethod> shuffleMethods(
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 a51edde..c44d311 100644
--- a/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MinifiedRenaming.java
@@ -20,9 +20,7 @@
 import com.android.tools.r8.naming.NamingLens.NonIdentityNamingLens;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import java.util.ArrayList;
 import java.util.IdentityHashMap;
-import java.util.List;
 import java.util.Map;
 
 class MinifiedRenaming extends NonIdentityNamingLens {
@@ -89,36 +87,12 @@
 
   @Override
   public DexString lookupName(DexMethod method) {
-    DexString renamed = renaming.get(method);
-    if (renamed != null) {
-      return renamed;
-    }
-    // If the method does not have a direct renaming, return the resolutions mapping.
-    ResolutionResult resolutionResult = appView.appInfo().unsafeResolveMethodDueToDexFormat(method);
-    if (resolutionResult.isSingleResolution()) {
-      return renaming.getOrDefault(resolutionResult.getSingleTarget().getReference(), method.name);
-    }
-    // If resolution fails, the method must be renamed consistently with the targets that give rise
-    // to the failure.
-    if (resolutionResult.isFailedResolution()) {
-      List<DexEncodedMethod> targets = new ArrayList<>();
-      resolutionResult.asFailedResolution().forEachFailureDependency(targets::add);
-      if (!targets.isEmpty()) {
-        DexString firstRename = renaming.get(targets.get(0).getReference());
-        assert targets.stream()
-            .allMatch(target -> renaming.get(target.getReference()) == firstRename);
-        if (firstRename != null) {
-          return firstRename;
-        }
-      }
-    }
-    // If no renaming can be found the default is the methods name.
-    return method.name;
+    return renaming.getOrDefault(method, method.getName());
   }
 
   @Override
   public DexString lookupName(DexField field) {
-    return renaming.getOrDefault(field, field.name);
+    return renaming.getOrDefault(field, field.getName());
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index c5b8ced..e7106a6 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -67,7 +67,7 @@
     timing.begin("MinifyMethods");
     MethodRenaming methodRenaming =
         new MethodNameMinifier(appView, subtypingInfo, minifyMembers)
-            .computeRenaming(interfaces, timing);
+            .computeRenaming(interfaces, executorService, timing);
     timing.end();
 
     assert new MinifiedRenaming(appView, classRenaming, methodRenaming, FieldRenaming.empty())
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index 92a507b..74737eb 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -145,7 +145,7 @@
     timing.begin("MinifyMethods");
     MethodRenaming methodRenaming =
         new MethodNameMinifier(appView, subtypingInfo, nameStrategy)
-            .computeRenaming(interfaces, timing);
+            .computeRenaming(interfaces, executorService, timing);
     // Amend the method renamings with the default interface methods.
     methodRenaming.renaming.putAll(defaultInterfaceMethodImplementationNames);
     methodRenaming.renaming.putAll(additionalMethodNamings);