VarHandle desugar: Add a builder for DexApplicationReadFlags

Bug: b/247076137
Change-Id: I207462dd555024622618c097019fbb7daaab3d5a
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 23b16cc..894227d 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -302,7 +302,10 @@
     private final Queue<DexClasspathClass> classpathClasses = new ConcurrentLinkedQueue<>();
     private final Queue<DexLibraryClass> libraryClasses = new ConcurrentLinkedQueue<>();
     // Jar application reader to share across all class readers.
-    private final JarApplicationReader application = new JarApplicationReader(options);
+    private final DexApplicationReadFlags.Builder readFlagsBuilder =
+        DexApplicationReadFlags.builder();
+    private final JarApplicationReader application =
+        new JarApplicationReader(options, readFlagsBuilder);
 
     // Flag of which input resource types have flown into the program classes.
     // Note that this is just at the level of the resources having been given.
@@ -317,12 +320,10 @@
     }
 
     public DexApplicationReadFlags getDexApplicationReadFlags() {
-      return new DexApplicationReadFlags(
-          hasReadProgramResourceFromDex,
-          hasReadProgramResourceFromCf,
-          application.getRecordWitnesses(),
-          application.getVarHandleWitnesses(),
-          application.getMethodHandlesLookupWitnesses());
+      return readFlagsBuilder
+          .setHasReadProgramClassFromDex(hasReadProgramResourceFromDex)
+          .setHasReadProgramClassFromCf(hasReadProgramResourceFromCf)
+          .build();
     }
 
     private void readDexSources(List<ProgramResource> dexSources, Queue<DexProgramClass> classes)
diff --git a/src/main/java/com/android/tools/r8/graph/DexApplicationReadFlags.java b/src/main/java/com/android/tools/r8/graph/DexApplicationReadFlags.java
index f949455..2032e29 100644
--- a/src/main/java/com/android/tools/r8/graph/DexApplicationReadFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/DexApplicationReadFlags.java
@@ -3,19 +3,76 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.graph;
 
