Retain library classes referenced from R8 partial classpath
Tree shaking in R8 prunes library classes that are not referenced from the program. In R8 partial we need to extend R8 to also retain the library classes that are referenced from the classpath, since part of the classpath also belongs to the app in R8 partial.
Change-Id: Ie09244b741c13958db794f28857b5ba6eef245e9
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialUseCollector.java b/src/main/java/com/android/tools/r8/partial/R8PartialUseCollector.java
index 670eafe..bb8af7d 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialUseCollector.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialUseCollector.java
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.partial;
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.diagnostic.DefinitionContext;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -13,6 +11,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.partial.R8PartialSubCompilationConfiguration.R8PartialR8SubCompilationConfiguration;
@@ -48,7 +47,7 @@
public static Predicate<DexType> getTargetPredicate(
AppView<? extends AppInfoWithClassHierarchy> appView) {
- return type -> asProgramClassOrNull(appView.definitionFor(type)) != null;
+ return type -> appView.definitionFor(type) != null;
}
public void run(ExecutorService executorService) throws ExecutionException {
@@ -96,6 +95,12 @@
notifyPresentItem(method);
}
+ @Override
+ protected void notifyPresentMethod(
+ DexClassAndMethod method, DefinitionContext referencedFrom, DexMethod reference) {
+ notifyPresentItem(method);
+ }
+
private void notifyPresentItem(Definition definition) {
if (seen.add(definition.getReference())) {
keep(definition);
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 7fb2bf6..93475c9 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4462,6 +4462,7 @@
appView
.dexItemFactory()
.forEachPossiblyCompilerSynthesizedType(this::recordCompilerSynthesizedTypeReference);
+ appView.rootSet().rootLibraryTypes.forEach(this::recordCompilerSynthesizedTypeReference);
timing.end();
// Rebuild a new app only containing referenced types.
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index f7ae53e..062b3b7 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -121,6 +121,7 @@
private final RootSetBuilderEventConsumer eventConsumer;
private final SubtypingInfo subtypingInfo;
private final DirectMappedDexApplication application;
+ private final Set<DexType> rootLibraryTypes = Sets.newIdentityHashSet();
private final Iterable<? extends ProguardConfigurationRule> rules;
private final DependentMinimumKeepInfoCollection dependentMinimumKeepInfo =
DependentMinimumKeepInfoCollection.createConcurrent();
@@ -245,14 +246,17 @@
@Override
protected synchronized void keep(Definition definition) {
- assert definition.isProgramDefinition();
- evaluateKeepRule(
- definition.asProgramDefinition(),
- null,
- null,
- modifiers,
- Action.empty(),
- keepRule);
+ if (definition.isProgramDefinition()) {
+ evaluateKeepRule(
+ definition.asProgramDefinition(),
+ null,
+ null,
+ modifiers,
+ Action.empty(),
+ keepRule);
+ } else if (definition.getContextClass().isLibraryClass()) {
+ rootLibraryTypes.add(definition.getContextType());
+ }
}
};
useCollector.run(executorService);
@@ -503,7 +507,8 @@
ifRules,
Lists.newArrayList(delayedRootSetActionItems),
pendingMethodMoveInverse,
- resourceRootIds);
+ resourceRootIds,
+ rootLibraryTypes);
}
private void propagateAssumeRules(DexClass clazz) {
@@ -2018,6 +2023,7 @@
public final Set<DexMember<?, ?>> identifierNameStrings;
public final Set<ProguardIfRule> ifRules;
public final IntSet resourceIds;
+ public final Set<DexType> rootLibraryTypes;
private RootSet(
DependentMinimumKeepInfoCollection dependentMinimumKeepInfo,
@@ -2032,7 +2038,8 @@
Set<ProguardIfRule> ifRules,
List<DelayedRootSetActionItem> delayedRootSetActionItems,
ProgramMethodMap<ProgramMethod> pendingMethodMoveInverse,
- IntSet resourceIds) {
+ IntSet resourceIds,
+ Set<DexType> rootLibraryTypes) {
super(
dependentMinimumKeepInfo,
dependentKeepClassCompatRule,
@@ -2047,6 +2054,7 @@
this.identifierNameStrings = Collections.unmodifiableSet(identifierNameStrings);
this.ifRules = Collections.unmodifiableSet(ifRules);
this.resourceIds = resourceIds;
+ this.rootLibraryTypes = rootLibraryTypes;
}
public void checkAllRulesAreUsed(InternalOptions options) {
@@ -2161,7 +2169,8 @@
ifRules,
delayedRootSetActionItems,
pendingMethodMoveInverse,
- resourceIds);
+ resourceIds,
+ rootLibraryTypes);
}
timing.end();
return rewrittenRootSet;
@@ -2459,7 +2468,8 @@
ifRules,
delayedRootSetActionItems,
ProgramMethodMap.empty(),
- IntSets.EMPTY_SET);
+ IntSets.EMPTY_SET,
+ Collections.emptySet());
}
public static MainDexRootSetBuilder builder(