Lazy synthetic item synthesis in LibraryRetargeter

Bug: 188767735
Change-Id: I903794cb064cb26f6db6fb01f7d36ca8113a4000
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
index 2460c25..68aca31 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -286,6 +286,12 @@
       DexType newHolder = backportCoreLibraryMembers.get(method.holder);
       return appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
     }
+    DexClassAndMethod emulatedMethod = emulatedDispatchMethods.get(method);
+    if (emulatedMethod != null) {
+      assert !emulatedMethod.getAccessFlags().isStatic();
+      DexType newHolder = ensureEmulatedHolderDispatchMethod(emulatedMethod).type;
+      return computeRetargetMethod(method, emulatedMethod.getAccessFlags().isStatic(), newHolder);
+    }
     return retargetLibraryMember.get(method);
   }
 
@@ -302,6 +308,12 @@
     return false;
   }
 
+  DexMethod computeRetargetMethod(DexMethod method, boolean isStatic, DexType newHolder) {
+    DexItemFactory factory = appView.dexItemFactory();
+    DexProto newProto = isStatic ? method.getProto() : factory.prependHolderToProto(method);
+    return factory.createMethod(newHolder, newProto, method.getName());
+  }
+
   private class RetargetingSetup {
 
     private void setUpRetargeting() {
@@ -316,6 +328,7 @@
             DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
             List<DexClassAndMethod> found = findMethodsWithName(methodName, typeClass);
             for (DexClassAndMethod method : found) {
+              boolean emulatedDispatch = false;
               DexMethod methodReference = method.getReference();
               if (!typeClass.isFinal()) {
                 nonFinalHolderRewrites.putIfAbsent(method.getName(), new ArrayList<>());
@@ -328,12 +341,16 @@
                     // Virtual rewrites require emulated dispatch for inheritance.
                     // The call is rewritten to the dispatch holder class instead.
                     emulatedDispatchMethods.add(method);
-                    // TODO(b/188767735): Postpone until needed.
-                    newHolder = ensureEmulatedHolderDispatchMethod(method).type;
+                    emulatedDispatch = true;
                   }
                 }
               }
-              retargetLibraryMember.put(methodReference, computeRetargetMethod(method, newHolder));
+              if (!emulatedDispatch) {
+                retargetLibraryMember.put(
+                    methodReference,
+                    computeRetargetMethod(
+                        methodReference, method.getAccessFlags().isStatic(), newHolder));
+              }
             }
           }
         }
@@ -350,13 +367,12 @@
             itemFactory.createMethod(
                 itemFactory.createType(itemFactory.arraysDescriptor), proto, name);
         DexMethod target =
-            itemFactory.createMethod(
-                itemFactory.createType("Ljava/util/DesugarArrays;"), proto, name);
+            computeRetargetMethod(
+                source, true, itemFactory.createType("Ljava/util/DesugarArrays;"));
         retargetLibraryMember.put(source, target);
 
         // TODO(b/181629049): This is only a workaround rewriting invokes of
         //  j.u.TimeZone.getTimeZone taking a java.time.ZoneId.
-        // to j.u.DesugarArrays.deepEquals0.
         name = itemFactory.createString("getTimeZone");
         proto =
             itemFactory.createProto(
@@ -365,8 +381,8 @@
         source =
             itemFactory.createMethod(itemFactory.createType("Ljava/util/TimeZone;"), proto, name);
         target =
-            itemFactory.createMethod(
-                itemFactory.createType("Ljava/util/DesugarTimeZone;"), proto, name);
+            computeRetargetMethod(
+                source, true, itemFactory.createType("Ljava/util/DesugarTimeZone;"));
         retargetLibraryMember.put(source, target);
       }
     }
@@ -402,15 +418,6 @@
       return false;
     }
 
-    private DexMethod computeRetargetMethod(DexClassAndMethod method, DexType newHolder) {
-      DexItemFactory factory = appView.dexItemFactory();
-      DexProto newProto =
-          method.getAccessFlags().isStatic()
-              ? method.getProto()
-              : factory.prependHolderToProto(method.getReference());
-      return factory.createMethod(newHolder, newProto, method.getName());
-    }
-
     private List<DexClassAndMethod> findMethodsWithName(DexString methodName, DexClass clazz) {
       List<DexClassAndMethod> found = new ArrayList<>();
       clazz.forEachClassMethodMatching(
@@ -648,7 +655,6 @@
         return;
       }
       for (DexClassAndMethod emulatedDispatchMethod : emulatedDispatchMethods) {
-        ensureEmulatedInterfaceDispatchMethod(emulatedDispatchMethod);
         ensureEmulatedHolderDispatchMethod(emulatedDispatchMethod);
       }
     }
diff --git a/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java b/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java
index 797d8b6..4838419 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/DexClassAndMethodSetBase.java
@@ -40,6 +40,10 @@
     methods.forEach(this::add);
   }
 
+  public T get(DexMethod method) {
+    return backing.get(method);
+  }
+
   public boolean contains(DexEncodedMethod method) {
     return backing.containsKey(method.getReference());
   }