Refactor pruned items removal from AppInfoWithLiveness
Change-Id: I6c16255b64f3267805d468a97eeb0e17ae70317c
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index cfb3540..1dc0468 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -37,6 +37,7 @@
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.InitClassLens;
+import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.analysis.ClassInitializerAssertionEnablingAnalysis;
import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis;
@@ -419,8 +420,12 @@
// Recompute the subtyping information.
Set<DexType> removedClasses = pruner.getRemovedClasses();
- appView.removePrunedClasses(
- prunedApp, removedClasses, pruner.getMethodsToKeepForConfigurationDebugging());
+ appView.pruneItems(
+ PrunedItems.builder()
+ .setPrunedApp(prunedApp)
+ .addRemovedClasses(removedClasses)
+ .addAdditionalPinnedItems(pruner.getMethodsToKeepForConfigurationDebugging())
+ .build());
new AbstractMethodRemover(
appViewWithLiveness, appViewWithLiveness.appInfo().computeSubtypingInfo())
.run();
@@ -587,7 +592,12 @@
merger.run(appBuilder, mainDexTracingResult, runtimeTypeCheckInfo);
if (lens != null) {
DirectMappedDexApplication app = appBuilder.build();
- appView.removePrunedClasses(app, appView.horizontallyMergedClasses().getSources());
+ appView.pruneItems(
+ PrunedItems.builder()
+ .setPrunedApp(app)
+ .addRemovedClasses(appView.horizontallyMergedClasses().getSources())
+ .addNoLongerSyntheticItems(appView.horizontallyMergedClasses().getTargets())
+ .build());
appView.rewriteWithLens(lens);
// Only required for class merging, clear instance to save memory.
@@ -748,10 +758,12 @@
options.reporter, options.usageInformationConsumer);
}
- appView.removePrunedClasses(
- application,
- CollectionUtils.mergeSets(prunedTypes, removedClasses),
- pruner.getMethodsToKeepForConfigurationDebugging());
+ appView.pruneItems(
+ PrunedItems.builder()
+ .setPrunedApp(application)
+ .addRemovedClasses(CollectionUtils.mergeSets(prunedTypes, removedClasses))
+ .addAdditionalPinnedItems(pruner.getMethodsToKeepForConfigurationDebugging())
+ .build());
new BridgeHoisting(appViewWithLiveness).run();
diff --git a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
index b6588df..ec95ade 100644
--- a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
+++ b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.Sets;
@@ -135,11 +136,11 @@
return rewrittenClassToFeatureSplitMap;
}
- public ClassToFeatureSplitMap withoutPrunedClasses(Set<DexType> prunedClasses) {
+ public ClassToFeatureSplitMap withoutPrunedItems(PrunedItems prunedItems) {
ClassToFeatureSplitMap classToFeatureSplitMapAfterPruning = new ClassToFeatureSplitMap();
classToFeatureSplitMap.forEach(
(type, featureSplit) -> {
- if (!prunedClasses.contains(type)) {
+ if (!prunedItems.getRemovedClasses().contains(type)) {
classToFeatureSplitMapAfterPruning.classToFeatureSplitMap.put(type, featureSplit);
}
});
diff --git a/src/main/java/com/android/tools/r8/graph/AppServices.java b/src/main/java/com/android/tools/r8/graph/AppServices.java
index 7fe273a..c0c3976 100644
--- a/src/main/java/com/android/tools/r8/graph/AppServices.java
+++ b/src/main/java/com/android/tools/r8/graph/AppServices.java
@@ -26,7 +26,6 @@
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -139,11 +138,11 @@
return new AppServices(appView, rewrittenFeatureMappings.build());
}
- public AppServices prunedCopy(Collection<DexType> removedClasses) {
+ public AppServices prunedCopy(PrunedItems prunedItems) {
ImmutableMap.Builder<DexType, Map<FeatureSplit, List<DexType>>> rewrittenServicesBuilder =
ImmutableMap.builder();
for (Entry<DexType, Map<FeatureSplit, List<DexType>>> entry : services.entrySet()) {
- if (removedClasses.contains(entry.getKey())) {
+ if (prunedItems.getRemovedClasses().contains(entry.getKey())) {
continue;
}
ImmutableMap.Builder<FeatureSplit, List<DexType>> prunedFeatureSplitImpls =
@@ -152,7 +151,7 @@
ImmutableList.Builder<DexType> rewrittenServiceImplementationTypesBuilder =
ImmutableList.builder();
for (DexType serviceImplementationType : featureSplitEntry.getValue()) {
- if (!removedClasses.contains(serviceImplementationType)) {
+ if (!prunedItems.getRemovedClasses().contains(serviceImplementationType)) {
rewrittenServiceImplementationTypesBuilder.add(serviceImplementationType);
}
}
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 ce2d937..d4728a4 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -38,8 +38,6 @@
import com.android.tools.r8.utils.ThrowingConsumer;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
-import java.util.Collection;
-import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
@@ -569,35 +567,17 @@
return !cfByteCodePassThrough.isEmpty();
}
- public void removePrunedClasses(
- DirectMappedDexApplication prunedApp, Set<DexType> removedClasses) {
- removePrunedClasses(prunedApp, removedClasses, Collections.emptySet());
+ public void pruneItems(PrunedItems prunedItems) {
+ pruneItems(withLiveness(), prunedItems);
}
- public void removePrunedClasses(
- DirectMappedDexApplication prunedApp,
- Set<DexType> removedClasses,
- Collection<DexMethod> methodsToKeepForConfigurationDebugging) {
- assert enableWholeProgramOptimizations();
- assert appInfo().hasLiveness();
- removePrunedClasses(
- prunedApp, removedClasses, methodsToKeepForConfigurationDebugging, withLiveness());
- }
-
- private static void removePrunedClasses(
- DirectMappedDexApplication prunedApp,
- Set<DexType> removedClasses,
- Collection<DexMethod> methodsToKeepForConfigurationDebugging,
- AppView<AppInfoWithLiveness> appView) {
- if (removedClasses.isEmpty() && !appView.options().configurationDebugging) {
- assert appView.appInfo.app() == prunedApp;
+ private static void pruneItems(AppView<AppInfoWithLiveness> appView, PrunedItems prunedItems) {
+ if (!prunedItems.hasRemovedClasses() && !appView.options().configurationDebugging) {
+ assert appView.appInfo().app() == prunedItems.getPrunedApp();
return;
}
- appView.setAppInfo(
- appView
- .appInfo()
- .prunedCopyFrom(prunedApp, removedClasses, methodsToKeepForConfigurationDebugging));
- appView.setAppServices(appView.appServices().prunedCopy(removedClasses));
+ appView.setAppInfo(appView.appInfo().prunedCopyFrom(prunedItems));
+ appView.setAppServices(appView.appServices().prunedCopy(prunedItems));
}
public void rewriteWithLens(NonIdentityGraphLens lens) {
diff --git a/src/main/java/com/android/tools/r8/graph/PrunedItems.java b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
new file mode 100644
index 0000000..2df596c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
@@ -0,0 +1,92 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.graph;
+
+import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Set;
+
+public class PrunedItems {
+
+ private final DexApplication prunedApp;
+ private final Set<DexReference> additionalPinnedItems;
+ private final Set<DexType> noLongerSyntheticItems;
+ private final Set<DexType> removedClasses;
+
+ private PrunedItems(
+ DexApplication prunedApp,
+ Set<DexReference> additionalPinnedItems,
+ Set<DexType> noLongerSyntheticItems,
+ Set<DexType> removedClasses) {
+ this.prunedApp = prunedApp;
+ this.additionalPinnedItems = additionalPinnedItems;
+ this.noLongerSyntheticItems = noLongerSyntheticItems;
+ this.removedClasses = removedClasses;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static PrunedItems empty(DexApplication application) {
+ return new Builder().setPrunedApp(application).build();
+ }
+
+ public DexApplication getPrunedApp() {
+ return prunedApp;
+ }
+
+ public Set<? extends DexReference> getAdditionalPinnedItems() {
+ return additionalPinnedItems;
+ }
+
+ public Set<DexType> getNoLongerSyntheticItems() {
+ return noLongerSyntheticItems;
+ }
+
+ public boolean hasRemovedClasses() {
+ return !removedClasses.isEmpty();
+ }
+
+ public Set<DexType> getRemovedClasses() {
+ return removedClasses;
+ }
+
+ public static class Builder {
+
+ private DexApplication prunedApp;
+
+ private final Set<DexReference> additionalPinnedItems = Sets.newIdentityHashSet();
+ private final Set<DexType> noLongerSyntheticItems = Sets.newIdentityHashSet();
+ private final Set<DexType> removedClasses = Sets.newIdentityHashSet();
+
+ public Builder setPrunedApp(DexApplication prunedApp) {
+ this.prunedApp = prunedApp;
+ return this;
+ }
+
+ public Builder addAdditionalPinnedItems(
+ Collection<? extends DexReference> additionalPinnedItems) {
+ this.additionalPinnedItems.addAll(additionalPinnedItems);
+ return this;
+ }
+
+ public Builder addNoLongerSyntheticItems(Set<DexType> noLongerSyntheticItems) {
+ this.noLongerSyntheticItems.addAll(noLongerSyntheticItems);
+ return this;
+ }
+
+ public Builder addRemovedClasses(Set<DexType> removedClasses) {
+ this.noLongerSyntheticItems.addAll(removedClasses);
+ this.removedClasses.addAll(removedClasses);
+ return this;
+ }
+
+ public PrunedItems build() {
+ return new PrunedItems(
+ prunedApp, additionalPinnedItems, noLongerSyntheticItems, removedClasses);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
index ff108a4..b9195c3 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
@@ -45,6 +45,10 @@
return mergedClasses.getKeys(type);
}
+ public Set<DexType> getTargets() {
+ return mergedClasses.values();
+ }
+
@Override
public boolean hasBeenMergedIntoDifferentType(DexType type) {
return mergedClasses.containsKey(type);
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index c5adef8..c1275c5 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -40,6 +40,7 @@
import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
@@ -318,20 +319,16 @@
previous.initClassReferences);
}
- private AppInfoWithLiveness(
- AppInfoWithLiveness previous,
- DirectMappedDexApplication application,
- Set<DexType> removedClasses,
- Collection<? extends DexReference> additionalPinnedItems) {
+ private AppInfoWithLiveness(AppInfoWithLiveness previous, PrunedItems prunedItems) {
this(
- previous.getSyntheticItems().commitPrunedClasses(application, removedClasses),
- previous.getClassToFeatureSplitMap().withoutPrunedClasses(removedClasses),
- previous.getMainDexClasses().withoutPrunedClasses(removedClasses),
+ previous.getSyntheticItems().commitPrunedItems(prunedItems),
+ previous.getClassToFeatureSplitMap().withoutPrunedItems(prunedItems),
+ previous.getMainDexClasses().withoutPrunedItems(prunedItems),
previous.deadProtoTypes,
previous.missingTypes,
- removedClasses == null
- ? previous.liveTypes
- : Sets.difference(previous.liveTypes, removedClasses),
+ prunedItems.hasRemovedClasses()
+ ? Sets.difference(previous.liveTypes, prunedItems.getRemovedClasses())
+ : previous.liveTypes,
previous.targetedMethods,
previous.failedResolutionTargets,
previous.bootstrapMethods,
@@ -342,7 +339,7 @@
previous.methodAccessInfoCollection,
previous.objectAllocationInfoCollection,
previous.callSites,
- extendPinnedItems(previous, additionalPinnedItems),
+ extendPinnedItems(previous, prunedItems.getAdditionalPinnedItems()),
previous.mayHaveSideEffects,
previous.noSideEffects,
previous.assumedValues,
@@ -362,14 +359,14 @@
previous.noStaticClassMerging,
previous.neverPropagateValue,
previous.identifierNameStrings,
- removedClasses == null
- ? previous.prunedTypes
- : CollectionUtils.mergeSets(previous.prunedTypes, removedClasses),
+ prunedItems.hasRemovedClasses()
+ ? CollectionUtils.mergeSets(previous.prunedTypes, prunedItems.getRemovedClasses())
+ : previous.prunedTypes,
previous.switchMaps,
previous.enumValueInfoMaps,
previous.lockCandidates,
previous.initClassReferences);
- assert keepInfo.verifyNoneArePinned(removedClasses, previous);
+ assert keepInfo.verifyNoneArePinned(prunedItems.getRemovedClasses(), previous);
}
private static KeepInfoCollection extendPinnedItems(
@@ -940,17 +937,15 @@
* Returns a copy of this AppInfoWithLiveness where the set of classes is pruned using the given
* DexApplication object.
*/
- public AppInfoWithLiveness prunedCopyFrom(
- DirectMappedDexApplication application,
- Set<DexType> removedClasses,
- Collection<? extends DexReference> additionalPinnedItems) {
+ public AppInfoWithLiveness prunedCopyFrom(PrunedItems prunedItems) {
assert checkIfObsolete();
- if (!removedClasses.isEmpty()) {
+ if (!prunedItems.hasRemovedClasses()) {
// Rebuild the hierarchy.
objectAllocationInfoCollection.mutate(mutator -> {}, this);
- keepInfo.mutate(keepInfo -> keepInfo.removeKeepInfoForPrunedItems(removedClasses));
+ keepInfo.mutate(
+ keepInfo -> keepInfo.removeKeepInfoForPrunedItems(prunedItems.getRemovedClasses()));
}
- return new AppInfoWithLiveness(this, application, removedClasses, additionalPinnedItems);
+ return new AppInfoWithLiveness(this, prunedItems);
}
public AppInfoWithLiveness rebuildWithLiveness(
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexClasses.java b/src/main/java/com/android/tools/r8/shaking/MainDexClasses.java
index a5fbd32..4e6b632 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexClasses.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexClasses.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.graph.PrunedItems;
import com.google.common.collect.Sets;
import java.util.Set;
import java.util.function.Consumer;
@@ -87,10 +88,10 @@
return mainDexClasses.size();
}
- public MainDexClasses withoutPrunedClasses(Set<DexType> prunedClasses) {
+ public MainDexClasses withoutPrunedItems(PrunedItems prunedItems) {
MainDexClasses mainDexClassesAfterPruning = createEmptyMainDexClasses();
for (DexType mainDexClass : mainDexClasses) {
- if (!prunedClasses.contains(mainDexClass)) {
+ if (!prunedItems.getRemovedClasses().contains(mainDexClass)) {
mainDexClassesAfterPruning.mainDexClasses.add(mainDexClass);
}
}
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 dcdaafc..764fc9c 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.ir.conversion.MethodProcessingId;
import com.android.tools.r8.synthesis.SyntheticFinalization.Result;
import com.google.common.collect.ImmutableList;
@@ -301,14 +302,13 @@
// Commit of the synthetic items to a new fully populated application.
public CommittedItems commit(DexApplication application) {
- return commitPrunedClasses(application, Collections.emptySet());
+ return commitPrunedItems(PrunedItems.empty(application));
}
- public CommittedItems commitPrunedClasses(
- DexApplication application, Set<DexType> removedClasses) {
+ public CommittedItems commitPrunedItems(PrunedItems prunedItems) {
return commit(
- application,
- removedClasses,
+ prunedItems.getPrunedApp(),
+ prunedItems.getNoLongerSyntheticItems(),
legacyPendingClasses,
legacySyntheticTypes,
pendingDefinitions,
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java
index 6d50046..599fddd 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneHashMap.java
@@ -120,6 +120,7 @@
inverse.computeIfAbsent(value, ignore -> new LinkedHashSet<>()).add(key);
}
+ @Override
public Set<V> values() {
return inverse.keySet();
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneMap.java
index 3ec2c15..1404c6a 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalManyToOneMap.java
@@ -25,4 +25,6 @@
Map<K, V> getForwardMap();
Set<K> keySet();
+
+ Set<V> values();
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java
index 90217df..8e2edb5 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/BidirectionalOneToOneHashMap.java
@@ -6,7 +6,6 @@
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
-import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -144,7 +143,7 @@
}
@Override
- public Collection<V> values() {
+ public Set<V> values() {
return backing.values();
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/collections/EmptyBidirectionalOneToOneMap.java b/src/main/java/com/android/tools/r8/utils/collections/EmptyBidirectionalOneToOneMap.java
index 69a28e6..f2c10c3 100644
--- a/src/main/java/com/android/tools/r8/utils/collections/EmptyBidirectionalOneToOneMap.java
+++ b/src/main/java/com/android/tools/r8/utils/collections/EmptyBidirectionalOneToOneMap.java
@@ -87,6 +87,11 @@
}
@Override
+ public Set<V> values() {
+ return Collections.emptySet();
+ }
+
+ @Override
public BidirectionalOneToOneMap<V, K> getInverseOneToOneMap() {
return new EmptyBidirectionalOneToOneMap<>();
}