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 {