Use builder in Nest lens

Bug:147204126
Change-Id: I728852c38edbc3f8d16ee736dddb4028e0a75f75
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLense.java b/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLense.java
index babdbae..9fca058 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLense.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLense.java
@@ -41,9 +41,9 @@
     assert methodMap instanceof IdentityHashMap;
     assert getFieldMap instanceof IdentityHashMap;
     assert putFieldMap instanceof IdentityHashMap;
+    this.nestConstructorType = nestConstructorType;
     this.getFieldMap = getFieldMap;
     this.putFieldMap = putFieldMap;
-    this.nestConstructorType = nestConstructorType;
   }
 
   private DexMethod lookupFieldForMethod(
@@ -111,11 +111,8 @@
   @Override
   public GraphLenseLookupResult lookupMethod(
       DexMethod method, DexMethod context, Invoke.Type type) {
-    DexMethod previousContext =
-        originalMethodSignatures != null
-            ? originalMethodSignatures.getOrDefault(context, context)
-            : context;
-    GraphLenseLookupResult previous = previousLense.lookupMethod(method, previousContext, type);
+    assert originalMethodSignatures == null;
+    GraphLenseLookupResult previous = previousLense.lookupMethod(method, context, type);
     DexMethod bridge = methodMap.get(previous.getMethod());
     if (bridge == null) {
       return previous;
@@ -130,4 +127,31 @@
     return new GraphLenseLookupResult(bridge, Invoke.Type.STATIC);
   }
 
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static class Builder extends NestedGraphLense.Builder {
+
+    private Map<DexField, DexMethod> getFieldMap = new IdentityHashMap<>();
+    private Map<DexField, DexMethod> putFieldMap = new IdentityHashMap<>();
+
+    public void mapGetField(DexField from, DexMethod to) {
+      getFieldMap.put(from, to);
+    }
+
+    public void mapPutField(DexField from, DexMethod to) {
+      putFieldMap.put(from, to);
+    }
+
+    public GraphLense build(AppView<?> appView, DexType nestConstructorType) {
+      assert typeMap.isEmpty();
+      assert fieldMap.isEmpty();
+      if (getFieldMap.isEmpty() && methodMap.isEmpty() && putFieldMap.isEmpty()) {
+        return appView.graphLense();
+      }
+      return new NestedPrivateMethodLense(
+          appView, nestConstructorType, methodMap, getFieldMap, putFieldMap, appView.graphLense());
+    }
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/R8NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/R8NestBasedAccessDesugaring.java
index a4642cd..1a6c365 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/R8NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/R8NestBasedAccessDesugaring.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
@@ -16,13 +15,13 @@
 import com.android.tools.r8.utils.ThreadUtils;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
+import java.util.function.BiConsumer;
 
 // Summary:
 // - Computes all the live nests reachable from Program Classes (Sequential), each time a
@@ -31,10 +30,6 @@
 // for the lens (Sequential)
 public class R8NestBasedAccessDesugaring extends NestBasedAccessDesugaring {
 
-  private final Map<DexMethod, DexMethod> lensBridges = new IdentityHashMap<>();
-  private final Map<DexField, DexMethod> lensGetFieldBridges = new IdentityHashMap<>();
-  private final Map<DexField, DexMethod> lensPutFieldBridges = new IdentityHashMap<>();
-
   public R8NestBasedAccessDesugaring(AppView<?> appView) {
     super(appView);
   }
@@ -44,43 +39,27 @@
     assert !appView.options().canUseNestBasedAccess()
         || appView.options().testing.enableForceNestBasedAccessDesugaringForTest;
     computeAndProcessNestsConcurrently(executorService);
-    addDeferredBridgesAndMapMethods();
+    NestedPrivateMethodLense.Builder lensBuilder = NestedPrivateMethodLense.builder();
+    addDeferredBridgesAndMapMethods(lensBuilder);
     clearNestAttributes();
-    if (nothingToMap()) {
-      return appView.graphLense();
-    }
     synthesizeNestConstructor(appBuilder);
-    return new NestedPrivateMethodLense(
-        appView,
-        getNestConstructorType(),
-        lensBridges,
-        lensGetFieldBridges,
-        lensPutFieldBridges,
-        appView.graphLense());
+    return lensBuilder.build(appView, getNestConstructorType());
   }
 
-  private boolean nothingToMap() {
-    return lensBridges.isEmpty() && lensGetFieldBridges.isEmpty() && lensPutFieldBridges.isEmpty();
-  }
-
-  private void addDeferredBridgesAndMapMethods() {
+  private void addDeferredBridgesAndMapMethods(NestedPrivateMethodLense.Builder lensBuilder) {
     // Here we add the bridges and we fill the lens map.
-    // The lens map are different than the original map since
-    // they refer DexMethod and not DexEncodedMethod (so they can be long lived without issues),
-    // and since they do not require synchronization (they are only read in the lens).
-    // We cannot easily do this concurrently since methods are added to classes.
-    addDeferredBridgesAndMapMethods(bridges, lensBridges);
-    addDeferredBridgesAndMapMethods(getFieldBridges, lensGetFieldBridges);
-    addDeferredBridgesAndMapMethods(putFieldBridges, lensPutFieldBridges);
+    addDeferredBridgesAndMapMethods(bridges, lensBuilder::map);
+    addDeferredBridgesAndMapMethods(getFieldBridges, lensBuilder::mapGetField);
+    addDeferredBridgesAndMapMethods(putFieldBridges, lensBuilder::mapPutField);
   }
 
   private <E> void addDeferredBridgesAndMapMethods(
-      Map<E, DexEncodedMethod> bridges, Map<E, DexMethod> map) {
+      Map<E, DexEncodedMethod> bridges, BiConsumer<E, DexMethod> lensInserter) {
     for (Map.Entry<E, DexEncodedMethod> entry : bridges.entrySet()) {
       DexClass holder = definitionFor(entry.getValue().method.holder);
       assert holder != null && holder.isProgramClass();
       holder.asProgramClass().addMethod(entry.getValue());
-      map.put(entry.getKey(), entry.getValue().method);
+      lensInserter.accept(entry.getKey(), entry.getValue().method);
     }
     bridges.clear();
   }