Adjust accessibility for desugared lambdas prior to IR processing in R8

Bug: 146030818
Change-Id: I51cbdc7f951263c7cc6a6d1123d1bca8a7c0ac84
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 dbd455b..541bb0e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -796,8 +796,6 @@
       assert (dexCode.getDebugInfo() == null)
           || (arity == dexCode.getDebugInfo().parameters.length);
     } else {
-      assert appView.options().isDesugaredLibraryCompilation()
-          || appView.options().enableCfInterfaceMethodDesugaring;
       assert code.isCfCode();
       CfCode cfCode = code.asCfCode();
       cfCode.addFakeThisParameter(appView.dexItemFactory());
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index b3a6d66..b8ce45a 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -402,8 +402,11 @@
   private void synthesizeLambdaClasses(Builder<?> builder, ExecutorService executorService)
       throws ExecutionException {
     if (lambdaRewriter != null) {
-      lambdaRewriter.adjustAccessibility();
-      lambdaRewriter.synthesizeLambdaClasses(builder, executorService);
+      if (appView.enableWholeProgramOptimizations()) {
+        lambdaRewriter.finalizeLambdaDesugaringForR8(builder);
+      } else {
+        lambdaRewriter.finalizeLambdaDesugaringForD8(builder, executorService);
+      }
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index ce77849..8169472 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -484,7 +484,7 @@
     }
 
     // Ensure access of the referenced symbol(s).
-    abstract void ensureAccessibility();
+    abstract DexEncodedMethod ensureAccessibility();
 
     DexClass definitionFor(DexType type) {
       return rewriter.converter.appView.appInfo().app().definitionFor(type);
@@ -527,7 +527,9 @@
     }
 
     @Override
-    void ensureAccessibility() {}
+    DexEncodedMethod ensureAccessibility() {
+      return null;
+    }
   }
 
   // Used for static private lambda$ methods. Only needs access relaxation.
@@ -538,7 +540,7 @@
     }
 
     @Override
-    void ensureAccessibility() {
+    DexEncodedMethod ensureAccessibility() {
       // We already found the static method to be called, just relax its accessibility.
       assert descriptor.getAccessibility() != null;
       descriptor.getAccessibility().unsetPrivate();
@@ -546,6 +548,7 @@
       if (implMethodHolder.isInterface()) {
         descriptor.getAccessibility().setPublic();
       }
+      return null;
     }
   }
 
@@ -558,7 +561,7 @@
     }
 
     @Override
-    void ensureAccessibility() {
+    DexEncodedMethod ensureAccessibility() {
       // For all instantiation points for which the compiler creates lambda$
       // methods, it creates these methods in the same class/interface.
       DexMethod implMethod = descriptor.implHandle.asMethod();
@@ -589,11 +592,13 @@
           DexEncodedMethod.setDebugInfoWithFakeThisParameter(
               newMethod.getCode(), callTarget.getArity(), rewriter.converter.appView);
           implMethodHolder.setDirectMethod(i, newMethod);
-          return;
+
+          return newMethod;
         }
       }
       assert false
           : "Unexpected failure to find direct lambda target for: " + implMethod.qualifiedName();
+      return null;
     }
   }
 
@@ -605,7 +610,7 @@
     }
 
     @Override
-    void ensureAccessibility() {
+    DexEncodedMethod ensureAccessibility() {
       // For all instantiation points for which the compiler creates lambda$
       // methods, it creates these methods in the same class/interface.
       DexMethod implMethod = descriptor.implHandle.asMethod();
@@ -632,9 +637,11 @@
           // Move the method from the direct methods to the virtual methods set.
           implMethodHolder.removeDirectMethod(i);
           implMethodHolder.appendVirtualMethod(newMethod);
-          return;
+
+          return newMethod;
         }
       }
+      return null;
     }
   }
 
@@ -647,7 +654,7 @@
     }
 
     @Override
