Remove context-dependent main-dex placement of synthetics.
Bug: 178127572
Bug: 181010111
Change-Id: Ic94a69ef0b0bc6d6d78887be7b0dfd6de8b4e1e0
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 679062f..5d62aae 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -131,7 +131,6 @@
assert checkIfObsolete();
assert context != null;
syntheticItems.addLegacySyntheticClass(clazz, context);
- mainDexInfo.addLegacySyntheticClass(clazz, context);
}
public void addSynthesizedClass(DexProgramClass clazz, Iterable<DexProgramClass> contexts) {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index cd90e16..c8d9834 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -100,14 +100,6 @@
commit, getClassToFeatureSplitMap(), getMainDexInfo(), getMissingClasses());
}
- public final AppInfoWithClassHierarchy rebuildWithClassHierarchy(MissingClasses missingClasses) {
- return new AppInfoWithClassHierarchy(
- getSyntheticItems().commit(app()),
- getClassToFeatureSplitMap(),
- getMainDexInfo(),
- missingClasses);
- }
-
public AppInfoWithClassHierarchy rebuildWithClassHierarchy(
Function<DexApplication, DexApplication> fn) {
assert checkIfObsolete();
@@ -123,7 +115,10 @@
assert getClass() == AppInfoWithClassHierarchy.class;
assert checkIfObsolete();
return new AppInfoWithClassHierarchy(
- getSyntheticItems().commit(app()), classToFeatureSplitMap, mainDexInfo, missingClasses);
+ getSyntheticItems().commit(app()),
+ getClassToFeatureSplitMap(),
+ mainDexInfo,
+ getMissingClasses());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
index 4bb2981..4e579f2 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
@@ -18,12 +18,9 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.utils.ConsumerUtils;
-import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.Sets;
import java.util.Collections;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
public class MainDexInfo {
@@ -34,7 +31,6 @@
Collections.emptySet(),
Collections.emptySet(),
Collections.emptySet(),
- Collections.emptySet(),
false);
public enum MainDexGroup {
@@ -46,7 +42,6 @@
// Specific set of classes specified to be in main-dex
private final Set<DexType> classList;
- private final Map<DexType, DexType> synthesizedClassesMap;
// Traced roots are traced main dex references.
private final Set<DexType> tracedRoots;
// Traced method roots are the methods visited from an initial main dex root set. The set is
@@ -64,7 +59,6 @@
Collections.emptySet(),
Collections.emptySet(),
Collections.emptySet(),
- /* synthesized classes - cannot be emptyset */ Sets.newIdentityHashSet(),
false);
}
@@ -73,17 +67,13 @@
Set<DexType> tracedRoots,
Set<DexMethod> tracedMethodRoots,
Set<DexType> tracedDependencies,
- Set<DexType> synthesizedClasses,
boolean tracedMethodRootsCleared) {
this.classList = classList;
this.tracedRoots = tracedRoots;
this.tracedMethodRoots = tracedMethodRoots;
this.tracedDependencies = tracedDependencies;
- this.synthesizedClassesMap = new ConcurrentHashMap<>();
this.tracedMethodRootsCleared = tracedMethodRootsCleared;
- synthesizedClasses.forEach(type -> synthesizedClassesMap.put(type, type));
assert tracedDependencies.stream().noneMatch(tracedRoots::contains);
- assert tracedRoots.containsAll(synthesizedClasses);
}
public boolean isNone() {
@@ -91,15 +81,6 @@
return this == NONE;
}
- public boolean isMainDexTypeThatShouldIncludeDependencies(DexType type) {
- // Dependencies of 'type' are only needed if 'type' is a direct/executed main-dex type.
- return classList.contains(type) || tracedRoots.contains(type);
- }
-
- public boolean isMainDex(ProgramDefinition definition) {
- return isFromList(definition) || isTracedRoot(definition) || isDependency(definition);
- }
-
public boolean isFromList(ProgramDefinition definition) {
return isFromList(definition.getContextType());
}
@@ -225,35 +206,6 @@
return NONE;
}
- // TODO(b/178127572): This mutates the MainDexClasses which otherwise should be immutable.
- public void addSyntheticClass(DexProgramClass clazz) {
- // TODO(b/178127572): This will add a synthesized type as long as the initial set is not empty.
- // A better approach would be to use the context for the synthetic with a containment check.
- assert !isNone();
- if (!classList.isEmpty()) {
- synthesizedClassesMap.computeIfAbsent(
- clazz.type,
- type -> {
- classList.add(type);
- return type;
- });
- }
- if (!tracedRoots.isEmpty()) {
- synthesizedClassesMap.computeIfAbsent(
- clazz.type,
- type -> {
- tracedRoots.add(type);
- return type;
- });
- }
- }
-
- public void addLegacySyntheticClass(DexProgramClass clazz, ProgramDefinition context) {
- if (isTracedRoot(context) || isFromList(context) || isDependency(context)) {
- addSyntheticClass(clazz);
- }
- }
-
public int size() {
return classList.size() + tracedRoots.size() + tracedDependencies.size();
}
@@ -279,11 +231,7 @@
}
Set<DexType> removedClasses = prunedItems.getRemovedClasses();
Set<DexType> modifiedClassList = Sets.newIdentityHashSet();
- Set<DexType> modifiedSynthesized = Sets.newIdentityHashSet();
classList.forEach(type -> ifNotRemoved(type, removedClasses, modifiedClassList::add));
- synthesizedClassesMap
- .keySet()
- .forEach(type -> ifNotRemoved(type, removedClasses, modifiedSynthesized::add));
MainDexInfo.Builder builder = builder();
tracedRoots.forEach(type -> ifNotRemoved(type, removedClasses, builder::addRoot));
// TODO(b/169927809): Methods could be pruned without the holder being pruned, however, one has
@@ -293,7 +241,7 @@
ifNotRemoved(
method.getHolderType(), removedClasses, ignored -> builder.addRoot(method)));
tracedDependencies.forEach(type -> ifNotRemoved(type, removedClasses, builder::addDependency));
- return builder.build(modifiedClassList, modifiedSynthesized);
+ return builder.build(modifiedClassList);
}
private void ifNotRemoved(
@@ -305,10 +253,8 @@
public MainDexInfo rewrittenWithLens(GraphLens lens) {
Set<DexType> modifiedClassList = Sets.newIdentityHashSet();
- Set<DexType> modifiedSynthesized = Sets.newIdentityHashSet();
classList.forEach(
type -> rewriteAndApplyIfNotPrimitiveType(lens, type, modifiedClassList::add));
- synthesizedClassesMap.keySet().forEach(type -> modifiedSynthesized.add(lens.lookupType(type)));
MainDexInfo.Builder builder = builder();
tracedRoots.forEach(type -> rewriteAndApplyIfNotPrimitiveType(lens, type, builder::addRoot));
tracedMethodRoots.forEach(method -> builder.addRoot(lens.getRenamedMethodSignature(method)));
@@ -322,7 +268,7 @@
rewriteAndApplyIfNotPrimitiveType(lens, type, builder::addDependency);
}
});
- return builder.build(modifiedClassList, modifiedSynthesized);
+ return builder.build(modifiedClassList);
}
public Builder builder() {
@@ -414,20 +360,14 @@
return new MainDexInfo(list);
}
- public MainDexInfo build(Set<DexType> classList, Set<DexType> synthesizedClasses) {
+ public MainDexInfo build(Set<DexType> classList) {
// Class can contain dependencies which we should not regard as roots.
assert list.isEmpty();
- return new MainDexInfo(
- classList,
- SetUtils.unionIdentityHashSet(roots, synthesizedClasses),
- methodRoots,
- Sets.difference(dependencies, synthesizedClasses),
- synthesizedClasses,
- tracedMethodRootsCleared);
+ return new MainDexInfo(classList, roots, methodRoots, dependencies, tracedMethodRootsCleared);
}
public MainDexInfo build(MainDexInfo previous) {
- return build(previous.classList, previous.synthesizedClassesMap.keySet());
+ return build(previous.classList);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index 68bca58..3e8f334 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.shaking.MainDexInfo;
import java.util.Comparator;
/**
@@ -126,19 +125,6 @@
appView.rewritePrefix.rewriteType(hygienicType, rewrittenType);
}
- // TODO(b/181010111): Remove this once main-dex is a computed property on synthetics.
- void addIfDerivedFromMainDexClass(
- DexProgramClass externalSyntheticClass, MainDexInfo mainDexInfo) {
- if (mainDexInfo.isMainDex(externalSyntheticClass)) {
- return;
- }
- // The input context type (not the annotated context) determines if the derived class is to be
- // in main dex, as it is the input context type that is traced as part of main-dex tracing.
- if (mainDexInfo.isMainDexTypeThatShouldIncludeDependencies(inputContextType)) {
- mainDexInfo.addSyntheticClass(externalSyntheticClass);
- }
- }
-
@Override
public String toString() {
return "SynthesizingContext{" + getSynthesizingContextType() + "}";
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index b2cf60e..916daac 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -22,7 +22,6 @@
import com.android.tools.r8.graph.TreeFixerBase;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.MainDexInfo;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.SetUtils;
@@ -231,20 +230,30 @@
assert !appView.appInfo().hasLiveness();
Result result = appView.getSyntheticItems().computeFinalSynthetics(appView);
appView.setAppInfo(new AppInfo(result.commit, appView.appInfo().getMainDexInfo()));
- appView.pruneItems(result.prunedItems);
if (result.lens != null) {
+ appView.setAppInfo(
+ appView
+ .appInfo()
+ .rebuildWithMainDexInfo(
+ appView.appInfo().getMainDexInfo().rewrittenWithLens(result.lens)));
appView.setGraphLens(result.lens);
}
+ appView.pruneItems(result.prunedItems);
}
public static void finalizeWithClassHierarchy(AppView<AppInfoWithClassHierarchy> appView) {
assert !appView.appInfo().hasLiveness();
Result result = appView.getSyntheticItems().computeFinalSynthetics(appView);
appView.setAppInfo(appView.appInfo().rebuildWithClassHierarchy(result.commit));
- appView.pruneItems(result.prunedItems);
if (result.lens != null) {
appView.setGraphLens(result.lens);
+ appView.setAppInfo(
+ appView
+ .appInfo()
+ .rebuildWithMainDexInfo(
+ appView.appInfo().getMainDexInfo().rewrittenWithLens(result.lens)));
}
+ appView.pruneItems(result.prunedItems);
}
public static void finalizeWithLiveness(AppView<AppInfoWithLiveness> appView) {
@@ -452,10 +461,6 @@
representative.getKind(),
representative.getContext(),
externalSyntheticClass.type));
- for (SyntheticProgramClassDefinition member : syntheticGroup.getMembers()) {
- addMainDexAndSynthesizedFromForMember(
- member, externalSyntheticClass, appView.appInfo().getMainDexInfo());
- }
});
syntheticMethodGroups.forEach(
(syntheticType, syntheticGroup) -> {
@@ -470,10 +475,6 @@
.getMethod()
.getReference()
.withHolder(externalSyntheticClass.type, factory)));
- for (SyntheticMethodDefinition member : syntheticGroup.getMembers()) {
- addMainDexAndSynthesizedFromForMember(
- member, externalSyntheticClass, appView.appInfo().getMainDexInfo());
- }
});
for (DexType key : syntheticMethodGroups.keySet()) {
@@ -517,13 +518,6 @@
return builder.build();
}
- private static void addMainDexAndSynthesizedFromForMember(
- SyntheticDefinition<?, ?, ?> member,
- DexProgramClass externalSyntheticClass,
- MainDexInfo mainDexInfo) {
- member.getContext().addIfDerivedFromMainDexClass(externalSyntheticClass, mainDexInfo);
- }
-
private static boolean shouldAnnotateSynthetics(InternalOptions options) {
// Only intermediate builds have annotated synthetics to allow later sharing.
// This is currently also disabled on CF to CF desugaring to avoid missing class references to
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
index 8f62a1c..2dd90c1 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListOutputTest.java
@@ -120,7 +120,7 @@
testForD8()
.setMinApi(AndroidApiLevel.K)
.addProgramClasses(ImmutableList.of(TestClass.class, MyConsumer.class))
- .addMainDexListClasses(TestClass.class)
+ .addMainDexKeepClassAndMemberRules(TestClass.class)
.setMainDexListConsumer(consumer)
.compile();
assertTrue(consumer.called);
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java
index 5e88d7d..6c2ad2e 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexWithSynthesizedClassesTest.java
@@ -26,7 +26,7 @@
static final AndroidApiLevel nativeMultiDexLevel = AndroidApiLevel.L;
- static final String EXPECTED = StringUtils.lines("AB");
+ static final String EXPECTED = StringUtils.lines("A");
private final TestParameters parameters;
@@ -53,7 +53,7 @@
D8TestCompileResult compileResult =
testForD8()
.addInnerClasses(MainDexWithSynthesizedClassesTest.class)
- .addMainDexListClasses(TestClass.class, A.class)
+ .addMainDexKeepClassAndMemberRules(TestClass.class)
.setMinApiThreshold(parameters.getApiLevel())
.compile();
checkCompilationResult(compileResult);
@@ -119,7 +119,7 @@
static class A {
Getter foo() {
- return () -> "A" + new B().foo().get();
+ return () -> "A";
}
}