Fix non-deternism in class staticizer
Bug: 161727616
Bug: 163097346
Change-Id: Id640b20abbe86691740bf4c647fe79a704a1a376
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) ||