Postpone EmulatedInterfaceProcessor interface modifications
- Processing of interface should be able to be performed
in any order.
Bug: 183998768
Change-Id: Iaae03d39628c97f4cb860133fc35afd5b9a605d2
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceProcessor.java
index 559172a..0a56ddb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceProcessor.java
@@ -285,12 +285,7 @@
if (appView.isAlreadyLibraryDesugared(emulatedInterface)) {
return;
}
- // TODO(b/183998768): Due to sequential dependencies we cannot generateEmulateInterfaceLibrary.
- // We need to merge this into a single loop. Uncomment the following line instead of running
- // it separately.
- // generateEmulateInterfaceLibrary(emulatedInterface);
- replaceInterfacesInEmulatedInterface(emulatedInterface);
- renameEmulatedInterface(emulatedInterface);
+ generateEmulateInterfaceLibrary(emulatedInterface);
}
@Override
@@ -300,6 +295,16 @@
assert syntheticClasses.isEmpty();
return;
}
+ for (DexType interfaceType : emulatedInterfaces.keySet()) {
+ DexClass theInterface = appView.definitionFor(interfaceType);
+ if (theInterface != null && theInterface.isProgramClass()) {
+ DexProgramClass emulatedInterface = theInterface.asProgramClass();
+ if (!appView.isAlreadyLibraryDesugared(emulatedInterface)) {
+ replaceInterfacesInEmulatedInterface(emulatedInterface);
+ renameEmulatedInterface(emulatedInterface);
+ }
+ }
+ }
syntheticClasses.forEach(
(interfaceClass, synthesizedClass) -> {
builder.addSynthesizedClass(synthesizedClass);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringProcessor.java
index d85e8a2..821ff44 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringProcessor.java
@@ -9,9 +9,19 @@
import com.android.tools.r8.utils.collections.ProgramMethodSet;
public interface InterfaceDesugaringProcessor {
+
boolean shouldProcess(DexProgramClass clazz);
+ // The process phase can be performed before, concurrently or after code desugaring. It can be
+ // executed concurrently on all classes. Each processing may require to read other classes,
+ // so this phase cannot modify the classes themselves (for example insertion/removal of methods).
+ // The phase can insert new classes with new methods, such as emulated interface dispatch classes
+ // or companion classes with their methods.
void process(DexProgramClass clazz, ProgramMethodSet synthesizedMethods);
+ // The finalization phase is done at a join point, after all code desugaring have been performed.
+ // All finalization phases of all desugaring processors are performed sequentially.
+ // Complex computations should be avoided if possible here and be moved to the concurrent phase.
+ // Classes may be mutated here (new methods can be inserted, etc.).
void finalizeProcessing(DexApplication.Builder<?> builder, ProgramMethodSet synthesizedMethods);
}
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 8fd5d23..c45a1e0 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
@@ -84,7 +84,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
import java.util.function.Predicate;
//
@@ -963,26 +962,29 @@
public void desugarInterfaceMethods(
Builder<?> builder, Flavor flavour, ExecutorService executorService)
throws ExecutionException {
- // TODO(b/183998768): Merge the following four sequential loops into a single one.
-
+ // During L8 compilation, emulated interfaces are processed to be renamed, to have
+ // their interfaces fixed-up and to generate the emulated dispatch code.
EmulatedInterfaceProcessor emulatedInterfaceProcessor =
new EmulatedInterfaceProcessor(appView, this);
- // TODO(b/183998768): Move this to emulatedInterfaceProcessor#process
- forEachProgramEmulatedInterface(emulatedInterfaceProcessor::generateEmulateInterfaceLibrary);
// Process all classes first. Add missing forwarding methods to
// replace desugared default interface methods.
- process(new ClassProcessor(appView, this), builder, flavour);
+ ClassProcessor classProcessor = new ClassProcessor(appView, this);
// Process interfaces, create companion or dispatch class if needed, move static
// methods to companion class, copy default interface methods to companion classes,
// make original default methods abstract, remove bridge methods, create dispatch
// classes if needed.
- process(new InterfaceProcessor(appView, this), builder, flavour);
+ InterfaceProcessor interfaceProcessor = new InterfaceProcessor(appView, this);
- // During L8 compilation, emulated interfaces are processed to be renamed, to have
- // their interfaces fixed-up and to generate the emulated dispatch code.
+ // TODO(b/183998768): Merge the following loops into a single one.
process(emulatedInterfaceProcessor, builder, flavour);
+ process(classProcessor, builder, flavour);
+ process(interfaceProcessor, builder, flavour);
+
+ classProcessor.finalizeProcessing(builder, synthesizedMethods);
+ interfaceProcessor.finalizeProcessing(builder, synthesizedMethods);
+ emulatedInterfaceProcessor.finalizeProcessing(builder, synthesizedMethods);
converter.processMethodsConcurrently(synthesizedMethods, executorService);
@@ -990,18 +992,6 @@
clear();
}
- private void forEachProgramEmulatedInterface(Consumer<DexProgramClass> consumer) {
- if (!appView.options().isDesugaredLibraryCompilation()) {
- return;
- }
- for (DexType interfaceType : emulatedInterfaces.keySet()) {
- DexClass theInterface = appView.definitionFor(interfaceType);
- if (theInterface != null && theInterface.isProgramClass()) {
- consumer.accept(theInterface.asProgramClass());
- }
- }
- }
-
private void clear() {
this.cache.clear();
this.synthesizedMethods.clear();
@@ -1020,7 +1010,6 @@
processor.process(clazz, synthesizedMethods);
}
}
- processor.finalizeProcessing(builder, synthesizedMethods);
}
final boolean isDefaultMethod(DexEncodedMethod method) {