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
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 5a3b866..9023c91 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -31,9 +31,11 @@
import com.android.tools.r8.shaking.Enqueuer.Mode;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.SetUtils;
import com.android.tools.r8.utils.ThreadUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
+import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -478,7 +480,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;
@@ -495,7 +498,7 @@
}
public AnnotationRemover build(AppView<AppInfoWithLiveness> appView) {
- return new AnnotationRemover(appView, annotationsToRetain, mode);
+ return new AnnotationRemover(appView, SetUtils.newIdentityHashSet(annotationsToRetain), mode);
}
}
}