Include synthetic kind in the structure of synthetics.
Bug: 188076699
Change-Id: I3c4b52ca9eb1207fa75f6dea95e3f5ce70c39e07
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
index 3c91d68..d868dfc 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
@@ -71,6 +71,7 @@
ClassToFeatureSplitMap classToFeatureSplitMap,
SyntheticItems syntheticItems) {
Hasher hasher = Hashing.murmur3_128().newHasher();
+ hasher.putInt(kind.id);
if (getKind().isFixedSuffixSynthetic) {
// Fixed synthetics are non-shareable. Its unique type is used as the hash key.
getHolder().getType().hash(hasher);
@@ -103,6 +104,12 @@
GraphLens graphLens,
ClassToFeatureSplitMap classToFeatureSplitMap,
SyntheticItems syntheticItems) {
+ {
+ int order = kind.compareTo(other.getKind());
+ if (order != 0) {
+ return order;
+ }
+ }
DexType thisType = getHolder().getType();
DexType otherType = other.getHolder().getType();
if (getKind().isFixedSuffixSynthetic) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 46bb432..f0fc2e7 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -41,6 +41,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
@@ -553,10 +554,11 @@
(externalSyntheticTypePrefix, groups) -> {
// Sort the equivalence groups that go into 'context' including the context type of the
// representative which is equal to 'context' here (see assert below).
- groups.sort(
+ Comparator<EquivalenceGroup<T>> comparator =
(a, b) ->
a.compareToIncludingContext(
- b, appView.graphLens(), classToFeatureSplitMap, synthetics));
+ b, appView.graphLens(), classToFeatureSplitMap, synthetics);
+ ListUtils.destructiveSort(groups, comparator);
for (int i = 0; i < groups.size(); i++) {
EquivalenceGroup<T> group = groups.get(i);
assert group
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 e7c8e46..3966fd0 100644
--- a/src/main/java/com/android/tools/r8/utils/ListUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ListUtils.java
@@ -7,6 +7,7 @@
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
@@ -181,4 +182,36 @@
public interface ReferenceAndIntConsumer<T> {
void accept(T item, int index);
}
+
+ public static <T> void destructiveSort(List<T> items, Comparator<T> comparator) {
+ items.sort(comparator);
+ }
+
+ // Utility to add a slow verification of a comparator as part of sorting. Note that this
+ // should not generally be used in asserts unless the quadratic behavior can be tolerated.
+ public static <T> void destructiveSortAndVerify(List<T> items, Comparator<T> comparator) {
+ destructiveSort(items, comparator);
+ assert verifyComparatorOnSortedList(items, comparator);
+ }
+
+ private static <T> boolean verifyComparatorOnSortedList(List<T> items, Comparator<T> comparator) {
+ for (int i = 0; i < items.size(); i++) {
+ boolean allowEqual = true;
+ for (int j = i; j < items.size(); j++) {
+ T a = items.get(i);
+ T b = items.get(j);
+ int result1 = comparator.compare(a, b);
+ int result2 = comparator.compare(b, a);
+ boolean isEqual = result1 == 0 && result2 == 0;
+ if (i == j) {
+ assert isEqual;
+ } else if (!allowEqual || !isEqual) {
+ allowEqual = false;
+ assert result1 < 0;
+ assert result2 > 0;
+ }
+ }
+ }
+ return true;
+ }
}