Handle collisions in rewriting of AppInfoWithLiveness
Change-Id: I7ecff6c821e6d0f85a51b9f997bd0372b077533c
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index 5a28054..a07a380 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.shaking.KeepInfoCollection;
import com.android.tools.r8.utils.Action;
import com.android.tools.r8.utils.IterableUtils;
+import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
@@ -559,10 +560,34 @@
return result;
}
- public <R extends DexReference, T> ImmutableMap<R, T> rewriteReferenceKeys(Map<R, T> map) {
- ImmutableMap.Builder<R, T> builder = ImmutableMap.builder();
- map.forEach((reference, value) -> builder.put(rewriteReference(reference), value));
- return builder.build();
+ public <R extends DexReference, T> Map<R, T> rewriteReferenceKeys(
+ Map<R, T> map, Function<List<T>, T> merge) {
+ Map<R, T> result = new IdentityHashMap<>();
+ Map<R, List<T>> needsMerge = new IdentityHashMap<>();
+ map.forEach(
+ (reference, value) -> {
+ R rewrittenReference = rewriteReference(reference);
+ List<T> unmergedValues = needsMerge.get(rewrittenReference);
+ if (unmergedValues != null) {
+ unmergedValues.add(value);
+ } else {
+ T existingValue = result.put(rewrittenReference, value);
+ if (existingValue != null) {
+ // Remove this for now and let the merge function decide when all colliding values are
+ // known.
+ needsMerge.put(rewrittenReference, ListUtils.newArrayList(existingValue, value));
+ result.remove(rewrittenReference);
+ }
+ }
+ });
+ needsMerge.forEach(
+ (rewrittenReference, unmergedValues) -> {
+ T mergedValue = merge.apply(unmergedValues);
+ if (mergedValue != null) {
+ result.put(rewrittenReference, mergedValue);
+ }
+ });
+ return result;
}
public Object2BooleanMap<DexReference> rewriteReferenceKeys(Object2BooleanMap<DexReference> map) {
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 c4ebfe7..239c0da 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1072,9 +1072,11 @@
objectAllocationInfoCollection.rewrittenWithLens(definitionSupplier, lens),
lens.rewriteCallSites(callSites, definitionSupplier),
keepInfo.rewrite(lens, application.options),
- lens.rewriteReferenceKeys(mayHaveSideEffects),
- lens.rewriteReferenceKeys(noSideEffects),
- lens.rewriteReferenceKeys(assumedValues),
+ // Take any rule in case of collisions.
+ lens.rewriteReferenceKeys(mayHaveSideEffects, ListUtils::first),
+ // Drop assume rules in case of collisions.
+ lens.rewriteReferenceKeys(noSideEffects, rules -> null),
+ lens.rewriteReferenceKeys(assumedValues, rules -> null),
lens.rewriteMethods(alwaysInline),
lens.rewriteMethods(forceInline),
lens.rewriteMethods(neverInline),
diff --git a/src/main/java/com/android/tools/r8/utils/ListUtils.java b/src/main/java/com/android/tools/r8/utils/ListUtils.java
index eb6e610..5781f91 100644
--- a/src/main/java/com/android/tools/r8/utils/ListUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ListUtils.java
@@ -148,6 +148,13 @@
return list;
}
+ public static <T> ArrayList<T> newArrayList(T element, T other) {
+ ArrayList<T> list = new ArrayList<>();
+ list.add(element);
+ list.add(other);
+ return list;
+ }
+
public static <T> ArrayList<T> newArrayList(ForEachable<T> forEachable) {
ArrayList<T> list = new ArrayList<>();
forEachable.forEach(list::add);