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();