-    void ensureAccessibility() {
+    DexEncodedMethod ensureAccessibility() {
       // Create a static accessor with proper accessibility.
       DexProgramClass accessorClass = programDefinitionFor(callTarget.holder);
       assert accessorClass != null;
@@ -673,7 +680,7 @@
         accessorClass.appendDirectMethod(accessorEncodedMethod);
       }
 
-      rewriter.converter.optimizeSynthesizedMethod(accessorEncodedMethod);
+      return accessorEncodedMethod;
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index ed49900..36fd691 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -112,19 +112,28 @@
       OptimizationFeedbackDelayed feedback,
       LensCodeRewriter lensCodeRewriter)
       throws ExecutionException {
-    Set<DexProgramClass> synthesizedLambdaClasses = Sets.newIdentityHashSet();
+    Set<LambdaClass> synthesizedLambdaClasses = Sets.newIdentityHashSet();
+    Set<DexProgramClass> synthesizedLambdaProgramClasses = Sets.newIdentityHashSet();
     for (DexEncodedMethod method : wave) {
-      synthesizeLambdaClassesForMethod(method, synthesizedLambdaClasses::add, lensCodeRewriter);
+      synthesizeLambdaClassesForMethod(
+          method,
+          lambdaClass -> {
+            synthesizedLambdaClasses.add(lambdaClass);
+            synthesizedLambdaProgramClasses.add(lambdaClass.getOrCreateLambdaClass());
+          },
+          lensCodeRewriter);
     }
 
     if (synthesizedLambdaClasses.isEmpty()) {
       return;
     }
 
+    synthesizeAccessibilityBridgesForLambdaClasses(synthesizedLambdaClasses, executorService);
+
     // Record that the static fields on each lambda class are only written inside the static
     // initializer of the lambdas.
     Map<DexEncodedField, Set<DexEncodedMethod>> writesWithContexts = new IdentityHashMap<>();
-    for (DexProgramClass synthesizedLambdaClass : synthesizedLambdaClasses) {
+    for (DexProgramClass synthesizedLambdaClass : synthesizedLambdaProgramClasses) {
       DexEncodedMethod clinit = synthesizedLambdaClass.getClassInitializer();
       if (clinit != null) {
         for (DexEncodedField field : synthesizedLambdaClass.staticFields()) {
@@ -137,14 +146,28 @@
     appViewWithLiveness.setAppInfo(
         appViewWithLiveness.appInfo().withStaticFieldWrites(writesWithContexts));
 
-    converter.optimizeSynthesizedLambdaClasses(synthesizedLambdaClasses, executorService);
+    converter.optimizeSynthesizedLambdaClasses(synthesizedLambdaProgramClasses, executorService);
     feedback.updateVisibleOptimizationInfo();
   }
 
+  private void synthesizeAccessibilityBridgesForLambdaClasses(
+      Collection<LambdaClass> lambdaClasses, ExecutorService executorService)
+      throws ExecutionException {
+    Set<DexEncodedMethod> nonDexAccessibilityBridges = Sets.newIdentityHashSet();
+    for (LambdaClass lambdaClass : lambdaClasses) {
+      // This call may cause methodMapping to be updated.
+      DexEncodedMethod accessibilityBridge = lambdaClass.target.ensureAccessibility();
+      if (accessibilityBridge != null && !accessibilityBridge.getCode().isDexCode()) {
+        nonDexAccessibilityBridges.add(accessibilityBridge);
+      }
+    }
+    if (!nonDexAccessibilityBridges.isEmpty()) {
+      converter.processMethodsConcurrently(nonDexAccessibilityBridges, executorService);
+    }
+  }
+
   public void synthesizeLambdaClassesForMethod(
-      DexEncodedMethod method,
-      Consumer<DexProgramClass> consumer,
-      LensCodeRewriter lensCodeRewriter) {
+      DexEncodedMethod method, Consumer<LambdaClass> consumer, LensCodeRewriter lensCodeRewriter) {
     if (!method.hasCode() || method.isProcessed()) {
       // Nothing to desugar.
       return;
@@ -167,9 +190,7 @@
             LambdaDescriptor descriptor =
                 inferLambdaDescriptor(lensCodeRewriter.rewriteCallSite(callSite, method));
             if (descriptor != LambdaDescriptor.MATCH_FAILED) {
-              consumer.accept(
-                  getOrCreateLambdaClass(descriptor, method.method.holder)
-                      .getOrCreateLambdaClass());
+              consumer.accept(getOrCreateLambdaClass(descriptor, method.method.holder));
             }
           }
         });
@@ -241,21 +262,6 @@
     return false;
   }
 
-  /** Adjust accessibility of referenced application symbols or creates necessary accessors. */
-  public void adjustAccessibility() {
-    // For each lambda class perform necessary adjustment of the
-    // referenced symbols to make them accessible. This can result in
-    // method access relaxation or creation of accessor method.
-    for (LambdaClass lambdaClass : knownLambdaClasses.values()) {
-      // This call may cause methodMapping to be updated.
-      lambdaClass.target.ensureAccessibility();
-    }
-    if (appView.enableWholeProgramOptimizations() && !methodMapping.isEmpty()) {
-      appView.setGraphLense(
-          new LambdaRewriterGraphLense(methodMapping, appView.graphLense(), factory));
-    }
-  }
-
   /**
    * Returns a synthetic class for desugared lambda or `null` if the `type` does not represent one.
    * Method can be called concurrently.
@@ -266,8 +272,9 @@
   }
 
   /** Generates lambda classes and adds them to the builder. */
-  public void synthesizeLambdaClasses(Builder<?> builder, ExecutorService executorService)
+  public void finalizeLambdaDesugaringForD8(Builder<?> builder, ExecutorService executorService)
       throws ExecutionException {
+    synthesizeAccessibilityBridgesForLambdaClasses(knownLambdaClasses.values(), executorService);
     AppInfo appInfo = appView.appInfo();
     for (LambdaClass lambdaClass : knownLambdaClasses.values()) {
       DexProgramClass synthesizedClass = lambdaClass.getOrCreateLambdaClass();
@@ -281,6 +288,20 @@
         executorService);
   }
 
+  /** Generates lambda classes and adds them to the builder. */
+  public void finalizeLambdaDesugaringForR8(Builder<?> builder) {
+    if (!methodMapping.isEmpty()) {
+      appView.setGraphLense(
+          new LambdaRewriterGraphLense(methodMapping, appView.graphLense(), factory));
+    }
+    AppInfo appInfo = appView.appInfo();
+    for (LambdaClass lambdaClass : knownLambdaClasses.values()) {
+      DexProgramClass synthesizedClass = lambdaClass.getOrCreateLambdaClass();
+      appInfo.addSynthesizedClass(synthesizedClass);
+      builder.addSynthesizedClass(synthesizedClass, lambdaClass.addToMainDexList.get());
+    }
+  }
+
   public Set<DexCallSite> getDesugaredCallSites() {
     synchronized (knownCallSites) {
       return knownCallSites.keySet();