Introduce ApplicationReaderMap instances

Bug: 201364089
Change-Id: Ia42044dd17ecdabfcc402aa725c3df7d09d52d8a
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 1afa0b8..e469f0a 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -54,7 +54,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ExecutionException;
@@ -368,13 +367,13 @@
       }
       // Read the DexCode items and DexProgramClass items in parallel.
       if (!options.skipReadingDexCode) {
-        Map<DexType, DexType> invertedTypeMap = ApplicationReaderMap.getInvertedTypeMap(options);
+        ApplicationReaderMap applicationReaderMap = ApplicationReaderMap.getInstance(options);
         for (DexParser<DexProgramClass> dexParser : dexParsers) {
           futures.add(
               executorService.submit(
                   () -> {
                     dexParser.addClassDefsTo(
-                        classes::add, invertedTypeMap); // Depends on Methods, Code items etc.
+                        classes::add, applicationReaderMap); // Depends on Methods, Code items etc.
                   }));
         }
       }
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index 2d9d4aa..03e0e31 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -80,7 +80,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 
@@ -715,7 +714,7 @@
     return methods;
   }
 
-  void addClassDefsTo(Consumer<T> classCollection, Map<DexType, DexType> invertedTypeMap) {
+  void addClassDefsTo(Consumer<T> classCollection, ApplicationReaderMap applicationReaderMap) {
     final DexSection dexSection = lookupSection(Constants.TYPE_CLASS_DEF_ITEM);
     final int length = dexSection.length;
     indexedItems.initializeClasses(length);
@@ -768,7 +767,7 @@
 
       Long checksum = null;
       if (checksums != null && !checksums.isEmpty()) {
-        DexType originalType = invertedTypeMap.getOrDefault(type, type);
+        DexType originalType = applicationReaderMap.getInvertedType(type);
         String desc = originalType.toDescriptorString();
         checksum = checksums.getOrDefault(desc, null);
         if (!options.dexClassChecksumFilter.test(desc, checksum)) {
@@ -1004,11 +1003,11 @@
   private void populateTypes() {
     DexSection dexSection = lookupSection(Constants.TYPE_TYPE_ID_ITEM);
     assert verifyOrderOfTypeIds(dexSection);
-    Map<DexType, DexType> typeMap = ApplicationReaderMap.getTypeMap(options);
+    ApplicationReaderMap applicationReaderMap = ApplicationReaderMap.getInstance(options);
     indexedItems.initializeTypes(dexSection.length);
     for (int i = 0; i < dexSection.length; i++) {
       DexType type = typeAt(i);
-      DexType actualType = typeMap.getOrDefault(type, type);
+      DexType actualType = applicationReaderMap.getType(type);
       indexedItems.setType(i, actualType);
     }
   }
diff --git a/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java b/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java
index b75d678..496066b3 100644
--- a/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java
+++ b/src/main/java/com/android/tools/r8/graph/ApplicationReaderMap.java
@@ -5,38 +5,65 @@
 package com.android.tools.r8.graph;
 
 import com.android.tools.r8.utils.InternalOptions;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
 
-public class ApplicationReaderMap {
+public abstract class ApplicationReaderMap {
 
-  public static Map<String, String> getDescriptorMap(InternalOptions options) {
-    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
+  public static ApplicationReaderMap INSTANCE;
+
+  public abstract String getDescriptor(String descriptor);
+
+  public abstract DexType getType(DexType type);
+
+  public abstract DexType getInvertedType(DexType type);
+
+  public static ApplicationReaderMap getInstance(InternalOptions options) {
     if (options.shouldDesugarRecords() && !options.testing.disableRecordApplicationReaderMap) {
-      builder.put(DexItemFactory.recordTagDescriptorString, DexItemFactory.recordDescriptorString);
+      return new RecordMap(options.dexItemFactory());
     }
-    return builder.build();
+    return new EmptyMap();
   }
 
-  public static Map<DexType, DexType> getTypeMap(InternalOptions options) {
-    DexItemFactory factory = options.dexItemFactory();
-    ImmutableMap.Builder<DexType, DexType> builder = ImmutableMap.builder();
-    getDescriptorMap(options)
-        .forEach(
-            (k, v) -> {
-              builder.put(factory.createType(k), factory.createType(v));
-            });
-    return builder.build();
+  public static class EmptyMap extends ApplicationReaderMap {
+
+    @Override
+    public String getDescriptor(String descriptor) {
+      return descriptor;
+    }
+
+    @Override
+    public DexType getType(DexType type) {
+      return type;
+    }
+
+    @Override
+    public DexType getInvertedType(DexType type) {
+      return type;
+    }
   }
 
-  public static Map<DexType, DexType> getInvertedTypeMap(InternalOptions options) {
-    DexItemFactory factory = options.dexItemFactory();
-    ImmutableMap.Builder<DexType, DexType> builder = ImmutableMap.builder();
-    getDescriptorMap(options)
-        .forEach(
-            (k, v) -> {
-              builder.put(factory.createType(v), factory.createType(k));
-            });
-    return builder.build();
+  public static class RecordMap extends ApplicationReaderMap {
+
+    private final DexItemFactory factory;
+
+    public RecordMap(DexItemFactory factory) {
+      this.factory = factory;
+    }
+
+    @Override
+    public String getDescriptor(String descriptor) {
+      return descriptor.equals(DexItemFactory.recordTagDescriptorString)
+          ? DexItemFactory.recordDescriptorString
+          : descriptor;
+    }
+
+    @Override
+    public DexType getType(DexType type) {
+      return type == factory.recordTagType ? factory.recordType : type;
+    }
+
+    @Override
+    public DexType getInvertedType(DexType type) {
+      return type == factory.recordType ? factory.recordTagType : type;
+    }
   }
 }
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 047be58..0bcf832 100644
--- a/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarApplicationReader.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import org.objectweb.asm.Type;
 
@@ -25,13 +24,13 @@
   private final ConcurrentHashMap<String, Type> asmObjectTypeCache = new ConcurrentHashMap<>();
   private final ConcurrentHashMap<String, Type> asmTypeCache = new ConcurrentHashMap<>();
   private final ConcurrentHashMap<String, DexString> stringCache = new ConcurrentHashMap<>();
-  private final Map<String, String> typeDescriptorMap;
+  private final ApplicationReaderMap applicationReaderMap;
 
   private boolean hasReadRecordReferenceFromProgramClass = false;
 
   public JarApplicationReader(InternalOptions options) {
     this.options = options;
-    typeDescriptorMap = ApplicationReaderMap.getDescriptorMap(options);
+    applicationReaderMap = ApplicationReaderMap.getInstance(options);
   }
 
   public Type getAsmObjectType(String name) {
@@ -61,7 +60,7 @@
 
   public DexType getTypeFromDescriptor(String desc) {
     assert isValidDescriptor(desc);
-    String actualDesc = typeDescriptorMap.getOrDefault(desc, desc);
+    String actualDesc = applicationReaderMap.getDescriptor(desc);
     return options.itemFactory.createType(getString(actualDesc));
   }