Merge "Ensure that we close input streams to not leak resources"
diff --git a/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
index 450e6d0..55ec4f1 100644
--- a/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
+++ b/src/test/java/com/android/tools/r8/cf/IdenticalCatchHandlerTest.java
@@ -63,7 +63,7 @@
   }
 
   private int countCatchHandlers(AndroidApp inputApp) throws Exception {
-    CodeInspector inspector = new CodeInspector(inputApp, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(inputApp);
     DexClass dexClass = inspector.clazz(TestClass.class).getDexClass();
     Code code = dexClass.virtualMethods()[0].getCode();
     if (code.isCfCode()) {
diff --git a/src/test/java/com/android/tools/r8/cf/LambdaTestRunner.java b/src/test/java/com/android/tools/r8/cf/LambdaTestRunner.java
index 7db1d61..632d0b9 100644
--- a/src/test/java/com/android/tools/r8/cf/LambdaTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/LambdaTestRunner.java
@@ -69,7 +69,7 @@
 
   private static CfInvokeDynamic findFirstInMethod(AndroidApp app) throws Exception {
     String returnType = "void";
-    CodeInspector inspector = new CodeInspector(app, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(app);
     List<String> args = Collections.singletonList(String[].class.getTypeName());
     DexEncodedMethod method = inspector.clazz(CLASS).method(returnType, METHOD, args).getMethod();
     CfCode code = method.getCode().asCfCode();
diff --git a/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java b/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java
index e4f9249..84ac87c 100644
--- a/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/SynchronizedNoopTestRunner.java
@@ -11,18 +11,16 @@
 import com.android.tools.r8.R8;
 import com.android.tools.r8.R8Command;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfMonitor;
+import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.JarCode;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidAppConsumers;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import org.junit.Test;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.InsnList;
-import org.objectweb.asm.tree.MethodNode;
 
 public class SynchronizedNoopTestRunner {
   private byte[] data;
@@ -40,21 +38,9 @@
     CodeInspector inspector = new CodeInspector(a.build());
     DexEncodedMethod method =
         inspector.clazz(CLASS).method("void", "noop", Collections.emptyList()).getMethod();
-    ArrayList<AbstractInsnNode> insns = new ArrayList<>();
-    JarCode jarCode = method.getCode().asJarCode();
-    MethodNode node = jarCode.getNode();
-    assert node != null;
-    InsnList asmInsns = node.instructions;
-    for (int i = 0; i < asmInsns.size(); i++) {
-      insns.add(asmInsns.get(i));
-    }
-    boolean hasMonitor =
-        insns
-            .stream()
-            .anyMatch(
-                insn ->
-                    insn.getOpcode() == Opcodes.MONITORENTER
-                        || insn.getOpcode() == Opcodes.MONITOREXIT);
+    CfCode cfCode = method.getCode().asCfCode();
+    List<CfInstruction> insns = cfCode.getInstructions();
+    boolean hasMonitor = insns.stream().anyMatch(insn -> insn instanceof CfMonitor);
     assertFalse(hasMonitor);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 6322840..2a56ef5 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -866,8 +866,8 @@
     MethodSubject method = clazz.method("void", "main", ImmutableList.of("java.lang.String[]"));
     assertThat(method, isPresent());
     assertThat(
-        method.getMethod().getCode().asJarCode().toString(),
-        containsString("INVOKEINTERFACE classmerging/MergeDefaultMethodIntoClassTest$A.f"));
+        method.getMethod().getCode().asCfCode().toString(),
+        containsString("invokeinterface classmerging.MergeDefaultMethodIntoClassTest$A.f()V"));
 
     runTestOnInput(main, app, preservedClassNames::contains, getProguardConfig(JAVA8_EXAMPLE_KEEP));
   }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
index e727904..d5b88cb 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/MemberValuePropagationTest.java
@@ -62,7 +62,7 @@
   @Test
   public void testWriteOnlyField_putObject_gone() throws Exception {
     List<Path> processedApp = runR8(EXAMPLE_KEEP);
-    CodeInspector inspector = new CodeInspector(processedApp, null, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(processedApp);
     ClassSubject clazz = inspector.clazz(QUALIFIED_CLASS_NAME);
     clazz.forAllMethods(
         methodSubject -> {
@@ -77,7 +77,7 @@
   @Test
   public void testWriteOnlyField_dontoptimize() throws Exception {
     List<Path> processedApp = runR8(DONT_OPTIMIZE);
-    CodeInspector inspector = new CodeInspector(processedApp, null, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(processedApp);
     ClassSubject clazz = inspector.clazz(QUALIFIED_CLASS_NAME);
     assert backend == Backend.DEX || backend == Backend.CF;
     clazz.forAllMethods(
diff --git a/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java b/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java
index 6290e20..27a7ed6 100644
--- a/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java
+++ b/src/test/java/com/android/tools/r8/jasmin/Regress65432240.java
@@ -7,17 +7,37 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.code.IfNez;
-import com.android.tools.r8.graph.DexCode;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.jasmin.JasminBuilder.ClassFileVersion;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.codeinspector.CfInstructionSubject;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
 import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
+@RunWith(Parameterized.class)
 public class Regress65432240 extends JasminTestBase {
 
+  private Backend backend;
+
+  @Parameterized.Parameters(name = "Backend: {0}")
+  public static Collection<Backend> data() {
+    return Arrays.asList(Backend.values());
+  }
+
+  public Regress65432240(Backend backend) {
+    this.backend = backend;
+  }
+
   @Test
   public void testConstantNotIntoEntryBlock() throws Exception {
     JasminBuilder builder = new JasminBuilder(ClassFileVersion.JDK_1_4);
@@ -58,13 +78,37 @@
     String expected = runOnJava(builder, clazz.name);
 
     AndroidApp originalApplication = builder.build();
-    AndroidApp processedApplication = ToolHelper.runR8(originalApplication);
+    AndroidApp processedApplication =
+        ToolHelper.runR8(
+            ToolHelper.prepareR8CommandBuilder(originalApplication, emptyConsumer(backend))
+                .addLibraryFiles(runtimeJar(backend))
+                .build());
 
-    DexEncodedMethod method = getMethod(processedApplication, clazz.name, signature);
-    DexCode code = method.getCode().asDexCode();
-    assertTrue(code.instructions[0] instanceof IfNez);
+    CodeInspector inspector =
+        new CodeInspector(processedApplication, o -> o.enableCfFrontend = true);
+    ClassSubject inspectedClass = inspector.clazz(clazz.name);
+    MethodSubject method = inspectedClass.method(signature);
+    assertTrue(method.isPresent());
+    Iterator<InstructionSubject> iterator = method.iterateInstructions();
+    InstructionSubject instruction = null;
+    boolean found = false;
+    while (iterator.hasNext()) {
+      instruction = iterator.next();
+      if (!(instruction instanceof CfInstructionSubject)
+          || !((CfInstructionSubject) instruction).isLoad()) {
+        found = true;
+        break;
+      }
+    }
+    assertTrue(found && instruction.isIfNez());
 
-    String artResult = runOnArtR8(builder, clazz.name);
-    assertEquals(expected, artResult);
+    String result;
+    if (backend == Backend.DEX) {
+      result = runOnArt(processedApplication, clazz.name);
+    } else {
+      assert backend == Backend.CF;
+      result = runOnJava(processedApplication, clazz.name, Collections.emptyList());
+    }
+    assertEquals(expected, result);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java b/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java
index 4903304..517bd03 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/CompositionalLenseTest.java
@@ -93,7 +93,7 @@
       options.enableInlining = false;
       options.enableClassMerging = false;
     });
-    CodeInspector codeInspector = new CodeInspector(processedApp, o -> o.enableCfFrontend = true);
+    CodeInspector codeInspector = new CodeInspector(processedApp);
     ClassSubject classSubject = codeInspector.clazz(TestMain.class);
     assertThat(classSubject, isPresent());
     MethodSubject methodSubject = classSubject.method(CodeInspector.MAIN);
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
index bf63d70..6fccb9a 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
@@ -388,7 +388,7 @@
       originalInspection.accept(inspector);
     }
 
-    CodeInspector inspector = new CodeInspector(processed, null, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(processed);
     inspection.accept(inspector);
 
     // We don't run Art, as the test R8RunExamplesTest already does that.
diff --git a/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java b/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java
index 6dd02c6..a66c222 100644
--- a/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java
+++ b/src/test/java/com/android/tools/r8/movestringconstants/MoveStringConstantsTest.java
@@ -62,12 +62,7 @@
               // setting (5) is just too small.
               options.inliningInstructionLimit = 10;
             });
-    inspection.accept(
-        new CodeInspector(
-            app,
-            options -> {
-              options.enableCfFrontend = true;
-            }));
+    inspection.accept(new CodeInspector(app));
 
     if (backend == Backend.DEX) {
       // Run on Art to check generated code against verifier.
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index aaecd58..ee25918 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -213,11 +213,7 @@
 
   private static CodeInspector createDexInspector(AndroidApp outputApp)
       throws IOException, ExecutionException {
-    return new CodeInspector(
-        outputApp,
-        o -> {
-          o.enableCfFrontend = true;
-        });
+    return new CodeInspector(outputApp);
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
index 73cdaaf..ba7d491 100644
--- a/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
+++ b/src/test/java/com/android/tools/r8/naming/IdentifierMinifierTest.java
@@ -17,8 +17,8 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
-import com.android.tools.r8.utils.codeinspector.ConstStringInstructionSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.ConstStringInstructionSubject;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
@@ -89,12 +89,7 @@
 
   @Test
   public void identiferMinifierTest() throws Exception {
-    CodeInspector codeInspector =
-        new CodeInspector(
-            processedApp,
-            options -> {
-              options.enableCfFrontend = true;
-            });
+    CodeInspector codeInspector = new CodeInspector(processedApp);
     inspection.accept(codeInspector);
   }
 
diff --git a/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java b/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
index f401f6a..e6589d5a 100644
--- a/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
+++ b/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
@@ -72,13 +72,7 @@
         Origin.unknown());
     AndroidApp app =
         ToolHelper.runR8(builder.build(), opts -> opts.enableClassInlining = enableClassInliner);
-    inspection.accept(
-        new CodeInspector(
-            app,
-            options -> {
-              options.enableCfFrontend = true;
-            }),
-        mode);
+    inspection.accept(new CodeInspector(app), mode);
 
     if (backend == Backend.DEX) {
       // Run on Art to check generated code against verifier.
diff --git a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
index 911ceb7..a09b9a4 100644
--- a/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
+++ b/src/test/java/com/android/tools/r8/regress/b69825683/Regress69825683Test.java
@@ -59,7 +59,7 @@
           .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
     }
     AndroidApp app = ToolHelper.runR8(builder.build(), o -> o.enableClassInlining = false);
-    CodeInspector inspector = new CodeInspector(app, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(app);
     List<FoundClassSubject> classes = inspector.allClasses();
 
     // Check that the synthetic class is still present.
@@ -103,7 +103,7 @@
           .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
     }
     AndroidApp app = ToolHelper.runR8(builder.build(), o -> o.enableClassInlining = false);
-    CodeInspector inspector = new CodeInspector(app, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(app);
     List<FoundClassSubject> classes = inspector.allClasses();
 
     // Check that the synthetic class is still present.
diff --git a/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java b/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
index ee99b38..bfc8154 100644
--- a/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
+++ b/src/test/java/com/android/tools/r8/rewrite/switchmaps/RewriteSwitchMapsTest.java
@@ -61,7 +61,7 @@
             .setProgramConsumer(emptyConsumer(backend))
             .build();
     AndroidApp result = ToolHelper.runR8(command);
-    CodeInspector inspector = new CodeInspector(result, o -> o.enableCfFrontend = true);
+    CodeInspector inspector = new CodeInspector(result);
     Assert.assertFalse(inspector.clazz(SWITCHMAP_CLASS_NAME).isPresent());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java b/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
index b3e6367..004acc1 100644
--- a/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/proxy/ProxiesTest.java
@@ -78,7 +78,7 @@
           .addLibraryFiles(ToolHelper.getJava8RuntimeJar());
     }
     AndroidApp app = ToolHelper.runR8(builder.build(), o -> o.enableDevirtualization = false);
-    inspection.accept(new CodeInspector(app, o -> o.enableCfFrontend = true));
+    inspection.accept(new CodeInspector(app));
     String result = backend == Backend.DEX ? runOnArt(app, mainClass) : runOnJava(app, mainClass);
     if (ToolHelper.isWindows()) {
       result = result.replace(System.lineSeparator(), "\n");
diff --git a/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java b/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
index d12f41a..f37d6c6 100644
--- a/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/testrules/ForceInlineTest.java
@@ -61,7 +61,7 @@
             .addLibraryFiles(library);
     ToolHelper.allowTestProguardOptions(builder);
     builder.addProguardConfiguration(proguardConfiguration, Origin.unknown());
-    return new CodeInspector(ToolHelper.runR8(builder.build(), o -> o.enableCfFrontend = true));
+    return new CodeInspector(ToolHelper.runR8(builder.build()));
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
index 6aa54df..f639e87 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
@@ -13,6 +13,7 @@
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.cf.code.CfInvokeDynamic;
 import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfLoad;
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.cf.code.CfNop;
 import com.android.tools.r8.cf.code.CfPosition;
@@ -155,4 +156,8 @@
   public boolean isIfNull() {
     return instruction instanceof CfIf && ((CfIf) instruction).getOpcode() == Opcodes.IFNULL;
   }
+
+  public boolean isLoad() {
+    return instruction instanceof CfLoad;
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 6fbbb20..bc31615 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -79,6 +79,7 @@
     }
     Timing timing = new Timing("CodeInspector");
     InternalOptions options = new InternalOptions();
+    options.enableCfFrontend = true;
     if (optionsConsumer != null) {
       optionsConsumer.accept(options);
     }
@@ -89,7 +90,7 @@
 
   public CodeInspector(AndroidApp app) throws IOException, ExecutionException {
     this(
-        new ApplicationReader(app, new InternalOptions(), new Timing("CodeInspector"))
+        new ApplicationReader(app, runOptionsConsumer(null), new Timing("CodeInspector"))
             .read(app.getProguardMapOutputData()));
   }
 
@@ -102,13 +103,16 @@
 
   private static InternalOptions runOptionsConsumer(Consumer<InternalOptions> optionsConsumer) {
     InternalOptions internalOptions = new InternalOptions();
-    optionsConsumer.accept(internalOptions);
+    internalOptions.enableCfFrontend = true;
+    if (optionsConsumer != null) {
+      optionsConsumer.accept(internalOptions);
+    }
     return internalOptions;
   }
 
   public CodeInspector(AndroidApp app, Path proguardMap) throws IOException, ExecutionException {
     this(
-        new ApplicationReader(app, new InternalOptions(), new Timing("CodeInspector"))
+        new ApplicationReader(app, runOptionsConsumer(null), new Timing("CodeInspector"))
             .read(StringResource.fromFile(proguardMap)));
   }