Fix non determinism of D8 with synthetics
Before we would be generating different hashes for the synthetic methods.
Bug: b/359616078
Change-Id: I0cc31845cf773cdd475810160bcfda1b621a28f1
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
index 068a1a7..6f20ec4 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
@@ -25,6 +25,8 @@
import com.android.tools.r8.graph.RecordComponentInfo;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.structural.HasherWrapper;
+import com.android.tools.r8.utils.structural.StructuralItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -185,11 +187,6 @@
directMethods.add(method);
}
}
- long checksum =
- 7 * (long) directMethods.hashCode()
- + 11 * (long) virtualMethods.hashCode()
- + 13 * (long) staticFields.hashCode()
- + 17 * (long) instanceFields.hashCode();
C clazz =
getClassKind()
.create(
@@ -213,7 +210,7 @@
DexEncodedMethod.EMPTY_ARRAY,
DexEncodedMethod.EMPTY_ARRAY,
factory.getSkipNameValidationForTesting(),
- c -> checksum,
+ c -> getChecksum(),
null);
if (useSortedMethodBacking) {
clazz.getMethodCollection().useSortedBacking();
@@ -222,4 +219,17 @@
clazz.setVirtualMethods(virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY));
return clazz;
}
+
+ private long getChecksum() {
+ return 7 * hashEntries(virtualMethods, directMethods)
+ + 13 * hashEntries(instanceFields, staticFields);
+ }
+
+ private <S extends StructuralItem<S>> long hashEntries(List<S>... entryLists) {
+ HasherWrapper hasherWrapper = HasherWrapper.murmur3128Hasher();
+ for (List<S> entryList : entryLists) {
+ entryList.stream().sorted().forEach(e -> e.hash(hasherWrapper));
+ }
+ return hasherWrapper.hash().hashCode();
+ }
}