Prune dead root set items
Bug: 150736225
Change-Id: If40fc7dc173aa3959ee277b9dc27c9974793150d
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 78e4102..7c21891 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2752,12 +2752,14 @@
// Verify all references on the input app before synthesizing definitions.
assert verifyReferences(appInfo.app());
- // Rebuild a new app only containing referenced types.
- // Ensure references from various root set collections.
- // TODO(b/150736225): Can we instead prune the items that are not enqueued?
- rootSet.noSideEffects.keySet().forEach(this::recordReference);
+ // Prune the root set items that turned out to be dead.
+ // TODO(b/150736225): Pruning of dead root set items is still incomplete.
+ rootSet.pruneDeadItems(appView, this);
+
+ // Ensure references from all hard coded factory items.
appView.dexItemFactory().forEachPossiblyCompilerSynthesizedType(this::recordTypeReference);
+ // Rebuild a new app only containing referenced types.
Set<DexLibraryClass> libraryClasses = Sets.newIdentityHashSet();
Set<DexClasspathClass> classpathClasses = Sets.newIdentityHashSet();
for (DexClass clazz : liveNonProgramTypes) {
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 369bcd9..b48c50c 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
+import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -1318,8 +1319,8 @@
this.noObfuscation = noObfuscation;
this.reasonAsked = reasonAsked;
this.checkDiscarded = checkDiscarded;
- this.alwaysInline = Collections.unmodifiableSet(alwaysInline);
- this.forceInline = Collections.unmodifiableSet(forceInline);
+ this.alwaysInline = alwaysInline;
+ this.forceInline = forceInline;
this.neverInline = neverInline;
this.bypassClinitForInlining = bypassClinitForInlining;
this.whyAreYouNotInlining = whyAreYouNotInlining;
@@ -1329,7 +1330,7 @@
this.neverReprocess = neverReprocess;
this.alwaysClassInline = alwaysClassInline;
this.neverClassInline = neverClassInline;
- this.neverMerge = Collections.unmodifiableSet(neverMerge);
+ this.neverMerge = neverMerge;
this.neverPropagateValue = neverPropagateValue;
this.mayHaveSideEffects = mayHaveSideEffects;
this.noSideEffects = noSideEffects;
@@ -1460,6 +1461,34 @@
assumedValues.remove(reference);
}
+ public void pruneDeadItems(DexDefinitionSupplier definitions, Enqueuer enqueuer) {
+ pruneDeadReferences(neverMerge, definitions, enqueuer);
+ pruneDeadReferences(alwaysInline, definitions, enqueuer);
+ pruneDeadReferences(noSideEffects.keySet(), definitions, enqueuer);
+ }
+
+ private static void pruneDeadReferences(
+ Set<? extends DexReference> references,
+ DexDefinitionSupplier definitions,
+ Enqueuer enqueuer) {
+ references.removeIf(
+ reference -> {
+ if (reference.isDexField()) {
+ DexEncodedField definition = definitions.definitionFor(reference.asDexField());
+ return definition == null || !enqueuer.isFieldReferenced(definition);
+ } else if (reference.isDexMethod()) {
+ DexEncodedMethod definition = definitions.definitionFor(reference.asDexMethod());
+ return definition == null
+ || !(enqueuer.isMethodLive(definition) || enqueuer.isMethodTargeted(definition));
+ } else {
+ DexClass definition = definitions.definitionFor(reference.asDexType());
+ return definition == null
+ || (definition.isProgramClass()
+ && !enqueuer.isTypeLive(definition.asProgramClass()));
+ }
+ });
+ }
+
public void move(DexReference original, DexReference rewritten) {
copy(original, rewritten);
prune(original);