Version 2.1.62
Cherry-pick: Fix non-deternism in class staticizer
CL: https://r8-review.googlesource.com/c/r8/+/52840
Bug: 161727616
Bug: 163097346
Change-Id: I81b04ff8e1dc2ae479d5fe67b2390f5a757ad3ea
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 571ec73..317ddf9 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "2.1.61";
+ public static final String LABEL = "2.1.62";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
index 323dd11..19aa4c2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizer.java
@@ -274,8 +274,8 @@
if (instruction.isNewInstance()) {
// Check the class being initialized against valid staticizing candidates.
NewInstance newInstance = instruction.asNewInstance();
- CandidateInfo candidateInfo = processInstantiation(context, iterator, newInstance);
- if (candidateInfo != null) {
+ CandidateInfo info = processInstantiation(context, iterator, newInstance);
+ if (info != null) {
alreadyProcessed.addAll(newInstance.outValue().aliasedUsers());
// For host class initializers having eligible instantiation we also want to
// ensure that the rest of the initializer consist of code w/o side effects.
@@ -283,15 +283,13 @@
// effects, otherwise we can still staticize, but cannot remove singleton reads.
while (iterator.hasNext()) {
if (!isAllowedInHostClassInitializer(context.getHolderType(), iterator.next(), code)) {
- candidateInfo.preserveRead.set(true);
+ info.preserveRead.set(true);
iterator.previous();
break;
}
// Ignore just read instruction.
}
- referencedFrom
- .computeIfAbsent(candidateInfo, ignore -> LongLivedProgramMethodSetBuilder.create())
- .add(context);
+ addReferencedFrom(info, context);
}
continue;
}
@@ -311,9 +309,7 @@
// Check the field being read: make sure all usages are valid.
CandidateInfo info = processStaticFieldRead(instruction.asStaticGet());
if (info != null) {
- referencedFrom
- .computeIfAbsent(info, ignore -> LongLivedProgramMethodSetBuilder.create())
- .add(context);
+ addReferencedFrom(info, context);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -327,9 +323,7 @@
// Check if it is a static singleton getter.
CandidateInfo info = processInvokeStatic(instruction.asInvokeStatic());
if (info != null) {
- referencedFrom
- .computeIfAbsent(info, ignore -> LongLivedProgramMethodSetBuilder.create())
- .add(context);
+ addReferencedFrom(info, context);
// If the candidate is still valid, ignore all usages in further analysis.
Value value = instruction.outValue();
if (value != null) {
@@ -368,6 +362,14 @@
}
}
+ private void addReferencedFrom(CandidateInfo info, ProgramMethod context) {
+ LongLivedProgramMethodSetBuilder builder =
+ referencedFrom.computeIfAbsent(info, ignore -> LongLivedProgramMethodSetBuilder.create());
+ synchronized (builder) {
+ builder.add(context);
+ }
+ }
+
private boolean isAllowedInHostClassInitializer(
DexType host, Instruction insn, IRCode code) {
return (insn.isStaticPut() && insn.asStaticPut().getField().holder == host) ||