Minor cleanup related to lambda merger

Change-Id: Ia3288155b047e6ded6a5186af7b835c6fef22910
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 1f7f7b5..be44297 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -252,7 +252,6 @@
         options.enableDesugaring
             ? new BackportedMethodRewriter(appView, this)
             : null;
-    this.lambdaMerger = options.enableLambdaMerging ? new LambdaMerger(appView) : null;
     this.covariantReturnTypeAnnotationTransformer =
         options.processCovariantReturnTypeAnnotations
             ? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
@@ -284,6 +283,8 @@
               : null;
       this.lensCodeRewriter = new LensCodeRewriter(appViewWithLiveness, lambdaRewriter);
       this.inliner = new Inliner(appViewWithLiveness, mainDexClasses, lensCodeRewriter);
+      this.lambdaMerger =
+          options.enableLambdaMerging ? new LambdaMerger(appViewWithLiveness) : null;
       this.outliner = new Outliner(appViewWithLiveness, this);
       this.memberValuePropagation =
           options.enableValuePropagation ? new MemberValuePropagation(appViewWithLiveness) : null;
@@ -307,6 +308,7 @@
       this.fieldBitAccessAnalysis = null;
       this.libraryMethodOverrideAnalysis = null;
       this.inliner = null;
+      this.lambdaMerger = null;
       this.outliner = null;
       this.memberValuePropagation = null;
       this.lensCodeRewriter = null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
index 8d33db8..e7da094 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/CodeProcessor.java
@@ -26,7 +26,9 @@
 import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.StaticGet;
 import com.android.tools.r8.ir.code.StaticPut;
+import com.android.tools.r8.ir.optimize.lambda.LambdaMerger.ApplyStrategy;
 import com.android.tools.r8.kotlin.Kotlin;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.ListIterator;
 import java.util.function.Function;
 
@@ -59,88 +61,75 @@
 
     boolean isValidNewInstance(CodeProcessor context, NewInstance invoke);
 
-    void patch(CodeProcessor context, NewInstance newInstance);
+    void patch(ApplyStrategy context, NewInstance newInstance);
 
-    void patch(CodeProcessor context, InvokeMethod invoke);
+    void patch(ApplyStrategy context, InvokeMethod invoke);
 
-    void patch(CodeProcessor context, InstancePut instancePut);
+    void patch(ApplyStrategy context, InstanceGet instanceGet);
 
-    void patch(CodeProcessor context, InstanceGet instanceGet);
-
-    void patch(CodeProcessor context, StaticPut staticPut);
-
-    void patch(CodeProcessor context, StaticGet staticGet);
+    void patch(ApplyStrategy context, StaticGet staticGet);
   }
 
   // No-op strategy.
-  static final Strategy NoOp = new Strategy() {
-    @Override
-    public LambdaGroup group() {
-      return null;
-    }
+  static final Strategy NoOp =
+      new Strategy() {
+        @Override
+        public LambdaGroup group() {
+          return null;
+        }
 
-    @Override
-    public boolean isValidInstanceFieldWrite(CodeProcessor context, DexField field) {
-      return false;
-    }
+        @Override
+        public boolean isValidInstanceFieldWrite(CodeProcessor context, DexField field) {
+          return false;
+        }
 
-    @Override
-    public boolean isValidInstanceFieldRead(CodeProcessor context, DexField field) {
-      return false;
-    }
+        @Override
+        public boolean isValidInstanceFieldRead(CodeProcessor context, DexField field) {
+          return false;
+        }
 
-    @Override
-    public boolean isValidStaticFieldWrite(CodeProcessor context, DexField field) {
-      return false;
-    }
+        @Override
+        public boolean isValidStaticFieldWrite(CodeProcessor context, DexField field) {
+          return false;
+        }
 
-    @Override
-    public boolean isValidStaticFieldRead(CodeProcessor context, DexField field) {
-      return false;
-    }
+        @Override
+        public boolean isValidStaticFieldRead(CodeProcessor context, DexField field) {
+          return false;
+        }
 
-    @Override
-    public boolean isValidInvoke(CodeProcessor context, InvokeMethod invoke) {
-      return false;
-    }
+        @Override
+        public boolean isValidInvoke(CodeProcessor context, InvokeMethod invoke) {
+          return false;
+        }
 
-    @Override
-    public boolean isValidNewInstance(CodeProcessor context, NewInstance invoke) {
-      return false;
-    }
+        @Override
+        public boolean isValidNewInstance(CodeProcessor context, NewInstance invoke) {
+          return false;
+        }
 
-    @Override
-    public void patch(CodeProcessor context, NewInstance newInstance) {
-      throw new Unreachable();
-    }
+        @Override
+        public void patch(ApplyStrategy context, NewInstance newInstance) {
+          throw new Unreachable();
+        }
 
-    @Override
-    public void patch(CodeProcessor context, InvokeMethod invoke) {
-      throw new Unreachable();
-    }
+        @Override
+        public void patch(ApplyStrategy context, InvokeMethod invoke) {
+          throw new Unreachable();
+        }
 
-    @Override
-    public void patch(CodeProcessor context, InstancePut instancePut) {
-      throw new Unreachable();
-    }
+        @Override
+        public void patch(ApplyStrategy context, InstanceGet instanceGet) {
+          throw new Unreachable();
+        }
 
-    @Override
-    public void patch(CodeProcessor context, InstanceGet instanceGet) {
-      throw new Unreachable();
-    }
+        @Override
+        public void patch(ApplyStrategy context, StaticGet staticGet) {
+          throw new Unreachable();
+        }
+      };
 
-    @Override
-    public void patch(CodeProcessor context, StaticPut staticPut) {
-      throw new Unreachable();
-    }
-
-    @Override
-    public void patch(CodeProcessor context, StaticGet staticGet) {
-      throw new Unreachable();
-    }
-  };
-
-  public final AppView<?> appView;
+  public final AppView<AppInfoWithLiveness> appView;
   public final DexItemFactory factory;
   public final Kotlin kotlin;
 
