Fix race condition in AnnotationRemover.Builder annotation retention
During Enqueuer tracing, multiple threads concurrently register matched
annotations for retention. AnnotationRemover.Builder.annotationsToRetain
was a non-thread-safe IdentityHashSet, leading to non-deterministic
lost updates (race on write) and corrupted resizes.
Change-Id: Icc8b7ea161cb316a873a813735381c51e76f2783
Bug: b/510830974
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 9bc1250..f21f525 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -31,8 +31,10 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.internal.ArrayUtils;
+import com.android.tools.r8.utils.internal.SetUtils;
import com.android.tools.r8.utils.internal.exceptions.Unreachable;
import com.google.common.collect.Sets;
+import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -477,7 +479,8 @@
* The set of annotations that were matched by a conditional if rule. These are needed for the
* interpretation of if rules in the second round of tree shaking.
*/
- private final Set<DexAnnotation> annotationsToRetain = Sets.newIdentityHashSet();
+ private final Set<DexAnnotation> annotationsToRetain =
+ Collections.synchronizedSet(Sets.newIdentityHashSet());
private final Mode mode;
@@ -494,7 +497,7 @@
}
public AnnotationRemover build(AppView<AppInfoWithLiveness> appView) {
- return new AnnotationRemover(appView, annotationsToRetain, mode);
+ return new AnnotationRemover(appView, SetUtils.newIdentityHashSet(annotationsToRetain), mode);
}
}
}