Don't encode stateless lambdas as singletons.
Bug: 222081665
Change-Id: I3a047573ca41a59fa4b665c10c489dbd717751fd
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 a014283..27298a9 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
@@ -99,13 +99,15 @@
this.target = createTarget(accessedFrom);
- boolean stateless = isStateless();
+ boolean statelessSingleton = isStatelessSingleton();
this.classConstructor =
- !stateless
- ? null
- : factory.createMethod(type, constructorProto, factory.classConstructorMethodName);
+ statelessSingleton
+ ? factory.createMethod(type, constructorProto, factory.classConstructorMethodName)
+ : null;
this.lambdaField =
- !stateless ? null : factory.createField(type, type, factory.lambdaInstanceFieldName);
+ statelessSingleton
+ ? factory.createField(type, type, factory.lambdaInstanceFieldName)
+ : null;
// Synthesize the program class once all fields are set.
synthesizeLambdaClass(builder, desugarInvoke);
@@ -145,8 +147,8 @@
appView.dexItemFactory().createString("f$" + index));
}
- public final boolean isStateless() {
- return descriptor.isStateless();
+ public final boolean isStatelessSingleton() {
+ return appView.options().createSingletonsForStatelessLambdas && descriptor.isStateless();
}
// Synthesize virtual methods.
@@ -193,13 +195,14 @@
// Synthesize direct methods.
private void synthesizeDirectMethods(SyntheticProgramClassBuilder builder) {
- boolean stateless = isStateless();
- List<DexEncodedMethod> methods = new ArrayList<>(stateless ? 2 : 1);
+ boolean statelessSingleton = isStatelessSingleton();
+ List<DexEncodedMethod> methods = new ArrayList<>(statelessSingleton ? 2 : 1);
// Constructor.
MethodAccessFlags accessFlags =
MethodAccessFlags.fromSharedAccessFlags(
- (stateless ? Constants.ACC_PRIVATE : Constants.ACC_PUBLIC) | Constants.ACC_SYNTHETIC,
+ (statelessSingleton ? Constants.ACC_PRIVATE : Constants.ACC_PUBLIC)
+ | Constants.ACC_SYNTHETIC,
true);
methods.add(
DexEncodedMethod.syntheticBuilder()
@@ -211,7 +214,7 @@
.build());
// Class constructor for stateless lambda classes.
- if (stateless) {
+ if (statelessSingleton) {
methods.add(
DexEncodedMethod.syntheticBuilder()
.setMethod(classConstructor)
@@ -249,7 +252,7 @@
// Synthesize static fields to represent singleton instance.
private void synthesizeStaticFields(SyntheticProgramClassBuilder builder) {
- if (isStateless()) {
+ if (isStatelessSingleton()) {
// Create instance field for stateless lambda.
assert this.lambdaField != null;
builder.setStaticFields(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
index 4c45086..f7e8d1a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
@@ -121,7 +121,7 @@
eventConsumer.acceptLambdaClass(lambdaClass, context);
- if (lambdaClass.isStateless()) {
+ if (lambdaClass.isStatelessSingleton()) {
return ImmutableList.of(
new CfStaticFieldRead(lambdaClass.lambdaField, lambdaClass.lambdaField));
}
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 2b8d72a..2408193 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -359,6 +359,10 @@
// Boolean value indicating that byte code pass through may be enabled.
public boolean enableCfByteCodePassThrough = false;
+ // Flag to control the representation of stateless lambdas.
+ // See b/222081665 for context.
+ public boolean createSingletonsForStatelessLambdas = false;
+
// Contain the contents of the build properties file from the compiler command.
public DumpOptions dumpOptions;
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
index ec8d314..8478b17 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidOTest.java
@@ -131,7 +131,7 @@
.withMinApiLevel(ToolHelper.getMinApiLevelForDexVmNoHigherThan(AndroidApiLevel.K))
.withBuilderTransformation(
b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 3, "lambdadesugaring"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 4, "lambdadesugaring"))
.run();
}
@@ -170,7 +170,7 @@
.withMinApiLevel(AndroidApiLevel.N)
.withBuilderTransformation(
b -> b.addProguardConfiguration(PROGUARD_OPTIONS, Origin.unknown()))
- .withDexCheck(inspector -> checkLambdaCount(inspector, 3, "lambdadesugaring"))
+ .withDexCheck(inspector -> checkLambdaCount(inspector, 4, "lambdadesugaring"))
.run();
}