@@ -159,7 +148,7 @@
   private InstructionListIterator instructions;
 
   CodeProcessor(
-      AppView<?> appView,
+      AppView<AppInfoWithLiveness> appView,
       Function<DexType, Strategy> strategyProvider,
       LambdaTypeVisitor lambdaChecker,
       DexEncodedMethod method,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 87fc257..cd07285 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -6,7 +6,6 @@
 
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexApplication.Builder;
@@ -99,7 +98,7 @@
   // should not be happening very frequently and we ignore possible overhead.
   private final Set<DexEncodedMethod> methodsToReprocess = Sets.newIdentityHashSet();
 
-  private final AppView<?> appView;
+  private final AppView<AppInfoWithLiveness> appView;
   private final DexItemFactory factory;
   private final Kotlin kotlin;
   private final DiagnosticsHandler reporter;
@@ -111,7 +110,7 @@
   // Lambda visitor throwing Unreachable on each lambdas it sees.
   private final LambdaTypeVisitor lambdaChecker;
 
-  public LambdaMerger(AppView<?> appView) {
+  public LambdaMerger(AppView<AppInfoWithLiveness> appView) {
     this.appView = appView;
     this.factory = appView.dexItemFactory();
     this.kotlin = factory.kotlin;
@@ -212,14 +211,11 @@
     analyzeReferencesInProgramClasses(app, executorService);
 
     // Analyse more complex aspects of lambda classes including method code.
-    assert appView.appInfo().hasSubtyping();
-    AppInfoWithSubtyping appInfoWithSubtyping = appView.appInfo().withSubtyping();
-    analyzeLambdaClassesStructure(appInfoWithSubtyping, executorService);
+    analyzeLambdaClassesStructure(executorService);
 
     // Remove invalidated lambdas, compact groups to ensure
     // sequential lambda ids, create group lambda classes.
-    Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses =
-        finalizeLambdaGroups(appInfoWithSubtyping);
+    Map<LambdaGroup, DexProgramClass> lambdaGroupsClasses = finalizeLambdaGroups();
 
     // Switch to APPLY strategy.
     this.strategyFactory = ApplyStrategy::new;
@@ -258,12 +254,11 @@
     ThreadUtils.awaitFutures(futures);
   }
 
-  private void analyzeLambdaClassesStructure(
-      AppInfoWithSubtyping appInfo, ExecutorService service) throws ExecutionException {
+  private void analyzeLambdaClassesStructure(ExecutorService service) throws ExecutionException {
     List<Future<?>> futures = new ArrayList<>();
     for (LambdaGroup group : groups.values()) {
       ThrowingConsumer<DexClass, LambdaStructureError> validator =
-          group.lambdaClassValidator(kotlin, appInfo);
+          group.lambdaClassValidator(kotlin, appView.appInfo());
       group.forEachLambda(info ->
           futures.add(service.submit(() -> {
             try {
@@ -282,7 +277,7 @@
     ThreadUtils.awaitFutures(futures);
   }
 
-  private Map<LambdaGroup, DexProgramClass> finalizeLambdaGroups(AppInfoWithSubtyping appInfo) {
+  private Map<LambdaGroup, DexProgramClass> finalizeLambdaGroups() {
     for (DexType lambda : invalidatedLambdas) {
       LambdaGroup group = lambdas.get(lambda);
       assert group != null;
@@ -303,7 +298,7 @@
       result.put(group, lambdaGroupClass);
 
       // We have to register this new class as a subtype of object.
-      appInfo.registerNewType(lambdaGroupClass.type, lambdaGroupClass.superType);
+      appView.appInfo().registerNewType(lambdaGroupClass.type, lambdaGroupClass.superType);
     }
     return result;
   }
@@ -423,7 +418,7 @@
     }
   }
 
-  private final class ApplyStrategy extends CodeProcessor {
+  public final class ApplyStrategy extends CodeProcessor {
     private ApplyStrategy(DexEncodedMethod method, IRCode code) {
       super(
           LambdaMerger.this.appView,
@@ -445,7 +440,9 @@
 
     @Override
     void process(Strategy strategy, InstancePut instancePut) {
-      strategy.patch(this, instancePut);
+      // Instance put should only appear in lambda class instance constructor,
+      // we should never get here since we never rewrite them.
+      throw new Unreachable();
     }
 
     @Override
@@ -455,7 +452,9 @@
 
     @Override
     void process(Strategy strategy, StaticPut staticPut) {
-      strategy.patch(this, staticPut);
+      // Static put should only appear in lambda class static initializer,
+      // we should never get here since we never rewrite them.
+      throw new Unreachable();
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
index 9552267..2e82172 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupCodeStrategy.java
@@ -7,7 +7,6 @@
 import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
 import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
 
-import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
@@ -17,19 +16,18 @@
 import com.android.tools.r8.ir.code.CheckCast;
 import com.android.tools.r8.ir.code.ConstNumber;
 import com.android.tools.r8.ir.code.InstanceGet;
-import com.android.tools.r8.ir.code.InstancePut;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InvokeDirect;
 import com.android.tools.r8.ir.code.InvokeMethod;
 import com.android.tools.r8.ir.code.InvokeVirtual;
 import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.StaticGet;
-import com.android.tools.r8.ir.code.StaticPut;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.optimize.lambda.CaptureSignature;
 import com.android.tools.r8.ir.optimize.lambda.CodeProcessor;
 import com.android.tools.r8.ir.optimize.lambda.CodeProcessor.Strategy;
 import com.android.tools.r8.ir.optimize.lambda.LambdaGroup;
+import com.android.tools.r8.ir.optimize.lambda.LambdaMerger.ApplyStrategy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -114,7 +112,7 @@
   }
 
   @Override
-  public void patch(CodeProcessor context, NewInstance newInstance) {
+  public void patch(ApplyStrategy context, NewInstance newInstance) {
     NewInstance patchedNewInstance =
         new NewInstance(
             group.getGroupClassType(),
@@ -125,7 +123,7 @@
   }
 
   @Override
-  public void patch(CodeProcessor context, InvokeMethod invoke) {
+  public void patch(ApplyStrategy context, InvokeMethod invoke) {
     assert group.containsLambda(invoke.getInvokedMethod().holder);
     if (isValidInitializerCall(context, invoke)) {
       patchInitializer(context, invoke.asInvokeDirect());
@@ -140,14 +138,7 @@
   }
 
   @Override
-  public void patch(CodeProcessor context, InstancePut instancePut) {
-    // Instance put should only appear in lambda class instance constructor,
-    // we should never get here since we never rewrite them.
-    throw new Unreachable();
-  }
-
-  @Override
-  public void patch(CodeProcessor context, InstanceGet instanceGet) {
+  public void patch(ApplyStrategy context, InstanceGet instanceGet) {
     DexField field = instanceGet.getField();
     DexType fieldType = field.type;
 
@@ -182,14 +173,7 @@
   }
 
   @Override
-  public void patch(CodeProcessor context, StaticPut staticPut) {
-    // Static put should only appear in lambda class static initializer,
-    // we should never get here since we never rewrite them.
-    throw new Unreachable();
-  }
-
-  @Override
-  public void patch(CodeProcessor context, StaticGet staticGet) {
+  public void patch(ApplyStrategy context, StaticGet staticGet) {
     context
         .instructions()
         .replaceCurrentInstruction(