+import com.google.common.collect.ImmutableSet;
 import java.util.Set;
 
 // Flags set based on the application when it was read.
 // Note that in r8, once classes are pruned, the flags may not reflect the application anymore.
 public class DexApplicationReadFlags {
 
+  public static class Builder {
+
+    private boolean hasReadProgramClassFromDex;
+    private boolean hasReadProgramClassFromCf;
+    private final ImmutableSet.Builder<DexType> recordWitnessesBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<DexType> varHandleWitnessesBuilder = ImmutableSet.builder();
+    private final ImmutableSet.Builder<DexType> methodHandlesLookupWitnessesBuilder =
+        ImmutableSet.builder();
+
+    private Builder() {}
+
+    public Builder setHasReadProgramClassFromDex(boolean value) {
+      hasReadProgramClassFromDex = value;
+      return this;
+    }
+
+    public Builder setHasReadProgramClassFromCf(boolean value) {
+      hasReadProgramClassFromCf = value;
+      return this;
+    }
+
+    public Builder addRecordWitness(DexType witness) {
+      synchronized (recordWitnessesBuilder) {
+        recordWitnessesBuilder.add(witness);
+      }
+      return this;
+    }
+
+    public Builder addVarHandleWitness(DexType witness) {
+      synchronized (varHandleWitnessesBuilder) {
+        varHandleWitnessesBuilder.add(witness);
+      }
+      return this;
+    }
+
+    public Builder addMethodHandlesLookupWitness(DexType witness) {
+      synchronized (methodHandlesLookupWitnessesBuilder) {
+        methodHandlesLookupWitnessesBuilder.add(witness);
+      }
+      return this;
+    }
+
+    public DexApplicationReadFlags build() {
+      return new DexApplicationReadFlags(
+          hasReadProgramClassFromDex,
+          hasReadProgramClassFromCf,
+          recordWitnessesBuilder.build(),
+          varHandleWitnessesBuilder.build(),
+          methodHandlesLookupWitnessesBuilder.build());
+    }
+  }
+
   private final boolean hasReadProgramClassFromDex;
   private final boolean hasReadProgramClassFromCf;
   private final Set<DexType> recordWitnesses;
   private final Set<DexType> varHandleWitnesses;
   private final Set<DexType> methodHandlesLookupWitnesses;
 
-  public DexApplicationReadFlags(
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  private DexApplicationReadFlags(
       boolean hasReadProgramClassFromDex,
       boolean hasReadProgramClassFromCf,
       Set<DexType> recordWitnesses,
diff --git a/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java b/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
index dbdaeb1..2f957dd 100644
--- a/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
@@ -8,9 +8,7 @@
 import com.android.tools.r8.ir.desugar.varhandle.VarHandleDesugaring;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.google.common.collect.Sets;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import org.objectweb.asm.Type;
 
@@ -28,15 +26,17 @@
   private final ConcurrentHashMap<String, Type> asmTypeCache = new ConcurrentHashMap<>();
   private final ConcurrentHashMap<String, DexString> stringCache = new ConcurrentHashMap<>();
   private final ApplicationReaderMap applicationReaderMap;
-  private final Set<DexType> recordWitnesses = Sets.newConcurrentHashSet();
-  private final Set<DexType> varHandleWitnesses = Sets.newConcurrentHashSet();
-  private final Set<DexType> methodHandlesLookupWitnesses = Sets.newConcurrentHashSet();
+  private final DexApplicationReadFlags.Builder readFlagsBuilder;
 
-  private boolean hasReadRecordReferenceFromProgramClass = false;
+  public JarApplicationReader(
+      InternalOptions options, DexApplicationReadFlags.Builder readFlagsBuilder) {
+    this.options = options;
+    this.readFlagsBuilder = readFlagsBuilder;
+    applicationReaderMap = ApplicationReaderMap.getInstance(options);
+  }
 
   public JarApplicationReader(InternalOptions options) {
-    this.options = options;
-    applicationReaderMap = ApplicationReaderMap.getInstance(options);
+    this(options, DexApplicationReadFlags.builder());
   }
 
   public Type getAsmObjectType(String name) {
@@ -160,14 +160,10 @@
 
   public void addRecordWitness(DexType witness, ClassKind<?> classKind) {
     if (classKind == ClassKind.PROGRAM) {
-      recordWitnesses.add(witness);
+      readFlagsBuilder.addRecordWitness(witness);
     }
   }
 
-  public Set<DexType> getRecordWitnesses() {
-    return recordWitnesses;
-  }
-
   public void checkFieldForRecord(DexField dexField, ClassKind<?> classKind) {
     if (options.shouldDesugarRecords() && RecordDesugaring.refersToRecord(dexField, getFactory())) {
       addRecordWitness(dexField.getHolderType(), classKind);
@@ -183,14 +179,10 @@
 
   public void addVarHandleWitness(DexType witness, ClassKind<?> classKind) {
     if (classKind == ClassKind.PROGRAM) {
-      varHandleWitnesses.add(witness);
+      readFlagsBuilder.addVarHandleWitness(witness);
     }
   }
 
-  public Set<DexType> getVarHandleWitnesses() {
-    return varHandleWitnesses;
-  }
-
   public void checkFieldForVarHandle(DexField dexField, ClassKind<?> classKind) {
     if (options.shouldDesugarVarHandle()
         && VarHandleDesugaring.refersToVarHandle(dexField, getFactory())) {
@@ -207,14 +199,10 @@
 
   public void addMethodHandlesLookupWitness(DexType witness, ClassKind<?> classKind) {
     if (classKind == ClassKind.PROGRAM) {
-      methodHandlesLookupWitnesses.add(witness);
+      readFlagsBuilder.addMethodHandlesLookupWitness(witness);
     }
   }
 
-  public Set<DexType> getMethodHandlesLookupWitnesses() {
-    return methodHandlesLookupWitnesses;
-  }
-
   public void checkClassForMethodHandlesLookup(DexClass dexClass, ClassKind<?> classKind) {
     if (options.shouldDesugarVarHandle()) {
       if (VarHandleDesugaring.refersToMethodHandlesLookup(dexClass.getType(), getFactory())) {