Generate accessor methods for private lambda methods in R8

Bug: 179889958
Change-Id: I311f377c0b1f05f4f4091de186709d45f7f179e4
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 477d8d8..d0131bc 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
@@ -256,7 +256,8 @@
   // Creates a delegation target for this particular lambda class. Note that we
   // should always be able to create targets for the lambdas we support.
   private Target createTarget(ProgramMethod accessedFrom) {
-    if (descriptor.delegatesToLambdaImplMethod()) {
+    if (appView.options().canAccessModifyLambdaImplementationMethods(appView)
+        && descriptor.delegatesToLambdaImplMethod()) {
       return createLambdaImplMethodTarget(accessedFrom);
     }
 
@@ -339,7 +340,7 @@
     assert descriptor.implHandle.type.isInvokeInstance() ||
         descriptor.implHandle.type.isInvokeDirect();
 
-    if (!descriptor.needsAccessor(accessedFrom)) {
+    if (!descriptor.needsAccessor(appView, accessedFrom)) {
       return new NoAccessorMethodTarget(Invoke.Type.VIRTUAL);
     }
     // We need to generate an accessor method in `accessedFrom` class/interface
@@ -371,7 +372,7 @@
   private Target createStaticMethodTarget(ProgramMethod accessedFrom) {
     assert descriptor.implHandle.type.isInvokeStatic();
 
-    if (!descriptor.needsAccessor(accessedFrom)) {
+    if (!descriptor.needsAccessor(appView, accessedFrom)) {
       return new NoAccessorMethodTarget(Invoke.Type.STATIC);
     }
 
@@ -395,7 +396,7 @@
     assert implHandle != null;
     assert implHandle.type.isInvokeConstructor();
 
-    if (!descriptor.needsAccessor(accessedFrom)) {
+    if (!descriptor.needsAccessor(appView, accessedFrom)) {
       return new NoAccessorMethodTarget(Invoke.Type.DIRECT);
     }
 
@@ -418,14 +419,14 @@
   // Create targets for interface methods.
   private Target createInterfaceMethodTarget(ProgramMethod accessedFrom) {
     assert descriptor.implHandle.type.isInvokeInterface();
-    assert !descriptor.needsAccessor(accessedFrom);
+    assert !descriptor.needsAccessor(appView, accessedFrom);
     return new NoAccessorMethodTarget(Invoke.Type.INTERFACE);
   }
 
   private DexString generateUniqueLambdaMethodName() {
     return appView
         .dexItemFactory()
-        .createString(LambdaRewriter.EXPECTED_LAMBDA_METHOD_PREFIX + descriptor.uniqueId);
+        .createString(LambdaRewriter.R8_LAMBDA_ACCESSOR_METHOD_PREFIX + descriptor.uniqueId);
   }
 
   // Represents information about the method lambda class need to delegate the call to. It may
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
index f661256..b0bca4f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
@@ -4,8 +4,11 @@
 
 package com.android.tools.r8.ir.desugar;
 
+import static com.android.tools.r8.ir.desugar.LambdaRewriter.JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX;
+
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -177,10 +180,14 @@
     return targetHolder == type;
   }
 
+  public boolean canAccessModifyLambdaImplementationMethods(AppView<?> appView) {
+    return appView.enableWholeProgramOptimizations();
+  }
+
   /** If the lambda delegates to lambda$ method. */
   public boolean delegatesToLambdaImplMethod() {
-    DexString methodName = implHandle.asMethod().name;
-    return methodName.toString().startsWith(LambdaRewriter.EXPECTED_LAMBDA_METHOD_PREFIX);
+    String methodName = implHandle.asMethod().getName().toString();
+    return methodName.startsWith(JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX);
   }
 
   /** Is a stateless lambda, i.e. lambda does not capture any values */
@@ -189,8 +196,9 @@
   }
 
   /** Checks if call site needs a accessor when referenced from `accessedFrom`. */
-  boolean needsAccessor(ProgramMethod accessedFrom) {
-    if (delegatesToLambdaImplMethod()) {
+  boolean needsAccessor(AppView<?> appView, ProgramMethod accessedFrom) {
+    if (appView.options().canAccessModifyLambdaImplementationMethods(appView)
+        && delegatesToLambdaImplMethod()) {
       return false;
     }
 
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 dbbaf99..3463db8 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
@@ -44,7 +44,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Function;
@@ -59,7 +58,8 @@
  */
 public class LambdaRewriter {
 
-  public static final String EXPECTED_LAMBDA_METHOD_PREFIX = "lambda$";
+  public static final String JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX = "lambda$";
+  public static final String R8_LAMBDA_ACCESSOR_METHOD_PREFIX = "access$lambda$";
   public static final String LAMBDA_INSTANCE_FIELD_NAME = "INSTANCE";
 
   private final AppView<?> appView;
@@ -73,8 +73,6 @@
   // NOTE: synchronize concurrent access on `knownLambdaClasses`.
   private final List<LambdaClass> knownLambdaClasses = new ArrayList<>();
 
-  private final Map<DexMethod, Integer> methodIds = new ConcurrentHashMap<>();
-
   public LambdaRewriter(AppView<?> appView) {
     this.appView = appView;
     this.instanceFieldName = appView.dexItemFactory().createString(LAMBDA_INSTANCE_FIELD_NAME);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index fe679ca..97925ac 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1397,6 +1397,15 @@
   }
 
   /**
+   * Allow access modification of synthetic lambda implementation methods in D8 to avoid generating
+   * an excessive amount of accessibility bridges. In R8, the lambda implementation methods are
+   * inlined into the synthesized accessibility bridges, thus we don't allow access modification.
+   */
+  public boolean canAccessModifyLambdaImplementationMethods(AppView<?> appView) {
+    return !appView.enableWholeProgramOptimizations();
+  }
+
+  /**
    * Dex2Oat issues a warning for abstract methods on non-abstract classes, so we never allow this.
    *
    * <p>Note that having an invoke instruction that targets an abstract method on a non-abstract
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index 389b0fa..e22d8df 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -167,7 +167,7 @@
         .withBuilderTransformation(ToolHelper::allowTestProguardOptions)
         .withBuilderTransformation(
             b -> b.addProguardConfiguration(PROGUARD_OPTIONS_N_PLUS, Origin.unknown()))
-        .withDexCheck(inspector -> checkLambdaCount(inspector, 35, "lambdadesugaringnplus"))
+        .withDexCheck(inspector -> checkLambdaCount(inspector, 36, "lambdadesugaringnplus"))
         .run();
 
     test("lambdadesugaringnplus", "lambdadesugaringnplus", "LambdasWithStaticAndDefaultMethods")
@@ -176,7 +176,7 @@
         .withBuilderTransformation(ToolHelper::allowTestProguardOptions)
         .withBuilderTransformation(
             b -> b.addProguardConfiguration(PROGUARD_OPTIONS_N_PLUS, Origin.unknown()))
-        .withDexCheck(inspector -> checkLambdaCount(inspector, 3, "lambdadesugaringnplus"))
+        .withDexCheck(inspector -> checkLambdaCount(inspector, 6, "lambdadesugaringnplus"))
         .run();
   }
 
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index a5a1a8a..6dc126c 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -2188,7 +2188,7 @@
 
       private static boolean isLambdaMethod(VmMirror mirror, Location location) {
         String methodName = mirror.getMethodName(location.classID, location.methodID);
-        return methodName.startsWith("lambda$");
+        return methodName.startsWith("lambda$") || methodName.startsWith("$private$lambda$");
       }
     }
 
diff --git a/src/test/java/com/android/tools/r8/debug/LambdaTest.java b/src/test/java/com/android/tools/r8/debug/LambdaTest.java
index f9e6c34..749c4b4 100644
--- a/src/test/java/com/android/tools/r8/debug/LambdaTest.java
+++ b/src/test/java/com/android/tools/r8/debug/LambdaTest.java
@@ -84,7 +84,6 @@
         checkMethod(debuggeeClass, initialMethodName),
         checkLine(SOURCE_FILE, 20),
         stepInto(INTELLIJ_FILTER),
-        config.isCfRuntime() ? LambdaTest::doNothing : stepInto(INTELLIJ_FILTER),
         checkMethod(debuggeeClass, "returnOne"),
         checkLine(SOURCE_FILE, 28),
         checkNoLocal(),
diff --git a/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java
index 7a97972..477af87 100644
--- a/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java
+++ b/src/test/java/com/android/tools/r8/desugar/DefaultLambdaWithSelfReferenceTestRunner.java
@@ -51,7 +51,7 @@
     this.parameters = parameters;
   }
 
-  private void runDebugger(DebugTestConfig config) throws Throwable {
+  private void runDebugger(DebugTestConfig config, boolean isR8) throws Throwable {
     MethodReference main = Reference.methodFromMethod(CLASS.getMethod("main", String[].class));
     Command checkThisLambda =
         conditional(
@@ -83,7 +83,9 @@
         stepInto(INTELLIJ_FILTER),
         checkLine(17),
         // When desugaring, the LambdaClass will change this to a static (later moved to companion).
-        checkThisLambda,
+        parameters.canUseDefaultAndStaticInterfaceMethods() && isR8
+            ? checkThisDefaultMethod
+            : checkThisLambda,
         run());
   }
 
@@ -92,7 +94,7 @@
     assumeTrue(parameters.isCfRuntime());
     JvmTestBuilder builder = testForJvm().addTestClasspath();
     builder.run(parameters.getRuntime(), CLASS).assertSuccessWithOutput(EXPECTED);
-    runDebugger(builder.debugConfig());
+    runDebugger(builder.debugConfig(), false);
   }
 
   @Test
@@ -111,7 +113,7 @@
         .run(parameters.getRuntime(), CLASS)
         .assertSuccessWithOutput(EXPECTED)
         .inspect(inspector -> assertThat(inspector.clazz(CLASS), isPresent()));
-    runDebugger(compileResult.debugConfig());
+    runDebugger(compileResult.debugConfig(), true);
   }
 
   @Test
@@ -168,7 +170,7 @@
         .run(parameters.getRuntime(), CLASS)
         .assertSuccessWithOutput(EXPECTED);
 
-    runDebugger(compiledResult.debugConfig());
+    runDebugger(compiledResult.debugConfig(), false);
 
     Path dissasemble1 = temp.newFolder().toPath().resolve("disassemble1.txt");
     Path dissasemble2 = temp.newFolder().toPath().resolve("disassemble2.txt");
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java
index bf507de..11b5e6c 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarInstanceLambdaWithReadsTest.java
@@ -3,12 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.desugar;
 
+import static com.android.tools.r8.ir.desugar.LambdaRewriter.JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX;
+import static com.android.tools.r8.ir.desugar.LambdaRewriter.R8_LAMBDA_ACCESSOR_METHOD_PREFIX;
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
@@ -41,7 +44,7 @@
         .addProgramClasses(Main.class, A.class, B.class, Consumer.class)
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutput(EXPECTED)
-        .inspect(this::checkJustOneLambdaImplementationMethod);
+        .inspect(inspector -> checkNumberOfLambdaMethods(inspector, false));
   }
 
   @Test
@@ -54,13 +57,27 @@
         .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), Main.class)
         .assertSuccessWithOutput(EXPECTED)
-        .inspect(this::checkJustOneLambdaImplementationMethod);
+        .inspect(inspector -> checkNumberOfLambdaMethods(inspector, true));
   }
 
-  private void checkJustOneLambdaImplementationMethod(CodeInspector inspector) {
+  private void checkNumberOfLambdaMethods(CodeInspector inspector, boolean isR8) {
+    // When generating DEX, only R8 synthesizes an accessor for the javac-generated lambda$ method.
+    List<FoundMethodSubject> lambdaAccessorMethods =
+        inspector
+            .clazz(Main.class)
+            .allMethods(m -> m.getOriginalName().startsWith(R8_LAMBDA_ACCESSOR_METHOD_PREFIX));
+    assertEquals(
+        BooleanUtils.intValue(parameters.isDexRuntime() && isR8), lambdaAccessorMethods.size());
+
+    // When generating DEX, R8 will inline the javac-generated lambda$ method into the synthesized
+    // $r8$lambda$ accessor method.
     List<FoundMethodSubject> lambdaImplementationMethods =
-        inspector.clazz(Main.class).allMethods(m -> m.getOriginalName().startsWith("lambda$"));
-    assertEquals(1, lambdaImplementationMethods.size());
+        inspector
+            .clazz(Main.class)
+            .allMethods(m -> m.getOriginalName().startsWith(JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX));
+    assertEquals(
+        1 - BooleanUtils.intValue(parameters.isDexRuntime() && isR8),
+        lambdaImplementationMethods.size());
   }
 
   private interface Consumer {
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java
index 5d84439..72549c5 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java
@@ -32,7 +32,7 @@
   private List<String> EXPECTED_JAVAC_RESULT =
       ImmutableList.of("Hello from inside lambda$test$0", "Hello from inside lambda$testStatic$1");
 
-  private List<String> EXPECTED_DESUGARED_RESULT =
+  private List<String> EXPECTED_D8_DESUGARED_RESULT =
       ImmutableList.of(
           "Hello from inside lambda$test$0$DesugarLambdaWithAnonymousClass$TestClass",
           "Hello from inside lambda$testStatic$1");
@@ -106,7 +106,7 @@
             r -> r.assertSuccessWithOutputLines(EXPECTED_JAVAC_RESULT))
         .applyIf(
             DesugarTestConfiguration::isDesugared,
-            r -> r.assertSuccessWithOutputLines(EXPECTED_DESUGARED_RESULT));
+            r -> r.assertSuccessWithOutputLines(EXPECTED_D8_DESUGARED_RESULT));
   }
 
   @Test
@@ -124,8 +124,7 @@
           .addKeepMainRule(TestClass.class)
           .run(parameters.getRuntime(), TestClass.class)
           .inspect(this::checkEnclosingMethod)
-          .assertSuccessWithOutputLines(
-              parameters.isCfRuntime() ? EXPECTED_JAVAC_RESULT : EXPECTED_DESUGARED_RESULT);
+          .assertSuccessWithOutputLines(EXPECTED_JAVAC_RESULT);
       assertFalse(parameters.isDexRuntime());
     } catch (AssertionError e) {
       assertTrue(parameters.isDexRuntime());
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithLocalClass.java b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithLocalClass.java
index f272f26..62c36fd 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithLocalClass.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithLocalClass.java
@@ -31,7 +31,7 @@
   private List<String> EXPECTED_JAVAC_RESULT =
       ImmutableList.of("Hello from inside lambda$test$0", "Hello from inside lambda$testStatic$1");
 
-  private List<String> EXPECTED_DESUGARED_RESULT =
+  private List<String> EXPECTED_D8_DESUGARED_RESULT =
       ImmutableList.of(
           "Hello from inside lambda$test$0$DesugarLambdaWithLocalClass$TestClass",
           "Hello from inside lambda$testStatic$1");
@@ -104,7 +104,7 @@
             r -> r.assertSuccessWithOutputLines(EXPECTED_JAVAC_RESULT))
         .applyIf(
             DesugarTestConfiguration::isDesugared,
-            r -> r.assertSuccessWithOutputLines(EXPECTED_DESUGARED_RESULT));
+            r -> r.assertSuccessWithOutputLines(EXPECTED_D8_DESUGARED_RESULT));
   }
 
   @Test
@@ -120,8 +120,7 @@
         .addKeepMainRule(TestClass.class)
         .run(parameters.getRuntime(), TestClass.class)
         .inspect(this::checkEnclosingMethod)
-        .assertSuccessWithOutputLines(
-            parameters.isCfRuntime() ? EXPECTED_JAVAC_RESULT : EXPECTED_JAVAC_RESULT);
+        .assertSuccessWithOutputLines(EXPECTED_JAVAC_RESULT);
   }
 
   public interface MyConsumer<T> {
diff --git a/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedInstanceLambdaMethodTest.java b/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedInstanceLambdaMethodTest.java
index b8769c3..ff70dab 100644
--- a/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedInstanceLambdaMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedInstanceLambdaMethodTest.java
@@ -4,14 +4,13 @@
 
 package com.android.tools.r8.desugar.lambdas;
 
-import static com.android.tools.r8.ir.desugar.LambdaRewriter.EXPECTED_LAMBDA_METHOD_PREFIX;
+import static com.android.tools.r8.ir.desugar.LambdaRewriter.JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX;
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.cf.CfVersion;
-import com.android.tools.r8.utils.codeinspector.AssertUtils;
 import java.io.IOException;
 import java.lang.reflect.Method;
 import java.util.stream.Stream;
@@ -38,7 +37,6 @@
     this.parameters = parameters;
   }
 
-  // TODO(b/179889958): Should succeed.
   @Test
   public void testRuntime() throws Exception {
     testForRuntime(parameters)
@@ -51,29 +49,22 @@
             result -> result.assertFailureWithErrorThatThrows(NoSuchMethodError.class));
   }
 
-  // TODO(b/179889958): Should succeed.
   @Test
   public void testR8() throws Exception {
-    AssertUtils.assertFailsCompilationIf(
-        parameters.isDexRuntime() && !parameters.canUseDefaultAndStaticInterfaceMethods(),
-        () ->
-            testForR8(parameters.getBackend())
-                .addProgramClasses(Main.class, A.class, FunctionalInterface.class)
-                .addProgramClassFileData(getProgramClassFileData())
-                .addKeepMainRule(Main.class)
-                .setMinApi(parameters.getApiLevel())
-                .compile()
-                .run(parameters.getRuntime(), Main.class)
-                .applyIf(
-                    parameters.isCfRuntime(),
-                    result -> result.assertSuccessWithOutputLines("Hello world!", "Hello world!"),
-                    result -> result.assertFailureWithErrorThatThrows(NoSuchMethodError.class)));
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Main.class, A.class, FunctionalInterface.class)
+        .addProgramClassFileData(getProgramClassFileData())
+        .addKeepMainRule(Main.class)
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("Hello world!", "Hello world!");
   }
 
   private byte[] getProgramClassFileData() throws IOException {
     Method lambdaMethod =
         Stream.of(I.class.getDeclaredMethods())
-            .filter(x -> x.getName().contains(EXPECTED_LAMBDA_METHOD_PREFIX))
+            .filter(x -> x.getName().contains(JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX))
             .findFirst()
             .get();
     return transformer(I.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedStaticLambdaMethodTest.java b/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedStaticLambdaMethodTest.java
index e14d2f3..029f690 100644
--- a/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedStaticLambdaMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/lambdas/ExplicitCallToJavacGeneratedStaticLambdaMethodTest.java
@@ -4,7 +4,7 @@
 
 package com.android.tools.r8.desugar.lambdas;
 
-import static com.android.tools.r8.ir.desugar.LambdaRewriter.EXPECTED_LAMBDA_METHOD_PREFIX;
+import static com.android.tools.r8.ir.desugar.LambdaRewriter.JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX;
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -60,7 +60,7 @@
   private byte[] getProgramClassFileData() throws IOException {
     Method lambdaMethod =
         Stream.of(I.class.getDeclaredMethods())
-            .filter(x -> x.getName().contains(EXPECTED_LAMBDA_METHOD_PREFIX))
+            .filter(x -> x.getName().contains(JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX))
             .findFirst()
             .get();
     return transformer(I.class)
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java b/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java
index 2836f61..437b725 100644
--- a/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/naming/retrace/DesugarLambdaRetraceTest.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.naming.retrace;
 
+import static com.android.tools.r8.ir.desugar.LambdaRewriter.R8_LAMBDA_ACCESSOR_METHOD_PREFIX;
 import static com.android.tools.r8.naming.retrace.StackTrace.isSame;
 import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileName;
 import static com.android.tools.r8.naming.retrace.StackTrace.isSameExceptForFileNameAndLineNumber;
@@ -52,7 +53,7 @@
   private int expectedActualStackTraceHeight() {
     // In DEX release the entire lambda is inlined.
     if (parameters.isDexRuntime()) {
-      return mode == CompilationMode.RELEASE ? 1 : 5;
+      return mode == CompilationMode.RELEASE ? 1 : 6;
     }
     // In CF release it is not and in debug there is no lambda desugaring thus the shorter stack.
     return mode == CompilationMode.RELEASE ? 2 : 4;
@@ -60,19 +61,22 @@
 
   private boolean isSynthesizedLambdaFrame(StackTraceLine line) {
     // TODO(141287349): The mapping should not map the external name to the internal name!
-    return SyntheticItemsTestUtils.isInternalLambda(Reference.classFromTypeName(line.className));
+    return SyntheticItemsTestUtils.isInternalLambda(Reference.classFromTypeName(line.className))
+        || line.methodName.startsWith(R8_LAMBDA_ACCESSOR_METHOD_PREFIX);
   }
 
-  private void checkLambdaFrame(StackTrace retracedStackTrace) {
+  private void checkLambdaFrames(StackTrace retracedStackTrace) {
     StackTrace lambdaFrames = retracedStackTrace.filter(this::isSynthesizedLambdaFrame);
-    assertEquals(1, lambdaFrames.size());
-    if (lambdaFrames.get(0).hasLineNumber()) {
-      assertEquals(mode == CompilationMode.RELEASE ? 0 : 2, lambdaFrames.get(0).lineNumber);
+    assertEquals(2, lambdaFrames.size());
+
+    StackTraceLine syntheticLambdaClassFrame = lambdaFrames.get(1);
+    if (syntheticLambdaClassFrame.hasLineNumber()) {
+      assertEquals(mode == CompilationMode.RELEASE ? 0 : 2, syntheticLambdaClassFrame.lineNumber);
     }
     // Proguard retrace will take the class name until the first $ to construct the file
     // name, so for "-$$Lambda$...", the file name becomes "-.java".
-    // TODO(b/141287349): Format the class name of desugard lambda classes.
-    // assertEquals("-.java", lambdaFrames.get(0).fileName);
+    // TODO(b/141287349): Format the class name of desugared lambda classes.
+    // assertEquals("-.java", syntheticLambdaClassFrame.fileName);
   }
 
   private void checkIsSame(StackTrace actualStackTrace, StackTrace retracedStackTrace) {
@@ -85,7 +89,7 @@
           retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)),
           isSame(expectedStackTrace));
       // Check the frame from the lambda class.
-      checkLambdaFrame(retracedStackTrace);
+      checkLambdaFrames(retracedStackTrace);
     }
     assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
   }
@@ -96,12 +100,12 @@
     if (parameters.isCfRuntime()) {
       assertThat(retracedStackTrace, isSameExceptForFileName(expectedStackTrace));
     } else {
-      // With the frame from the lambda class filtered out the stack trace is the same.
+      // With the frames from the lambda class filtered out the stack trace is the same.
       assertThat(
           retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)),
           isSameExceptForFileName(expectedStackTrace));
       // Check the frame from the lambda class.
-      checkLambdaFrame(retracedStackTrace);
+      checkLambdaFrames(retracedStackTrace);
     }
     assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
   }
@@ -117,7 +121,7 @@
           retracedStackTrace.filter(line -> !isSynthesizedLambdaFrame(line)),
           isSameExceptForFileNameAndLineNumber(expectedStackTrace));
       // Check the frame from the lambda class.
-      checkLambdaFrame(retracedStackTrace);
+      checkLambdaFrames(retracedStackTrace);
     }
     assertEquals(expectedActualStackTraceHeight(), actualStackTrace.size());
   }
diff --git a/src/test/java/com/android/tools/r8/regress/b163264839/Regress163264839Test.java b/src/test/java/com/android/tools/r8/regress/b163264839/Regress163264839Test.java
index 541ca47..1527d17 100644
--- a/src/test/java/com/android/tools/r8/regress/b163264839/Regress163264839Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b163264839/Regress163264839Test.java
@@ -49,8 +49,7 @@
             .addProgramClasses(TestClass.class)
             .run(parameters.getRuntime(), TestClass.class);
 
-    if (isInterface
-        || (parameters.isCfRuntime() && parameters.getRuntime().asCf().getVm().equals(CfVm.JDK8))) {
+    if (isInterface || parameters.isCfRuntime(CfVm.JDK8)) {
       // JDK 8 allows mismatched method references in this case.
       result.assertSuccessWithOutput(EXPECTED);
     } else {