Reland "Collect synthetic inputs in R8"
This reverts commit c225205824ce58503ff38eec05c3b31ade65cfb5.
Change-Id: Ic7c1352a597793307519838ab67806e9f3100cee
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 546fad4..8a4c9cc 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -103,6 +103,7 @@
import com.android.tools.r8.shaking.VerticalClassMergerGraphLens;
import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
import com.android.tools.r8.synthesis.SyntheticFinalization;
+import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.CfgPrinter;
@@ -291,6 +292,7 @@
appView = AppView.createForR8(application, mainDexInfo);
appView.setAppServices(AppServices.builder(appView).build());
+ SyntheticItems.collectSyntheticInputs(appView);
}
// Check for potentially having pass-through of Cf-code for kotlin libraries.
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 7321cc0..1cd36de 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -558,6 +558,10 @@
return true;
}
+ public boolean hasClassHierarchy() {
+ return appInfo().hasClassHierarchy();
+ }
+
@SuppressWarnings("unchecked")
public AppView<AppInfoWithClassHierarchy> withClassHierarchy() {
return appInfo.hasClassHierarchy()
@@ -565,6 +569,12 @@
: null;
}
+ @SuppressWarnings("unchecked")
+ public AppView<AppInfo> withoutClassHierarchy() {
+ assert !hasClassHierarchy();
+ return (AppView<AppInfo>) this;
+ }
+
public boolean hasLiveness() {
return appInfo().hasLiveness();
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 86c8ef6..7c2162c 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2983,7 +2983,8 @@
ImmutableSet<ProguardKeepRuleBase> keepAllSet =
ImmutableSet.of(appView.options().getProguardConfiguration().getKeepAllRule());
for (DexProgramClass clazz : appView.appInfo().classes()) {
- if (appView.getSyntheticItems().isNonLegacySynthetic(clazz)) {
+ if (appView.getSyntheticItems().isSyntheticClass(clazz)
+ && !appView.getSyntheticItems().isSubjectToKeepRules(clazz)) {
// Don't treat compiler synthesized classes as kept roots.
continue;
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
index 7dbdec5..a201d6a 100644
--- a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
+++ b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.utils.BooleanBox;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Map;
@@ -29,6 +30,7 @@
null;
private ImmutableMap.Builder<DexType, SyntheticMethodReference> newNonLegacyMethods = null;
private ImmutableMap.Builder<DexType, LegacySyntheticReference> newLegacyClasses = null;
+ private ImmutableSet.Builder<DexType> newSyntheticInputs = null;
public Builder(CommittedSyntheticsCollection parent) {
this.parent = parent;
@@ -81,6 +83,11 @@
return this;
}
+ Builder addToSyntheticInputs() {
+ newSyntheticInputs = ImmutableSet.builder();
+ return this;
+ }
+
public CommittedSyntheticsCollection build() {
if (newNonLegacyClasses == null && newNonLegacyMethods == null && newLegacyClasses == null) {
return parent;
@@ -97,13 +104,22 @@
newLegacyClasses == null
? parent.legacyTypes
: newLegacyClasses.putAll(parent.legacyTypes).build();
+ ImmutableSet<DexType> allSyntheticInputs =
+ newSyntheticInputs == null
+ ? parent.syntheticInputs
+ : newSyntheticInputs
+ .addAll(allNonLegacyClasses.keySet())
+ .addAll(allNonLegacyMethods.keySet())
+ .addAll(allLegacyClasses.keySet())
+ .build();
return new CommittedSyntheticsCollection(
- allLegacyClasses, allNonLegacyMethods, allNonLegacyClasses);
+ allLegacyClasses, allNonLegacyMethods, allNonLegacyClasses, allSyntheticInputs);
}
}
private static final CommittedSyntheticsCollection EMPTY =
- new CommittedSyntheticsCollection(ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of());
+ new CommittedSyntheticsCollection(
+ ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of(), ImmutableSet.of());
/**
* Immutable set of synthetic types in the application (eg, committed).
@@ -118,13 +134,18 @@
/** Mapping from synthetic type to its synthetic class item description. */
private final ImmutableMap<DexType, SyntheticProgramClassReference> nonLegacyClasses;
+ /** Set of synthetic types that were present in the input. */
+ private final ImmutableSet<DexType> syntheticInputs;
+
public CommittedSyntheticsCollection(
ImmutableMap<DexType, LegacySyntheticReference> legacyTypes,
ImmutableMap<DexType, SyntheticMethodReference> nonLegacyMethods,
- ImmutableMap<DexType, SyntheticProgramClassReference> nonLegacyClasses) {
+ ImmutableMap<DexType, SyntheticProgramClassReference> nonLegacyClasses,
+ ImmutableSet<DexType> syntheticInputs) {
this.legacyTypes = legacyTypes;
this.nonLegacyMethods = nonLegacyMethods;
this.nonLegacyClasses = nonLegacyClasses;
+ this.syntheticInputs = syntheticInputs;
assert legacyTypes.size() + nonLegacyMethods.size() + nonLegacyClasses.size()
== Sets.union(
Sets.union(nonLegacyMethods.keySet(), nonLegacyClasses.keySet()),
@@ -140,8 +161,15 @@
return new Builder(this);
}
+ Builder builderForSyntheticInputs() {
+ return new Builder(this).addToSyntheticInputs();
+ }
+
boolean isEmpty() {
- return legacyTypes.isEmpty() && nonLegacyMethods.isEmpty() && nonLegacyClasses.isEmpty();
+ boolean empty =
+ legacyTypes.isEmpty() && nonLegacyMethods.isEmpty() && nonLegacyClasses.isEmpty();
+ assert !empty || syntheticInputs.isEmpty();
+ return empty;
}
boolean containsType(DexType type) {
@@ -156,6 +184,10 @@
return nonLegacyMethods.containsKey(type) || nonLegacyClasses.containsKey(type);
}
+ public boolean containsSyntheticInput(DexType type) {
+ return syntheticInputs.contains(type);
+ }
+
public ImmutableMap<DexType, LegacySyntheticReference> getLegacyTypes() {
return legacyTypes;
}
@@ -176,6 +208,10 @@
return nonLegacyClasses.get(type);
}
+ public void forEachSyntheticInput(Consumer<DexType> fn) {
+ syntheticInputs.forEach(fn);
+ }
+
public void forEachNonLegacyItem(Consumer<SyntheticReference<?, ?, ?>> fn) {
nonLegacyMethods.forEach((t, r) -> fn.accept(r));
nonLegacyClasses.forEach((t, r) -> fn.accept(r));
@@ -217,7 +253,16 @@
return new CommittedSyntheticsCollection(
rewriteItems(legacyTypes, lens),
rewriteItems(nonLegacyMethods, lens),
- rewriteItems(nonLegacyClasses, lens));
+ rewriteItems(nonLegacyClasses, lens),
+ rewriteItems(syntheticInputs, lens));
+ }
+
+ private static ImmutableSet<DexType> rewriteItems(Set<DexType> items, NonIdentityGraphLens lens) {
+ ImmutableSet.Builder<DexType> rewrittenItems = ImmutableSet.builder();
+ for (DexType item : items) {
+ rewrittenItems.add(lens.lookupType(item));
+ }
+ return rewrittenItems.build();
}
private static <R extends Rewritable<R>> ImmutableMap<DexType, R> rewriteItems(
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 8f883ea..5fa5498 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -35,6 +35,7 @@
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.hash.HashCode;
import java.util.ArrayList;
@@ -237,6 +238,12 @@
}
});
+ SyntheticFinalizationGraphLens syntheticFinalizationGraphLens = lensBuilder.build(appView);
+
+ ImmutableSet.Builder<DexType> finalInputSyntheticsBuilder = ImmutableSet.builder();
+ committed.forEachSyntheticInput(
+ type -> finalInputSyntheticsBuilder.add(syntheticFinalizationGraphLens.lookupType(type)));
+
// TODO(b/181858113): Remove once deprecated main-dex-list is removed.
MainDexInfo.Builder mainDexInfoBuilder = appView.appInfo().getMainDexInfo().builderFromCopy();
derivedMainDexTypes.forEach(mainDexInfoBuilder::addList);
@@ -246,9 +253,12 @@
SyntheticItems.INVALID_ID_AFTER_SYNTHETIC_FINALIZATION,
application,
new CommittedSyntheticsCollection(
- committed.getLegacyTypes(), finalMethods, finalClasses),
+ committed.getLegacyTypes(),
+ finalMethods,
+ finalClasses,
+ finalInputSyntheticsBuilder.build()),
ImmutableList.of()),
- lensBuilder.build(appView),
+ syntheticFinalizationGraphLens,
PrunedItems.builder().setPrunedApp(application).addRemovedClasses(prunedSynthetics).build(),
mainDexInfoBuilder.build());
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index d6c93aa..b90083a 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -109,7 +109,7 @@
this.committed = committed;
}
- public static void collectSyntheticInputs(AppView<AppInfo> appView) {
+ public static void collectSyntheticInputs(AppView<?> appView) {
// Collecting synthetic items must be the very first task after application build.
SyntheticItems synthetics = appView.getSyntheticItems();
assert synthetics.nextSyntheticId == 0;
@@ -119,7 +119,8 @@
// If the compilation is in intermediate mode the synthetics should just be passed through.
return;
}
- CommittedSyntheticsCollection.Builder builder = synthetics.committed.builder();
+ CommittedSyntheticsCollection.Builder builder =
+ synthetics.committed.builderForSyntheticInputs();
// TODO(b/158159959): Consider identifying synthetics in the input reader to speed this up.
for (DexProgramClass clazz : appView.appInfo().classes()) {
SyntheticMarker marker =
@@ -127,10 +128,9 @@
if (marker.isSyntheticMethods()) {
clazz.forEachProgramMethod(
// TODO(b/158159959): Support having multiple methods per class.
- method -> {
- builder.addNonLegacyMethod(
- new SyntheticMethodDefinition(marker.getKind(), marker.getContext(), method));
- });
+ method ->
+ builder.addNonLegacyMethod(
+ new SyntheticMethodDefinition(marker.getKind(), marker.getContext(), method)));
} else if (marker.isSyntheticClass()) {
builder.addNonLegacyClass(
new SyntheticProgramClassDefinition(marker.getKind(), marker.getContext(), clazz));
@@ -143,7 +143,15 @@
CommittedItems commit =
new CommittedItems(
synthetics.nextSyntheticId, appView.appInfo().app(), committed, ImmutableList.of());
- appView.setAppInfo(new AppInfo(commit, appView.appInfo().getMainDexInfo()));
+ if (appView.appInfo().hasClassHierarchy()) {
+ appView
+ .withClassHierarchy()
+ .setAppInfo(appView.appInfo().withClassHierarchy().rebuildWithClassHierarchy(commit));
+ } else {
+ appView
+ .withoutClassHierarchy()
+ .setAppInfo(new AppInfo(commit, appView.appInfo().getMainDexInfo()));
+ }
}
// Predicates and accessors.
@@ -239,6 +247,11 @@
return null;
}
+ public boolean isSubjectToKeepRules(DexProgramClass clazz) {
+ assert isSyntheticClass(clazz);
+ return committed.containsSyntheticInput(clazz.getType());
+ }
+
public boolean isSyntheticClass(DexType type) {
return isLegacySyntheticClass(type) || isNonLegacySynthetic(type);
}