Defer state pruning to last wave
Change-Id: Ibe6c460eaa3f8be19aaa353e1898553f3d958619
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 3c3533a..79d8789 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -1354,7 +1354,7 @@
DexClass newHolder = definitions.definitionFor(newMethodReference.getHolderType());
assert newHolder != null;
DexEncodedMethod newMethod = newHolder.lookupMethod(newMethodReference);
- assert newMethod != null;
+ assert newMethod != null : newMethodReference.toSourceString();
return newMethod;
}
diff --git a/src/main/java/com/android/tools/r8/graph/PrunedItems.java b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
index 19ebb99..3e96a43 100644
--- a/src/main/java/com/android/tools/r8/graph/PrunedItems.java
+++ b/src/main/java/com/android/tools/r8/graph/PrunedItems.java
@@ -4,11 +4,14 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.utils.DequeUtils;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.Sets;
import java.util.Collection;
+import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@@ -255,6 +258,9 @@
}
public PrunedItems build() {
+ if (hasFullyInlinedMethods()) {
+ compressInliningPaths();
+ }
return new PrunedItems(
prunedApp,
additionalPinnedItems,
@@ -264,6 +270,38 @@
removedFields,
removedMethods);
}
+
+ private void compressInliningPaths() {
+ Map<DexMethod, ProgramMethod> fullyInlinedMethodsUpdate = new IdentityHashMap<>();
+ for (Entry<DexMethod, ProgramMethod> entry : fullyInlinedMethods.entrySet()) {
+ DexMethod innermostCallee = entry.getKey();
+ if (fullyInlinedMethodsUpdate.containsKey(innermostCallee)) {
+ // Already processed as a result of previously processing a callee of the current callee.
+ continue;
+ }
+ ProgramMethod innermostCaller = entry.getValue();
+ ProgramMethod outermostCaller = fullyInlinedMethods.get(innermostCaller.getReference());
+ if (outermostCaller == null) {
+ continue;
+ }
+ Deque<DexMethod> fullyInlinedMethodChain =
+ DequeUtils.newArrayDeque(innermostCallee, innermostCaller.getReference());
+ while (true) {
+ DexMethod currentCallee = outermostCaller.getReference();
+ ProgramMethod currentCaller = fullyInlinedMethods.get(currentCallee);
+ if (currentCaller == null) {
+ break;
+ }
+ fullyInlinedMethodChain.addLast(currentCallee);
+ outermostCaller = currentCaller;
+ }
+ assert !removedMethods.contains(outermostCaller.getReference());
+ for (DexMethod callee : fullyInlinedMethodChain) {
+ fullyInlinedMethodsUpdate.put(callee, outermostCaller);
+ }
+ }
+ fullyInlinedMethods.putAll(fullyInlinedMethodsUpdate);
+ }
}
public static class ConcurrentBuilder extends Builder {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
index ae766bd..436969d 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
@@ -263,17 +263,12 @@
onWaveDoneActions.forEach(com.android.tools.r8.utils.Action::execute);
onWaveDoneActions = null;
}
- if (prunedItemsBuilder.hasFullyInlinedMethods() || prunedItemsBuilder.hasRemovedMethods()) {
- appView.pruneItems(
- prunedItemsBuilder.setPrunedApp(appView.app()).build(), executorService, timing);
- prunedItemsBuilder.clearFullyInlinedMethods();
- prunedItemsBuilder.clearRemovedMethods();
- }
}
private void lastWaveDone(
PostMethodProcessor.Builder postMethodProcessorBuilder, ExecutorService executorService)
throws ExecutionException {
+ pruneItems(executorService);
if (assertionErrorTwoArgsConstructorRewriter != null) {
assertionErrorTwoArgsConstructorRewriter.onLastWaveDone(postMethodProcessorBuilder);
assertionErrorTwoArgsConstructorRewriter = null;
@@ -289,4 +284,13 @@
// Ensure determinism of method-to-reprocess set.
appView.testing().checkDeterminism(postMethodProcessorBuilder::dump);
}
+
+ public void pruneItems(ExecutorService executorService) throws ExecutionException {
+ if (prunedItemsBuilder.hasFullyInlinedMethods() || prunedItemsBuilder.hasRemovedMethods()) {
+ appView.pruneItems(
+ prunedItemsBuilder.setPrunedApp(appView.app()).build(), executorService, timing);
+ prunedItemsBuilder.clearFullyInlinedMethods();
+ prunedItemsBuilder.clearRemovedMethods();
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
index 0b947a3..4a19396 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorOptimizationInfoPopulator.java
@@ -88,6 +88,7 @@
converter.onMethodPruned(prunedMethod);
postMethodProcessorBuilder.remove(prunedMethod, appView.graphLens());
}
+ converter.pruneItems(executorService);
converter.waveDone(ProgramMethodSet.empty(), executorService);
}
diff --git a/src/main/java/com/android/tools/r8/utils/DequeUtils.java b/src/main/java/com/android/tools/r8/utils/DequeUtils.java
index 6745d6b..986a6a2 100644
--- a/src/main/java/com/android/tools/r8/utils/DequeUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/DequeUtils.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.utils;
import java.util.ArrayDeque;
+import java.util.Collections;
import java.util.Deque;
public class DequeUtils {
@@ -14,4 +15,10 @@
deque.add(element);
return deque;
}
+
+ public static <T> Deque<T> newArrayDeque(T... elements) {
+ Deque<T> deque = new ArrayDeque<>();
+ Collections.addAll(deque, elements);
+ return deque;
+ }
}