Generalize instruction transform helpers.

The generalization makes it easier to match a point and replace it by
arbitrary instructions instead of being limited to instructions of
the same kind.

Change-Id: I0618ec095c7659dfc1daf66f1f856cd928a44ec9
diff --git a/src/test/java/com/android/tools/r8/cf/ConstantDynamicHolderTest.java b/src/test/java/com/android/tools/r8/cf/ConstantDynamicHolderTest.java
index 81f50fc..1ec23ca 100644
--- a/src/test/java/com/android/tools/r8/cf/ConstantDynamicHolderTest.java
+++ b/src/test/java/com/android/tools/r8/cf/ConstantDynamicHolderTest.java
@@ -80,7 +80,7 @@
             "main",
             (value, continuation) -> {
               assertEquals("replaced by dynamic null constant", value);
-              continuation.apply(getDynamicConstant());
+              continuation.visitLdcInsn(getDynamicConstant());
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/cf/methodhandles/InvalidBootstrapMethodHandleTest.java b/src/test/java/com/android/tools/r8/cf/methodhandles/InvalidBootstrapMethodHandleTest.java
index 900fb85..a815910 100644
--- a/src/test/java/com/android/tools/r8/cf/methodhandles/InvalidBootstrapMethodHandleTest.java
+++ b/src/test/java/com/android/tools/r8/cf/methodhandles/InvalidBootstrapMethodHandleTest.java
@@ -10,7 +10,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRunResult;
-import com.android.tools.r8.transformers.MethodTransformer;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.collect.ImmutableMap;
 import java.util.List;
@@ -175,16 +174,13 @@
 
   private byte[] getProgramClassFileData() throws Exception {
     return transformer(InvalidBootstrapMethodHandleTestClass.class)
-        .addMethodTransformer(
-            new MethodTransformer() {
-              @Override
-              public void visitMethodInsn(
-                  int opcode, String owner, String name, String descriptor, boolean isInterface) {
-                if (opcode == Opcodes.INVOKESTATIC && name.equals("foo")) {
-                  visitInvokeDynamicInsn("foo", "()V", getHandle());
-                } else {
-                  super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
-                }
+        .transformMethodInsnInMethod(
+            "main",
+            (opcode, owner, name, descriptor, isInterface, visitor) -> {
+              if (opcode == Opcodes.INVOKESTATIC && name.equals("foo")) {
+                visitor.visitInvokeDynamicInsn("foo", "()V", getHandle());
+              } else {
+                visitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/classmerging/VerticalClassMergerSuperCallInStaticTest.java b/src/test/java/com/android/tools/r8/classmerging/VerticalClassMergerSuperCallInStaticTest.java
index dafc7db..cab2a18 100644
--- a/src/test/java/com/android/tools/r8/classmerging/VerticalClassMergerSuperCallInStaticTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/VerticalClassMergerSuperCallInStaticTest.java
@@ -72,7 +72,7 @@
         .transformMethodInsnInMethod(
             "callSuper",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
-              continuation.apply(
+              continuation.visitMethodInsn(
                   INVOKESPECIAL,
                   DescriptorUtils.getBinaryNameFromJavaType(Base.class.getTypeName()),
                   name,
diff --git a/src/test/java/com/android/tools/r8/desugar/DefaultMethodWithAccessTest.java b/src/test/java/com/android/tools/r8/desugar/DefaultMethodWithAccessTest.java
index 0c778d0..6cb4dd0 100644
--- a/src/test/java/com/android/tools/r8/desugar/DefaultMethodWithAccessTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/DefaultMethodWithAccessTest.java
@@ -51,7 +51,7 @@
             .transformMethodInsnInMethod(
                 "access",
                 (opcode, owner, name, descriptor, isInterface, continuation) -> {
-                  continuation.apply(
+                  continuation.visitMethodInsn(
                       name.equals("print") ? Opcodes.INVOKESPECIAL : opcode,
                       owner,
                       name,
diff --git a/src/test/java/com/android/tools/r8/desugar/PrivateMethodsInInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/PrivateMethodsInInterfaceTest.java
index 564f831..66fbdaa 100644
--- a/src/test/java/com/android/tools/r8/desugar/PrivateMethodsInInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/PrivateMethodsInInterfaceTest.java
@@ -47,7 +47,7 @@
         .transformMethodInsnInMethod(
             "foo",
             ((opcode, owner, name, descriptor, isInterface, continuation) -> {
-              continuation.apply(
+              continuation.visitMethodInsn(
                   name.equals("bar") ? Opcodes.INVOKESPECIAL : opcode,
                   owner,
                   name,
@@ -57,7 +57,7 @@
         .transformMethodInsnInMethod(
             "baz",
             ((opcode, owner, name, descriptor, isInterface, continuation) -> {
-              continuation.apply(
+              continuation.visitMethodInsn(
                   name.equals("bar") ? Opcodes.INVOKESPECIAL : opcode,
                   owner,
                   name,
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
index a8c5c6f..e2474ca 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/DefaultInterfaceMethodDesugaringWithStaticResolutionInvokeVirtualTest.java
@@ -64,14 +64,14 @@
                 (opcode, owner, name, descriptor, isInterface, continuation) -> {
                   if (invalidInvoke && opcode == Opcodes.INVOKEVIRTUAL) {
                     assertEquals("m", name);
-                    continuation.apply(
+                    continuation.visitMethodInsn(
                         opcode,
                         DescriptorUtils.getBinaryNameFromJavaType(C.class.getTypeName()),
                         name,
                         descriptor,
                         isInterface);
                   } else {
-                    continuation.apply(opcode, owner, name, descriptor, isInterface);
+                    continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
                   }
                 })
             .transform());
diff --git a/src/test/java/com/android/tools/r8/graph/InvokeFinalTest.java b/src/test/java/com/android/tools/r8/graph/InvokeFinalTest.java
index f72a98f..54f2fa4 100644
--- a/src/test/java/com/android/tools/r8/graph/InvokeFinalTest.java
+++ b/src/test/java/com/android/tools/r8/graph/InvokeFinalTest.java
@@ -63,7 +63,7 @@
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               // The super call to bar() is already INVOKESPECIAL.
               assertTrue(name.equals("foo") || opcode == INVOKESPECIAL);
-              continuation.apply(INVOKESPECIAL, owner, name, descriptor, isInterface);
+              continuation.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, isInterface);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForInvokeVirtualTest.java
index 283f479..eaf7d56 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForInvokeVirtualTest.java
@@ -51,7 +51,7 @@
             "bar",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               assertEquals(INVOKEVIRTUAL, opcode);
-              continuation.apply(INVOKESPECIAL, owner, name, descriptor, isInterface);
+              continuation.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, isInterface);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForNonDeclaredInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForNonDeclaredInvokeVirtualTest.java
index 1477df4..9b9a8eb 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForNonDeclaredInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialForNonDeclaredInvokeVirtualTest.java
@@ -51,7 +51,7 @@
             "bar",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               assertEquals(INVOKEVIRTUAL, opcode);
-              continuation.apply(INVOKESPECIAL, owner, name, descriptor, isInterface);
+              continuation.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, isInterface);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceTest.java
index 24ae2fc..7a51803 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceTest.java
@@ -63,7 +63,7 @@
             "bar",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               assertEquals(INVOKEVIRTUAL, opcode);
-              continuation.apply(INVOKESPECIAL, owner, name, descriptor, isInterface);
+              continuation.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, isInterface);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceWithBridgeTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceWithBridgeTest.java
index 647881d..3536adb 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceWithBridgeTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialInterfaceWithBridgeTest.java
@@ -53,7 +53,7 @@
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               assertEquals(INVOKEVIRTUAL, opcode);
               assertEquals(owner, DescriptorUtils.getBinaryNameFromJavaType(B.class.getTypeName()));
-              continuation.apply(INVOKESPECIAL, owner, name, descriptor, isInterface);
+              continuation.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, isInterface);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialMissingInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialMissingInvokeVirtualTest.java
index 5343c5a..93a94e9 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialMissingInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialMissingInvokeVirtualTest.java
@@ -54,7 +54,7 @@
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               assertEquals(INVOKEVIRTUAL, opcode);
               assertEquals("notify", name);
-              continuation.apply(
+              continuation.visitMethodInsn(
                   INVOKESPECIAL,
                   DescriptorUtils.getBinaryNameFromJavaType(A.class.getTypeName()),
                   "foo",
diff --git a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnSameClassTest.java b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnSameClassTest.java
index 7fae808..5bc6d22 100644
--- a/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnSameClassTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokespecial/InvokeSpecialOnSameClassTest.java
@@ -56,7 +56,7 @@
         .transformMethodInsnInMethod(
             "bar",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
-              continuation.apply(INVOKESPECIAL, owner, name, descriptor, isInterface);
+              continuation.visitMethodInsn(INVOKESPECIAL, owner, name, descriptor, isInterface);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/graph/invokestatic/InvokeStaticOnInterfaceTest.java b/src/test/java/com/android/tools/r8/graph/invokestatic/InvokeStaticOnInterfaceTest.java
index ecdaa6f..090844e 100644
--- a/src/test/java/com/android/tools/r8/graph/invokestatic/InvokeStaticOnInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/graph/invokestatic/InvokeStaticOnInterfaceTest.java
@@ -99,7 +99,7 @@
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               assertEquals(INVOKESTATIC, opcode);
               assertTrue(isInterface);
-              continuation.apply(opcode, owner, name, descriptor, false);
+              continuation.visitMethodInsn(opcode, owner, name, descriptor, false);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/callsites/CallSiteOptimizationWithInvokeCustomTargetTest.java b/src/test/java/com/android/tools/r8/ir/optimize/callsites/CallSiteOptimizationWithInvokeCustomTargetTest.java
index 059cf8d..1a2d667 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/callsites/CallSiteOptimizationWithInvokeCustomTargetTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/callsites/CallSiteOptimizationWithInvokeCustomTargetTest.java
@@ -13,7 +13,6 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.transformers.MethodTransformer;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.google.common.collect.ImmutableList;
@@ -79,28 +78,21 @@
   private List<byte[]> getProgramClassFileData() throws Exception {
     return ImmutableList.of(
         transformer(TestClass.class)
-            .addMethodTransformer(
-                new MethodTransformer() {
-                  @Override
-                  public void visitMethodInsn(
-                      int opcode,
-                      String owner,
-                      String name,
-                      String descriptor,
-                      boolean isInterface) {
-                    if (opcode == Opcodes.INVOKESTATIC && name.equals("foo")) {
-                      visitInvokeDynamicInsn(
-                          "foo",
-                          "(I)V",
-                          new Handle(
-                              Opcodes.H_INVOKESTATIC,
-                              binaryName(TestClass.class),
-                              "bootstrap",
-                              "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
-                              false));
-                    } else {
-                      super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
-                    }
+            .transformMethodInsnInMethod(
+                "main",
+                (opcode, owner, name, descriptor, isInterface, visitor) -> {
+                  if (opcode == Opcodes.INVOKESTATIC && name.equals("foo")) {
+                    visitor.visitInvokeDynamicInsn(
+                        "foo",
+                        "(I)V",
+                        new Handle(
+                            Opcodes.H_INVOKESTATIC,
+                            binaryName(TestClass.class),
+                            "bootstrap",
+                            "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
+                            false));
+                  } else {
+                    visitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
                   }
                 })
             .transform());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
index 15e37c1..5874af4 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
@@ -82,7 +82,7 @@
                   type.equals(TEMPLATE_CODE_EXCEPTION_BINARY_NAME)
                       ? getExceptionBinaryName()
                       : type;
-              continuation.apply(start, end, handler, newType);
+              continuation.visitTryCatchBlock(start, end, handler, newType);
             })
         .transform();
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java b/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java
index 1314274..0031ca2 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/logging/AndroidLogRemovalTest.java
@@ -51,7 +51,7 @@
                 .transformMethodInsnInMethod(
                     "main",
                     (opcode, owner, name, descriptor, isInterface, continuation) ->
-                        continuation.apply(
+                        continuation.visitMethodInsn(
                             opcode,
                             owner.endsWith("$Log") ? "android/util/Log" : owner,
                             name,
diff --git a/src/test/java/com/android/tools/r8/resolution/InvokeInterfaceOnClassTest.java b/src/test/java/com/android/tools/r8/resolution/InvokeInterfaceOnClassTest.java
index c9d94ad..84a91ca 100644
--- a/src/test/java/com/android/tools/r8/resolution/InvokeInterfaceOnClassTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/InvokeInterfaceOnClassTest.java
@@ -108,14 +108,16 @@
   private static byte[] transformMain() throws Exception {
     String binaryNameForI = Reference.classFromClass(I.class).getBinaryName();
     return transformer(Main.class)
-        .transformMethodInsnInMethod("main",
+        .transformMethodInsnInMethod(
+            "main",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (owner.equals(binaryNameForI) && name.equals("f")) {
                 assertEquals(Opcodes.INVOKEVIRTUAL, opcode);
                 assertFalse(isInterface);
-                continuation.apply(Opcodes.INVOKEINTERFACE, owner, name, descriptor, true);
+                continuation.visitMethodInsn(
+                    Opcodes.INVOKEINTERFACE, owner, name, descriptor, true);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java b/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java
index 8fccb56..bade483 100644
--- a/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/InvokeSuperCallInStaticTest.java
@@ -97,7 +97,7 @@
         .transformMethodInsnInMethod(
             "callSuper",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
-              continuation.apply(
+              continuation.visitMethodInsn(
                   INVOKESPECIAL,
                   DescriptorUtils.getBinaryNameFromJavaType(Base.class.getTypeName()),
                   name,
diff --git a/src/test/java/com/android/tools/r8/resolution/InvokeVirtualOnInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/InvokeVirtualOnInterfaceTest.java
index d0a4906..3f2fc61 100644
--- a/src/test/java/com/android/tools/r8/resolution/InvokeVirtualOnInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/InvokeVirtualOnInterfaceTest.java
@@ -115,9 +115,9 @@
               if (owner.equals(binaryNameForI) && name.equals("f")) {
                 assertEquals(INVOKEINTERFACE, opcode);
                 assertTrue(isInterface);
-                continuation.apply(INVOKEVIRTUAL, owner, name, descriptor, false);
+                continuation.visitMethodInsn(INVOKEVIRTUAL, owner, name, descriptor, false);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java b/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java
index 543ecad..c0f46b5 100644
--- a/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/PrivateInvokeVirtualTest.java
@@ -85,9 +85,10 @@
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (name.contains("compareToHelper")) {
                 assertEquals(Opcodes.INVOKESPECIAL, opcode);
-                continuation.apply(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(
+                    Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
index 18cbb66..4fbe946 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
@@ -85,7 +85,7 @@
                           ? DescriptorUtils.getBinaryNameFromJavaType(I.class.getName())
                           : DescriptorUtils.getBinaryNameFromJavaType(A.class.getName());
                   boolean newIsInterface = symbolicReferenceIsDefiningType;
-                  continuation.apply(
+                  continuation.visitMethodInsn(
                       Opcodes.INVOKESPECIAL, newOwner, name, descriptor, newIsInterface);
                 })
             .transform());
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java
index bae2756..a25f3c6 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessWithIntermediateTest.java
@@ -83,7 +83,8 @@
                       symbolicReferenceIsDefiningType
                           ? DescriptorUtils.getBinaryNameFromJavaType(I.class.getName())
                           : DescriptorUtils.getBinaryNameFromJavaType(J.class.getName());
-                  continuation.apply(Opcodes.INVOKESPECIAL, newOwner, name, descriptor, true);
+                  continuation.visitMethodInsn(
+                      Opcodes.INVOKESPECIAL, newOwner, name, descriptor, true);
                 })
             .transform());
   }
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
index 79e8f76..68b2a16 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
@@ -86,7 +86,7 @@
                       symbolicReferenceIsDefiningType
                           ? DescriptorUtils.getBinaryNameFromJavaType(A.class.getName())
                           : DescriptorUtils.getBinaryNameFromJavaType(B.class.getName());
-                  continuation.apply(opcode, newOwner, name, descriptor, isInterface);
+                  continuation.visitMethodInsn(opcode, newOwner, name, descriptor, isInterface);
                 })
             .transform());
   }
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
index 06f7e8d..9a17065 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
@@ -132,7 +132,7 @@
         .transformMethodInsnInMethod(
             "callClInit",
             (opcode, owner, name, descriptor, isInterface, continuation) ->
-                continuation.apply(opcode, owner, "<clinit>", descriptor, isInterface))
+                continuation.visitMethodInsn(opcode, owner, "<clinit>", descriptor, isInterface))
         .transform();
   }
 
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
index c8fad67..81ed494 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
@@ -94,14 +94,14 @@
             "callFooBar",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (name.equals("notify")) {
-                continuation.apply(
+                continuation.visitMethodInsn(
                     INVOKEINTERFACE,
                     DescriptorUtils.getBinaryNameFromJavaType(I.class.getTypeName()),
                     "bar",
                     descriptor,
                     true);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java
index d909591..d8f8c4a 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvalidResolutionToThisTarget.java
@@ -102,14 +102,14 @@
             "main",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (name.equals("foo")) {
-                continuation.apply(
+                continuation.visitMethodInsn(
                     opcode,
                     DescriptorUtils.getBinaryNameFromJavaType(A.class.getTypeName()),
                     name,
                     descriptor,
                     isInterface);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java
index 03425c6..cc85bbc 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PackagePrivateFinalOverrideTest.java
@@ -209,14 +209,14 @@
             "main",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (name.equals("clear")) {
-                continuation.apply(
+                continuation.visitMethodInsn(
                     opcode,
                     DescriptorUtils.getBinaryNameFromJavaType(ViewModel.class.getTypeName()),
                     name,
                     descriptor,
                     isInterface);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
@@ -230,9 +230,9 @@
             "run",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (name.equals("clearBridge")) {
-                continuation.apply(opcode, owner, "clear", descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, "clear", descriptor, isInterface);
               } else {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java
index 645fb55..949cfa0 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/PrivateOverrideOfVirtualTargetTest.java
@@ -102,11 +102,11 @@
             "callOnB",
             (opcode, owner, name, descriptor, isInterface, continuation) -> {
               if (name.equals("foo")) {
-                continuation.apply(opcode, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
                 return;
               }
               if (modifyOwner.get()) {
-                continuation.apply(
+                continuation.visitMethodInsn(
                     Opcodes.INVOKEVIRTUAL,
                     DescriptorUtils.getBinaryNameFromJavaType(A.class.getTypeName()),
                     name,
@@ -114,7 +114,8 @@
                     isInterface);
                 modifyOwner.set(false);
               } else {
-                continuation.apply(Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
+                continuation.visitMethodInsn(
+                    Opcodes.INVOKEVIRTUAL, owner, name, descriptor, isInterface);
               }
             })
         .transform();
diff --git a/src/test/java/com/android/tools/r8/shaking/B149831282.java b/src/test/java/com/android/tools/r8/shaking/B149831282.java
index 910d44b..97441cc 100644
--- a/src/test/java/com/android/tools/r8/shaking/B149831282.java
+++ b/src/test/java/com/android/tools/r8/shaking/B149831282.java
@@ -63,13 +63,14 @@
                     "main",
                     (opcode, type, continuation) -> {
                       assertEquals(binaryName(C.class), type);
-                      continuation.apply(opcode, "b149831282/C");
+                      continuation.visitTypeInsn(opcode, "b149831282/C");
                     })
                 .transformMethodInsnInMethod(
                     "main",
                     (opcode, owner, name, descriptor, isInterface, continuation) -> {
                       assertEquals(binaryName(C.class), owner);
-                      continuation.apply(opcode, "b149831282/C", name, descriptor, isInterface);
+                      continuation.visitMethodInsn(
+                          opcode, "b149831282/C", name, descriptor, isInterface);
                     })
                 .transform())
         .addProgramClassFileData(
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index b2e0060..3f1ad69 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -434,7 +434,7 @@
         });
   }
 
-  /** Abstraction of the MethodVisitor.visitMethodInsn method with its continuation. */
+  /** Abstraction of the MethodVisitor.visitMethodInsn method with its sub visitor. */
   @FunctionalInterface
   public interface MethodInsnTransform {
     void visitMethodInsn(
@@ -443,40 +443,26 @@
         String name,
         String descriptor,
         boolean isInterface,
-        MethodInsnTransformContinuation continuation);
+        MethodVisitor visitor);
   }
 
-  /** Continuation for transforming a method. Will continue with the super visitor if called. */
-  @FunctionalInterface
-  public interface MethodInsnTransformContinuation {
-    void apply(int opcode, String owner, String name, String descriptor, boolean isInterface);
-  }
-
-  /** Abstraction of the MethodVisitor.visitTypeInsn method with its continuation. */
+  /** Abstraction of the MethodVisitor.visitTypeInsn method with its sub visitor. */
   @FunctionalInterface
   public interface TypeInsnTransform {
-    void visitTypeInsn(int opcode, String type, TypeInsnTransformContinuation continuation);
+    void visitTypeInsn(int opcode, String type, MethodVisitor visitor);
   }
 
-  /** Continuation for transforming a method. Will continue with the super visitor if called. */
+  /** Abstraction of the MethodVisitor.visitLdcInsn method with its sub visitor. */
   @FunctionalInterface
-  public interface TypeInsnTransformContinuation {
-    void apply(int opcode, String type);
+  public interface LdcInsnTransform {
+    void visitLdcInsn(Object value, MethodVisitor visitor);
   }
 
+  /** Abstraction of the MethodVisitor.visitTryCatchBlock method with its sub visitor. */
   @FunctionalInterface
   public interface TryCatchBlockTransform {
     void visitTryCatchBlock(
-        Label start,
-        Label end,
-        Label handler,
-        String type,
-        TryCatchBlockTransformContinuation continuation);
-  }
-
-  @FunctionalInterface
-  public interface TryCatchBlockTransformContinuation {
-    void apply(Label start, Label end, Label handler, String type);
+        Label start, Label end, Label handler, String type, MethodVisitor visitor);
   }
 
   public ClassFileTransformer replaceAnnotationDescriptor(
@@ -540,6 +526,23 @@
         });
   }
 
+  @FunctionalInterface
+  private interface VisitMethodInsnCallback {
+    void visitMethodInsn(
+        int opcode, String owner, String name, String descriptor, boolean isInterface);
+  }
+
+  private MethodVisitor redirectVisitMethodInsn(
+      MethodVisitor visitor, VisitMethodInsnCallback callback) {
+    return new MethodVisitor(ASM7, visitor) {
+      @Override
+      public void visitMethodInsn(
+          int opcode, String owner, String name, String descriptor, boolean isInterface) {
+        callback.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
+      }
+    };
+  }
+
   public ClassFileTransformer transformMethodInsnInMethod(
       String methodName, MethodInsnTransform transform) {
     return addMethodTransformer(
@@ -549,7 +552,12 @@
               int opcode, String owner, String name, String descriptor, boolean isInterface) {
             if (getContext().method.getMethodName().equals(methodName)) {
               transform.visitMethodInsn(
-                  opcode, owner, name, descriptor, isInterface, super::visitMethodInsn);
+                  opcode,
+                  owner,
+                  name,
+                  descriptor,
+                  isInterface,
+                  redirectVisitMethodInsn(this, super::visitMethodInsn));
             } else {
               super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
             }
@@ -557,6 +565,21 @@
         });
   }
 
+  @FunctionalInterface
+  private interface VisitTypeInsnCallback {
+    void visitTypeInsn(int opcode, String type);
+  }
+
+  private MethodVisitor redirectVisitTypeInsn(
+      MethodVisitor visitor, VisitTypeInsnCallback callback) {
+    return new MethodVisitor(ASM7, visitor) {
+      @Override
+      public void visitTypeInsn(int opcode, String type) {
+        callback.visitTypeInsn(opcode, type);
+      }
+    };
+  }
+
   public ClassFileTransformer transformTypeInsnInMethod(
       String methodName, TypeInsnTransform transform) {
     return addMethodTransformer(
@@ -564,7 +587,8 @@
           @Override
           public void visitTypeInsn(int opcode, String type) {
             if (getContext().method.getMethodName().equals(methodName)) {
-              transform.visitTypeInsn(opcode, type, super::visitTypeInsn);
+              transform.visitTypeInsn(
+                  opcode, type, redirectVisitTypeInsn(this, super::visitTypeInsn));
             } else {
               super.visitTypeInsn(opcode, type);
             }
@@ -572,6 +596,21 @@
         });
   }
 
+  @FunctionalInterface
+  private interface VisitTryCatchBlockCallback {
+    void visitTryCatchBlock(Label start, Label end, Label handler, String type);
+  }
+
+  private MethodVisitor redirectVistiTryCatchBlock(
+      MethodVisitor visitor, VisitTryCatchBlockCallback callback) {
+    return new MethodVisitor(ASM7, visitor) {
+      @Override
+      public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+        callback.visitTryCatchBlock(start, end, handler, type);
+      }
+    };
+  }
+
   public ClassFileTransformer transformTryCatchBlock(
       String methodName, TryCatchBlockTransform transform) {
     return addMethodTransformer(
@@ -579,7 +618,12 @@
           @Override
           public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
             if (getContext().method.getMethodName().equals(methodName)) {
-              transform.visitTryCatchBlock(start, end, handler, type, super::visitTryCatchBlock);
+              transform.visitTryCatchBlock(
+                  start,
+                  end,
+                  handler,
+                  type,
+                  redirectVistiTryCatchBlock(this, super::visitTryCatchBlock));
             } else {
               super.visitTryCatchBlock(start, end, handler, type);
             }
@@ -587,16 +631,18 @@
         });
   }
 
-  /** Abstraction of the MethodVisitor.visitLdcInsn method with its continuation. */
   @FunctionalInterface
-  public interface LdcInsnTransform {
-    void visitLdcInsn(Object value, LdcInsnTransformContinuation continuation);
+  private interface VisitLdcInsnCallback {
+    void visitLdcInsn(Object value);
   }
 
-  /** Continuation for transforming a method. Will continue with the super visitor if called. */
-  @FunctionalInterface
-  public interface LdcInsnTransformContinuation {
-    void apply(Object value);
+  private MethodVisitor redirectVisitLdcInsn(MethodVisitor visitor, VisitLdcInsnCallback callback) {
+    return new MethodVisitor(ASM7, visitor) {
+      @Override
+      public void visitLdcInsn(Object value) {
+        callback.visitLdcInsn(value);
+      }
+    };
   }
 
   public ClassFileTransformer transformLdcInsnInMethod(
@@ -606,7 +652,7 @@
           @Override
           public void visitLdcInsn(Object value) {
             if (getContext().method.getMethodName().equals(methodName)) {
-              transform.visitLdcInsn(value, super::visitLdcInsn);
+              transform.visitLdcInsn(value, redirectVisitLdcInsn(this, super::visitLdcInsn));
             } else {
               super.visitLdcInsn(value);
             }