Introduce desugaring precedence sets
Bug: 191656218
Change-Id: I2db490640965c4c99eca518b64b93b181e419b23
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index b4da192..7a3dd75 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -29,8 +29,10 @@
import com.android.tools.r8.ir.desugar.twr.TwrInstructionDesugaring;
import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThrowingConsumer;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
@@ -75,14 +77,15 @@
if (appView.options().enableBackportedMethodRewriting()) {
backportedMethodRewriter = new BackportedMethodRewriter(appView);
}
- // Place TWR before Interface desugaring to eliminate potential $closeResource interface calls.
if (appView.options().enableTryWithResourcesDesugaring()) {
desugarings.add(new TwrInstructionDesugaring(appView));
}
if (appView.options().isInterfaceMethodDesugaringEnabled()) {
interfaceMethodRewriter =
new InterfaceMethodRewriter(
- appView, backportedMethodRewriter, desugaredLibraryRetargeter);
+ appView,
+ SetUtils.newImmutableSetExcludingNullItems(
+ backportedMethodRewriter, desugaredLibraryRetargeter));
desugarings.add(interfaceMethodRewriter);
} else {
interfaceMethodRewriter = null;
@@ -91,9 +94,11 @@
appView.rewritePrefix.isRewriting()
? new DesugaredLibraryAPIConverter(
appView,
- interfaceMethodRewriter,
- desugaredLibraryRetargeter,
- backportedMethodRewriter)
+ SetUtils.newImmutableSetExcludingNullItems(
+ interfaceMethodRewriter, desugaredLibraryRetargeter, backportedMethodRewriter),
+ interfaceMethodRewriter != null
+ ? interfaceMethodRewriter.getEmulatedMethods()
+ : ImmutableSet.of())
: null;
if (desugaredLibraryAPIConverter != null) {
desugarings.add(desugaredLibraryAPIConverter);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAPIConverter.java
index 828e70c..4634977 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryAPIConverter.java
@@ -23,22 +23,22 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryWrapperSynthesizerEventConsumer.DesugaredLibraryClasspathWrapperSynthesizeEventConsumer;
-import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConversionCfCodeProvider;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringDiagnostic;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
@@ -67,31 +67,24 @@
private final AppView<?> appView;
private final DexItemFactory factory;
- // This is used to filter out double desugaring on backported methods.
- private final BackportedMethodRewriter backportedMethodRewriter;
- private final InterfaceMethodRewriter interfaceMethodRewriter;
- private final DesugaredLibraryRetargeter retargeter;
+ private final Set<CfInstructionDesugaring> precedingDesugarings;
+ private final Set<DexString> emulatedMethods;
private final DesugaredLibraryWrapperSynthesizer wrapperSynthesizor;
- private final Set<DexMethod> trackedCallBackAPIs;
private final Set<DexMethod> trackedAPIs;
public DesugaredLibraryAPIConverter(
AppView<?> appView,
- InterfaceMethodRewriter interfaceMethodRewriter,
- DesugaredLibraryRetargeter retargeter,
- BackportedMethodRewriter backportedMethodRewriter) {
+ Set<CfInstructionDesugaring> precedingDesugarings,
+ Set<DexString> emulatedMethods) {
this.appView = appView;
this.factory = appView.dexItemFactory();
- this.interfaceMethodRewriter = interfaceMethodRewriter;
- this.retargeter = retargeter;
- this.backportedMethodRewriter = backportedMethodRewriter;
+ this.precedingDesugarings = precedingDesugarings;
+ this.emulatedMethods = emulatedMethods;
this.wrapperSynthesizor = new DesugaredLibraryWrapperSynthesizer(appView);
if (appView.options().testing.trackDesugaredAPIConversions) {
- trackedCallBackAPIs = Sets.newConcurrentHashSet();
trackedAPIs = Sets.newConcurrentHashSet();
} else {
- trackedCallBackAPIs = null;
trackedAPIs = null;
}
}
@@ -176,10 +169,7 @@
// The problem is that a method can resolve into a library method which is not present at runtime,
// the code relies in that case on emulated interface dispatch. We should not convert such API.
private boolean isEmulatedInterfaceOverride(DexClassAndMethod invokedMethod) {
- if (interfaceMethodRewriter == null) {
- return false;
- }
- if (!interfaceMethodRewriter.getEmulatedMethods().contains(invokedMethod.getName())) {
+ if (!emulatedMethods.contains(invokedMethod.getName())) {
return false;
}
DexClassAndMethod interfaceResult =
@@ -195,18 +185,8 @@
}
private boolean isAlreadyDesugared(CfInvoke invoke, ProgramMethod context) {
- if (interfaceMethodRewriter != null
- && interfaceMethodRewriter.needsDesugaring(invoke, context)) {
- return true;
- }
- if (retargeter != null && retargeter.needsDesugaring(invoke, context)) {
- return true;
- }
- if (backportedMethodRewriter != null
- && backportedMethodRewriter.needsDesugaring(invoke, context)) {
- return true;
- }
- return false;
+ return Iterables.any(
+ precedingDesugarings, desugaring -> desugaring.needsDesugaring(invoke, context));
}
public static DexMethod methodWithVivifiedTypeInSignature(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 9ee3f54..09c13c0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -34,15 +34,12 @@
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.ValueType;
-import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.DesugarDescription;
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryConfiguration;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryRetargeter;
import com.android.tools.r8.ir.desugar.lambda.LambdaInstructionDesugaring;
import com.android.tools.r8.ir.desugar.stringconcat.StringConcatInstructionDesugaring;
import com.android.tools.r8.ir.optimize.UtilityMethodsForCodeOptimizations;
@@ -56,6 +53,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.structural.Ordered;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Collection;
@@ -108,8 +106,7 @@
private final Map<DexType, DefaultMethodsHelper.Collection> cache = new ConcurrentHashMap<>();
// This is used to filter out double desugaring on backported methods.
- private final BackportedMethodRewriter backportedMethodRewriter;
- private final DesugaredLibraryRetargeter desugaredLibraryRetargeter;
+ private final Set<CfInstructionDesugaring> precedingDesugarings;
/** Defines a minor variation in desugaring. */
public enum Flavor {
@@ -119,26 +116,10 @@
ExcludeDexResources
}
- // Constructor for cf to cf desugaring.
public InterfaceMethodRewriter(
- AppView<?> appView,
- BackportedMethodRewriter rewriter,
- DesugaredLibraryRetargeter desugaredLibraryRetargeter) {
+ AppView<?> appView, Set<CfInstructionDesugaring> precedingDesugarings) {
this.appView = appView;
- this.backportedMethodRewriter = rewriter;
- this.desugaredLibraryRetargeter = desugaredLibraryRetargeter;
- this.options = appView.options();
- this.factory = appView.dexItemFactory();
- this.helper = new InterfaceDesugaringSyntheticHelper(appView);
- initializeEmulatedInterfaceVariables();
- }
-
- // Constructor for IR desugaring.
- public InterfaceMethodRewriter(AppView<?> appView, IRConverter converter) {
- assert converter != null;
- this.appView = appView;
- this.backportedMethodRewriter = null;
- this.desugaredLibraryRetargeter = null;
+ this.precedingDesugarings = precedingDesugarings;
this.options = appView.options();
this.factory = appView.dexItemFactory();
this.helper = new InterfaceDesugaringSyntheticHelper(appView);
@@ -228,13 +209,8 @@
}
private boolean isAlreadyDesugared(CfInvoke invoke, ProgramMethod context) {
- // In Cf to Cf it is forbidden to desugar twice the same instruction, if the backported
- // method rewriter or the desugared library retargeter already desugar the instruction, they
- // take precedence and nothing has to be done here.
- return (backportedMethodRewriter != null
- && backportedMethodRewriter.needsDesugaring(invoke, context))
- || (desugaredLibraryRetargeter != null
- && desugaredLibraryRetargeter.needsDesugaring(invoke, context));
+ return Iterables.any(
+ precedingDesugarings, desugaring -> desugaring.needsDesugaring(invoke, context));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/utils/SetUtils.java b/src/main/java/com/android/tools/r8/utils/SetUtils.java
index 04b399d..0a53f60 100644
--- a/src/main/java/com/android/tools/r8/utils/SetUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/SetUtils.java
@@ -89,6 +89,16 @@
return builder.build();
}
+ public static <T> ImmutableSet<T> newImmutableSetExcludingNullItems(T... items) {
+ ImmutableSet.Builder<T> builder = ImmutableSet.builder();
+ for (T item : items) {
+ if (item != null) {
+ builder.add(item);
+ }
+ }
+ return builder.build();
+ }
+
public static <T, S> Set<T> mapIdentityHashSet(Set<S> set, Function<S, T> fn) {
Set<T> out = newIdentityHashSet(set.size());
for (S element : set) {