Avoid that force inlining marks are overridden by delayed optimization feedback

Bug: 141735091
Change-Id: I1cad2d2da08c5f917c2e2840ab748ffd70dd4dd4
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
index 376e186..08aefe9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodOptimizationFeedback.java
@@ -19,6 +19,8 @@
 
 public interface MethodOptimizationFeedback {
 
+  void markForceInline(DexEncodedMethod method);
+
   void markInlinedIntoSingleCallSite(DexEncodedMethod method);
 
   void markMethodCannotBeKept(DexEncodedMethod method);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
index 162642c..d185a37 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
@@ -107,6 +107,11 @@
   // METHOD OPTIMIZATION INFO:
 
   @Override
+  public void markForceInline(DexEncodedMethod method) {
+    getMethodOptimizationInfoForUpdating(method).markForceInline();
+  }
+
+  @Override
   public synchronized void markInlinedIntoSingleCallSite(DexEncodedMethod method) {
     getMethodOptimizationInfoForUpdating(method).markInlinedIntoSingleCallSite();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
index ea5afa0..79b2e7f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackIgnore.java
@@ -44,6 +44,9 @@
   // METHOD OPTIMIZATION INFO:
 
   @Override
+  public void markForceInline(DexEncodedMethod method) {}
+
+  @Override
   public void markInlinedIntoSingleCallSite(DexEncodedMethod method) {}
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
index 537cbd1..9119b4b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackSimple.java
@@ -52,6 +52,11 @@
   // METHOD OPTIMIZATION INFO.
 
   @Override
+  public void markForceInline(DexEncodedMethod method) {
+    // Ignored.
+  }
+
+  @Override
   public synchronized void markInlinedIntoSingleCallSite(DexEncodedMethod method) {
     method.getMutableOptimizationInfo().markInlinedIntoSingleCallSite();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
index a90efc7..4ce3033 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaGroup.java
@@ -79,6 +79,10 @@
     }
   }
 
+  public final boolean allLambdas(Predicate<LambdaInfo> predicate) {
+    return !anyLambda(lambda -> !predicate.test(lambda));
+  }
+
   public final boolean anyLambda(Predicate<LambdaInfo> predicate) {
     assert verifyLambdaIds(false);
     for (LambdaInfo info : lambdas.values()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index f399ad6..89451c9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -228,6 +228,11 @@
     // sequential lambda ids, create group lambda classes.
     Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses = finalizeLambdaGroups();
 
+    // Mark all the implementation methods for force inlining.
+    for (LambdaGroup group : lambdaGroupsClasses.keySet()) {
+      group.forEachLambda(info -> info.clazz.virtualMethods().forEach(feedback::markForceInline));
+    }
+
     // Fixup optimization info to ensure that the optimization info does not refer to any merged
     // lambdas.
     LambdaMergerOptimizationInfoFixer optimizationInfoFixer =
@@ -238,7 +243,6 @@
     this.strategyFactory = (method, code) -> new ApplyStrategy(method, code, optimizationInfoFixer);
 
     // Add synthesized lambda group classes to the builder.
-
     for (Entry<LambdaGroup, DexProgramClass> entry : lambdaGroupsClasses.entrySet()) {
       DexProgramClass synthesizedClass = entry.getValue();
       appView.appInfo().addSynthesizedClass(synthesizedClass);
@@ -254,6 +258,18 @@
       synthesizedClass.forEachMethod(
           encodedMethod -> encodedMethod.markProcessed(ConstraintWithTarget.NEVER));
     }
+
+    // Verify that all implementation methods are marked for force inlining (i.e., check that the
+    // delayed optimization feedback has been flushed).
+    assert lambdaGroupsClasses.keySet().stream()
+        .allMatch(
+            group ->
+                group.allLambdas(
+                    lambda ->
+                        lambda.clazz.virtualMethods().stream()
+                            .map(DexEncodedMethod::getOptimizationInfo)
+                            .allMatch(MethodOptimizationInfo::forceInline)));
+
     converter.optimizeSynthesizedClasses(lambdaGroupsClasses.values(), executorService);
 
     // Rewrite lambda class references into lambda group class
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
index 4226daa..15d4160 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
@@ -105,14 +105,6 @@
         // anyways and our new method is a product of inlining.
         MethodAccessFlags accessFlags = MAIN_METHOD_FLAGS.copy();
 
-        // Mark all the impl methods for force inlining
-        // LambdaGroupVirtualMethodSourceCode relies on.
-        for (DexEncodedMethod implMethod : implMethods) {
-          if (implMethod != null) {
-            implMethod.getMutableOptimizationInfo().markForceInline();
-          }
-        }
-
         DexMethod method = factory.createMethod(group.getGroupClassType(), methodProto, methodName);
         result.add(
             new DexEncodedMethod(