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);
     }
   }
 }