Attempt to synthesize companion class only when needed
Bug: 183998768
Change-Id: I12b557568061c7a38dc0355a0d16b09f7ae24e7e
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index 83f051d..206a3ed 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -89,7 +89,43 @@
if (!iface.isInterface()) {
return;
}
+ analyzeBridges(iface);
+ if (needsCompanionClass(iface)) {
+ synthesizeCompanionClass(iface, synthesizedMethods);
+ }
+ }
+ private void analyzeBridges(DexProgramClass iface) {
+ for (ProgramMethod method : iface.virtualProgramMethods()) {
+ DexEncodedMethod virtual = method.getDefinition();
+ if (!interfaceMethodRemovalChangesApi(virtual, iface)) {
+ getPostProcessingInterfaceInfo(iface).setHasBridgesToRemove();
+ return;
+ }
+ }
+ }
+
+ private boolean needsCompanionClass(DexProgramClass iface) {
+ if (hasStaticMethodThatTriggersNonTrivialClassInitializer(iface)) {
+ return true;
+ }
+ for (ProgramMethod method : iface.virtualProgramMethods()) {
+ DexEncodedMethod virtual = method.getDefinition();
+ if (rewriter.isDefaultMethod(virtual)) {
+ return true;
+ }
+ }
+ for (ProgramMethod method : iface.directProgramMethods()) {
+ DexEncodedMethod definition = method.getDefinition();
+ if (!definition.isInitializer()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void synthesizeCompanionClass(
+ DexProgramClass iface, ProgramMethodSet synthesizedMethods) {
// The list of methods to be created in companion class.
List<DexEncodedMethod> companionMethods = new ArrayList<>();
@@ -102,9 +138,7 @@
// make private instance methods public static.
processDirectInterfaceMethods(iface, companionMethods);
- if (companionMethods.isEmpty()) {
- return; // No methods to create, companion class not needed.
- }
+ assert !companionMethods.isEmpty();
ClassAccessFlags companionClassFlags = iface.accessFlags.copy();
companionClassFlags.unsetAbstract();
@@ -260,20 +294,14 @@
getPostProcessingInterfaceInfo(iface)
.mapDefaultMethodToCompanionMethod(virtual, implMethod);
}
-
- if (!interfaceMethodRemovalChangesApi(virtual, iface)) {
- getPostProcessingInterfaceInfo(iface).setHasBridgesToRemove();
- }
}
}
private void processDirectInterfaceMethods(
DexProgramClass iface, List<DexEncodedMethod> companionMethods) {
- DexEncodedMethod clinit = null;
for (ProgramMethod method : iface.directProgramMethods()) {
DexEncodedMethod definition = method.getDefinition();
if (definition.isClassInitializer()) {
- clinit = definition;
continue;
}
if (definition.isInstanceInitializer()) {
@@ -283,6 +311,8 @@
continue;
}
+ getPostProcessingInterfaceInfo(iface).setHasNonClinitDirectMethods();
+
MethodAccessFlags originalFlags = method.getAccessFlags();
MethodAccessFlags newFlags = originalFlags.copy();
if (originalFlags.isPrivate()) {
@@ -343,12 +373,6 @@
companionMethods.add(implMethod);
getPostProcessingInterfaceInfo(iface).moveMethod(oldMethod, companionMethod);
}
-
- boolean hasNonClinitDirectMethods =
- iface.getMethodCollection().size() != (clinit == null ? 0 : 1);
- if (hasNonClinitDirectMethods) {
- getPostProcessingInterfaceInfo(iface).setHasNonClinitDirectMethods();
- }
}
private void clearDirectMethods(DexProgramClass iface) {