Merge "Update NonVirtualOverrideTest to enable compiling a testJar with R8"
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
index 2588070..51dc435 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryProvidedProguardRulesTest.java
@@ -50,28 +50,26 @@
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
 
-class A {
-  private static String buildClassName(String className) {
-    return A.class.getPackage().getName() + "." + className;
-  }
-
-  public static void main(String[] args) {
-    try {
-      Class bClass = Class.forName(buildClassName("B"));
-      System.out.println("YES");
-    } catch (ClassNotFoundException e) {
-      System.out.println("NO");
-    }
-  }
-}
-
-class B {
-
-}
-
 @RunWith(Parameterized.class)
 public class LibraryProvidedProguardRulesTest extends TestBase {
 
+  static class A {
+    private static String buildClassName(String className) {
+      return com.android.tools.r8.shaking.A.class.getPackage().getName() + "." + className;
+    }
+
+    public static void main(String[] args) {
+      try {
+        Class bClass = Class.forName(buildClassName("B"));
+        System.out.println("YES");
+      } catch (ClassNotFoundException e) {
+        System.out.println("NO");
+      }
+    }
+  }
+
+  static class B {}
+
   private Backend backend;
 
   @Parameters(name = "Backend: {0}")
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
index b813e6f..287b736 100644
--- a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTest.java
@@ -7,19 +7,19 @@
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
 import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 
 import com.android.tools.r8.ByteDataView;
 import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
+import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.ir.optimize.Inliner.Reason;
-import com.android.tools.r8.jasmin.JasminBuilder;
-import com.android.tools.r8.jasmin.JasminBuilder.ClassBuilder;
-import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -28,118 +28,169 @@
 import com.google.common.collect.ImmutableSet;
 import java.nio.file.Path;
 import java.util.Collection;
+import java.util.Objects;
+import java.util.function.Function;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.BeforeParam;
 
 @RunWith(Parameterized.class)
 public class NonVirtualOverrideTest extends TestBase {
 
-  private static Class<?> main = NonVirtualOverrideTestClass.class;
-  private static Class<?> A = NonVirtualOverrideTestClass.A.class;
-  private static Class<?> B = NonVirtualOverrideTestClass.B.class;
-  private static Class<?> C = NonVirtualOverrideTestClass.C.class;
-
-  private final Backend backend;
+  private final TestParameters parameters;
   private final boolean enableClassInlining;
   private final boolean enableVerticalClassMerging;
 
+  static class Dimensions {
+
+    private final Backend backend;
+    private final boolean enableClassInlining;
+    private final boolean enableVerticalClassMerging;
+
+    public Dimensions(
+        Backend backend, boolean enableClassInlining, boolean enableVerticalClassMerging) {
+      this.backend = backend;
+      this.enableClassInlining = enableClassInlining;
+      this.enableVerticalClassMerging = enableVerticalClassMerging;
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(backend, enableClassInlining, enableVerticalClassMerging);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (!(o instanceof Dimensions)) {
+        return false;
+      }
+      Dimensions other = (Dimensions) o;
+      return this.backend == other.backend
+          && this.enableClassInlining == other.enableClassInlining
+          && this.enableVerticalClassMerging == other.enableVerticalClassMerging;
+    }
+  }
+
   @Parameterized.Parameters(name = "Backend: {0}, class inlining: {1}, vertical class merging: {2}")
   public static Collection<Object[]> data() {
-    return buildParameters(ToolHelper.getBackends(), BooleanUtils.values(), BooleanUtils.values());
+    return buildParameters(
+        getTestParameters().withAllRuntimes().build(),
+        BooleanUtils.values(),
+        BooleanUtils.values());
   }
 
   public NonVirtualOverrideTest(
-      Backend backend, boolean enableClassInlining, boolean enableVerticalClassMerging) {
-    this.backend = backend;
+      TestParameters parameters, boolean enableClassInlining, boolean enableVerticalClassMerging) {
+    this.parameters = parameters;
     this.enableClassInlining = enableClassInlining;
     this.enableVerticalClassMerging = enableVerticalClassMerging;
   }
 
-  @Test
-  public void test() throws Exception {
-    // Construct B such that it inherits from A and shadows method A.m() with a private method.
-    JasminBuilder jasminBuilder = new JasminBuilder();
-    ClassBuilder classBuilder = jasminBuilder.addClass(B.getName(), A.getName());
-    classBuilder.addDefaultConstructor();
-    for (String methodName : ImmutableList.of("m1", "m2")) {
-      classBuilder.addPrivateVirtualMethod(
-          methodName, ImmutableList.of(), "V", jasminCodeForPrinting("In B." + methodName + "()"));
-    }
-    for (String methodName : ImmutableList.of("m3", "m4")) {
-      classBuilder.addStaticMethod(
-          methodName, ImmutableList.of(), "V", jasminCodeForPrinting("In B." + methodName + "()"));
-    }
+  @ClassRule public static TemporaryFolder staticTemp = ToolHelper.getTemporaryFolderForTest();
 
-    AndroidApp input =
-        AndroidApp.builder()
-            .addProgramFiles(
-                ToolHelper.getClassFileForTestClass(main),
-                ToolHelper.getClassFileForTestClass(A),
-                ToolHelper.getClassFileForTestClass(C))
-            .addClassProgramData(jasminBuilder.buildClasses())
-            .build();
+  @BeforeParam
+  public static void forceCompilation(
+      TestParameters parameters, boolean enableClassInlining, boolean enableVerticalClassMerging) {
+    expectedResults.apply(isDexVmBetween5_1_1and7_0_0(parameters));
+    compilationResults.apply(
+        new Dimensions(parameters.getBackend(), enableClassInlining, enableVerticalClassMerging));
+  }
 
-    // Run the program using java.
-    String referenceResult;
-    if (backend == Backend.DEX
-        && ToolHelper.getDexVm().getVersion().isOlderThanOrEqual(Version.V7_0_0)
-        && ToolHelper.getDexVm().getVersion().isAtLeast(Version.V5_1_1)) {
-      referenceResult =
-          String.join(
-              System.lineSeparator(),
-              "In A.m1()",
-              "In A.m2()",
-              "In A.m3()",
-              "In A.m4()",
-              "In C.m1()",
-              "In A.m2()",
-              "In C.m3()",
-              "In A.m4()",
-              "In A.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
-              "In A.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
-              "In C.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
-              "In C.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
-              "In C.m1()",
-              "In C.m3()",
-              "");
+  private static Function<Boolean, String> expectedResults =
+      memoizeFunction(NonVirtualOverrideTest::getExpectedResult);
+
+  private static Function<Dimensions, R8TestCompileResult> compilationResults =
+      memoizeFunction(NonVirtualOverrideTest::compile);
+
+  public static String getExpectedResult(boolean isOldVm) throws Exception {
+    if (isOldVm) {
+      return String.join(
+          System.lineSeparator(),
+          "In A.m1()",
+          "In A.m2()",
+          "In A.m3()",
+          "In A.m4()",
+          "In C.m1()",
+          "In A.m2()",
+          "In C.m3()",
+          "In A.m4()",
+          "In A.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
+          "In A.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
+          "In C.m1()", // With Java: Caught IllegalAccessError when calling B.m1()
+          "In C.m3()", // With Java: Caught IncompatibleClassChangeError when calling B.m3()
+          "In C.m1()",
+          "In C.m3()",
+          "");
     } else {
-      Path referenceJar = temp.getRoot().toPath().resolve("input.jar");
+      Path referenceJar = staticTemp.getRoot().toPath().resolve("input.jar");
       ArchiveConsumer inputConsumer = new ArchiveConsumer(referenceJar);
-      for (Class<?> clazz : ImmutableList.of(main, A, C)) {
-        inputConsumer.accept(
-            ByteDataView.of(ToolHelper.getClassAsBytes(clazz)),
-            DescriptorUtils.javaTypeToDescriptor(clazz.getName()),
-            null);
-      }
       inputConsumer.accept(
-          ByteDataView.of(jasminBuilder.buildClasses().get(0)),
-          DescriptorUtils.javaTypeToDescriptor(B.getName()),
+          ByteDataView.of(NonVirtualOverrideTestClassDump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(NonVirtualOverrideTestClass.class.getName()),
+          null);
+      inputConsumer.accept(
+          ByteDataView.of(ADump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(A.class.getName()),
+          null);
+      inputConsumer.accept(
+          ByteDataView.of(BDump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(B.class.getName()),
+          null);
+      inputConsumer.accept(
+          ByteDataView.of(CDump.dump()),
+          DescriptorUtils.javaTypeToDescriptor(C.class.getName()),
           null);
       inputConsumer.finished(null);
 
-      ProcessResult javaResult = ToolHelper.runJava(referenceJar, main.getName());
+      ProcessResult javaResult =
+          ToolHelper.runJava(referenceJar, NonVirtualOverrideTestClass.class.getName());
       assertEquals(javaResult.exitCode, 0);
-      referenceResult = javaResult.stdout;
+      return javaResult.stdout;
     }
+  }
 
-    // Run the program on Art after is has been compiled with R8.
-    AndroidApp compiled =
-        compileWithR8(
-            input,
-            keepMainProguardConfiguration(main),
+  public static boolean isDexVmBetween5_1_1and7_0_0(TestParameters parameters) {
+    if (!parameters.isDexRuntime()) {
+      return false;
+    }
+    Version version = parameters.getRuntime().asDex().getVm().getVersion();
+    return version.isOlderThanOrEqual(Version.V7_0_0) && version.isAtLeast(Version.V5_1_1);
+  }
+
+  public static R8TestCompileResult compile(Dimensions dimensions) throws Exception {
+    return testForR8(staticTemp, dimensions.backend)
+        .addProgramClassFileData(
+            NonVirtualOverrideTestClassDump.dump(), ADump.dump(), BDump.dump(), CDump.dump())
+        .addKeepMainRule(NonVirtualOverrideTestClass.class)
+        .addOptionsModification(
             options -> {
-              options.enableClassInlining = enableClassInlining;
-              options.enableVerticalClassMerging = enableVerticalClassMerging;
+              options.enableClassInlining = dimensions.enableClassInlining;
+              options.enableVerticalClassMerging = dimensions.enableVerticalClassMerging;
               options.testing.validInliningReasons = ImmutableSet.of(Reason.FORCE);
-            },
-            backend);
-    assertEquals(referenceResult, runOnVM(compiled, main, backend));
+            })
+        .setMinApi(AndroidApiLevel.B)
+        .compile();
+  }
+
+  @Test
+  public void test() throws Exception {
+    // Run the program on Art after is has been compiled with R8.
+    String referenceResult = expectedResults.apply(isDexVmBetween5_1_1and7_0_0(parameters));
+    R8TestCompileResult compiled =
+        compilationResults.apply(
+            new Dimensions(
+                parameters.getBackend(), enableClassInlining, enableVerticalClassMerging));
+    compiled
+        .run(parameters.getRuntime(), NonVirtualOverrideTestClass.class)
+        .assertSuccessWithOutput(referenceResult);
 
     // Check that B is present and that it doesn't contain the unused private method m2.
     if (!enableClassInlining && !enableVerticalClassMerging) {
-      CodeInspector inspector = new CodeInspector(compiled);
-      ClassSubject classSubject = inspector.clazz(B.getName());
+      CodeInspector inspector = compiled.inspector();
+      ClassSubject classSubject = inspector.clazz(B.class.getName());
       assertThat(classSubject, isRenamed());
       assertThat(classSubject.method("void", "m1", ImmutableList.of()), isPresent());
       assertThat(classSubject.method("void", "m2", ImmutableList.of()), not(isPresent()));
@@ -147,114 +198,4 @@
       assertThat(classSubject.method("void", "m4", ImmutableList.of()), not(isPresent()));
     }
   }
-
-  private static String[] jasminCodeForPrinting(String message) {
-    return new String[] {
-      ".limit stack 2",
-      ".limit locals 1",
-      "getstatic java/lang/System/out Ljava/io/PrintStream;",
-      "ldc \"" + message + "\"",
-      "invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V",
-      "return"
-    };
-  }
-}
-
-class NonVirtualOverrideTestClass {
-
-  public static void main(String[] args) {
-    A a = new B();
-    a.m1();
-    a.m2();
-    a.m3();
-    a.m4();
-
-    a = new C();
-    a.m1();
-    a.m2();
-    a.m3();
-    a.m4();
-
-    B b = new B();
-    try {
-      b.m1();
-    } catch (IllegalAccessError exception) {
-      System.out.println("Caught IllegalAccessError when calling B.m1()");
-    }
-    try {
-      b.m3();
-    } catch (IncompatibleClassChangeError exception) {
-      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
-    }
-
-    try {
-      b = new C();
-      b.m1();
-    } catch (IllegalAccessError exception) {
-      System.out.println("Caught IllegalAccessError when calling B.m1()");
-    }
-    try {
-      b = new C();
-      b.m3();
-    } catch (IncompatibleClassChangeError exception) {
-      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
-    }
-
-    C c = new C();
-    c.m1();
-    c.m3();
-  }
-
-  static class A {
-
-    public void m1() {
-      System.out.println("In A.m1()");
-    }
-
-    public void m2() {
-      System.out.println("In A.m2()");
-    }
-
-    public void m3() {
-      System.out.println("In A.m3()");
-    }
-
-    public void m4() {
-      System.out.println("In A.m4()");
-    }
-  }
-
-  static class B extends A {
-
-    // Will be made private with Jasmin. This method is targeted and can therefore not be removed.
-    public void m1() {
-      System.out.println("In B.m1()");
-    }
-
-    // Will be made private with Jasmin. Ends up being dead code because the method is never called.
-    public void m2() {
-      System.out.println("In B.m2()");
-    }
-
-    // Will be made static with Jasmin. This method is targeted and can therefore not be removed.
-    public void m3() {
-      System.out.println("In B.m3()");
-    }
-
-    // Will be made static with Jasmin. Ends up being dead code because the method is never called.
-    public void m4() {
-      System.out.println("In B.m4()");
-    }
-  }
-
-  static class C extends B {
-
-    public void m1() {
-      System.out.println("In C.m1()");
-    }
-
-    public void m3() {
-      System.out.println("In C.m3()");
-    }
-  }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTestDump.java b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTestDump.java
new file mode 100644
index 0000000..e8f54b3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/NonVirtualOverrideTestDump.java
@@ -0,0 +1,726 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+class NonVirtualOverrideTestClass {
+
+  public static void main(String[] args) {
+    A a = new B();
+    a.m1();
+    a.m2();
+    a.m3();
+    a.m4();
+
+    a = new C();
+    a.m1();
+    a.m2();
+    a.m3();
+    a.m4();
+
+    B b = new B();
+    try {
+      b.m1();
+    } catch (IllegalAccessError exception) {
+      System.out.println("Caught IllegalAccessError when calling B.m1()");
+    }
+    try {
+      b.m3();
+    } catch (IncompatibleClassChangeError exception) {
+      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
+    }
+
+    try {
+      b = new C();
+      b.m1();
+    } catch (IllegalAccessError exception) {
+      System.out.println("Caught IllegalAccessError when calling B.m1()");
+    }
+    try {
+      b = new C();
+      b.m3();
+    } catch (IncompatibleClassChangeError exception) {
+      System.out.println("Caught IncompatibleClassChangeError when calling B.m3()");
+    }
+
+    C c = new C();
+    c.m1();
+    c.m3();
+  }
+}
+
+class A {
+
+  public void m1() {
+    System.out.println("In A.m1()");
+  }
+
+  public void m2() {
+    System.out.println("In A.m2()");
+  }
+
+  public void m3() {
+    System.out.println("In A.m3()");
+  }
+
+  public void m4() {
+    System.out.println("In A.m4()");
+  }
+}
+
+class B extends A {
+
+  // Made private in the dump below. This method is targeted and can therefore not be removed.
+  public void m1() {
+    System.out.println("In B.m1()");
+  }
+
+  // Made private in the dump below. Ends up being dead code because the method is never called.
+  public void m2() {
+    System.out.println("In B.m2()");
+  }
+
+  // Made static in the dump below. This method is targeted and can therefore not be removed.
+  public void m3() {
+    System.out.println("In B.m3()");
+  }
+
+  // Made static in the dump below. Ends up being dead code because the method is never called.
+  public void m4() {
+    System.out.println("In B.m4()");
+  }
+}
+
+class C extends B {
+
+  public void m1() {
+    System.out.println("In C.m1()");
+  }
+
+  public void m3() {
+    System.out.println("In C.m3()");
+  }
+}
+
+/* Below are dumps from the classes above with the changes to B as described */
+
+class NonVirtualOverrideTestClassDump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8,
+        ACC_SUPER,
+        "com/android/tools/r8/shaking/NonVirtualOverrideTestClass",
+        null,
+        "java/lang/Object",
+        null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(7, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this",
+          "Lcom/android/tools/r8/shaking/NonVirtualOverrideTestClass;",
+          null,
+          label0,
+          label1,
+          0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor =
+          classWriter.visitMethod(
+              ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      Label label1 = new Label();
+      Label label2 = new Label();
+      methodVisitor.visitTryCatchBlock(label0, label1, label2, "java/lang/IllegalAccessError");
+      Label label3 = new Label();
+      Label label4 = new Label();
+      Label label5 = new Label();
+      methodVisitor.visitTryCatchBlock(
+          label3, label4, label5, "java/lang/IncompatibleClassChangeError");
+      Label label6 = new Label();
+      Label label7 = new Label();
+      Label label8 = new Label();
+      methodVisitor.visitTryCatchBlock(label6, label7, label8, "java/lang/IllegalAccessError");
+      Label label9 = new Label();
+      Label label10 = new Label();
+      Label label11 = new Label();
+      methodVisitor.visitTryCatchBlock(
+          label9, label10, label11, "java/lang/IncompatibleClassChangeError");
+      Label label12 = new Label();
+      methodVisitor.visitLabel(label12);
+      methodVisitor.visitLineNumber(10, label12);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/B");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/B", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 1);
+      Label label13 = new Label();
+      methodVisitor.visitLabel(label13);
+      methodVisitor.visitLineNumber(11, label13);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m1", "()V", false);
+      Label label14 = new Label();
+      methodVisitor.visitLabel(label14);
+      methodVisitor.visitLineNumber(12, label14);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m2", "()V", false);
+      Label label15 = new Label();
+      methodVisitor.visitLabel(label15);
+      methodVisitor.visitLineNumber(13, label15);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m3", "()V", false);
+      Label label16 = new Label();
+      methodVisitor.visitLabel(label16);
+      methodVisitor.visitLineNumber(14, label16);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m4", "()V", false);
+      Label label17 = new Label();
+      methodVisitor.visitLabel(label17);
+      methodVisitor.visitLineNumber(16, label17);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 1);
+      Label label18 = new Label();
+      methodVisitor.visitLabel(label18);
+      methodVisitor.visitLineNumber(17, label18);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m1", "()V", false);
+      Label label19 = new Label();
+      methodVisitor.visitLabel(label19);
+      methodVisitor.visitLineNumber(18, label19);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m2", "()V", false);
+      Label label20 = new Label();
+      methodVisitor.visitLabel(label20);
+      methodVisitor.visitLineNumber(19, label20);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m3", "()V", false);
+      Label label21 = new Label();
+      methodVisitor.visitLabel(label21);
+      methodVisitor.visitLineNumber(20, label21);
+      methodVisitor.visitVarInsn(ALOAD, 1);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/A", "m4", "()V", false);
+      Label label22 = new Label();
+      methodVisitor.visitLabel(label22);
+      methodVisitor.visitLineNumber(22, label22);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/B");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/B", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 2);
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(24, label0);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m1", "()V", false);
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(27, label1);
+      methodVisitor.visitJumpInsn(GOTO, label3);
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLineNumber(25, label2);
+      methodVisitor.visitFrame(
+          Opcodes.F_FULL,
+          3,
+          new Object[] {
+            "[Ljava/lang/String;",
+            "com/android/tools/r8/shaking/A",
+            "com/android/tools/r8/shaking/B"
+          },
+          1,
+          new Object[] {"java/lang/IllegalAccessError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label23 = new Label();
+      methodVisitor.visitLabel(label23);
+      methodVisitor.visitLineNumber(26, label23);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IllegalAccessError when calling B.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label3);
+      methodVisitor.visitLineNumber(29, label3);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m3", "()V", false);
+      methodVisitor.visitLabel(label4);
+      methodVisitor.visitLineNumber(32, label4);
+      methodVisitor.visitJumpInsn(GOTO, label6);
+      methodVisitor.visitLabel(label5);
+      methodVisitor.visitLineNumber(30, label5);
+      methodVisitor.visitFrame(
+          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label24 = new Label();
+      methodVisitor.visitLabel(label24);
+      methodVisitor.visitLineNumber(31, label24);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IncompatibleClassChangeError when calling B.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label6);
+      methodVisitor.visitLineNumber(35, label6);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 2);
+      Label label25 = new Label();
+      methodVisitor.visitLabel(label25);
+      methodVisitor.visitLineNumber(36, label25);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m1", "()V", false);
+      methodVisitor.visitLabel(label7);
+      methodVisitor.visitLineNumber(39, label7);
+      methodVisitor.visitJumpInsn(GOTO, label9);
+      methodVisitor.visitLabel(label8);
+      methodVisitor.visitLineNumber(37, label8);
+      methodVisitor.visitFrame(
+          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IllegalAccessError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label26 = new Label();
+      methodVisitor.visitLabel(label26);
+      methodVisitor.visitLineNumber(38, label26);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IllegalAccessError when calling B.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label9);
+      methodVisitor.visitLineNumber(41, label9);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 2);
+      Label label27 = new Label();
+      methodVisitor.visitLabel(label27);
+      methodVisitor.visitLineNumber(42, label27);
+      methodVisitor.visitVarInsn(ALOAD, 2);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/B", "m3", "()V", false);
+      methodVisitor.visitLabel(label10);
+      methodVisitor.visitLineNumber(45, label10);
+      Label label28 = new Label();
+      methodVisitor.visitJumpInsn(GOTO, label28);
+      methodVisitor.visitLabel(label11);
+      methodVisitor.visitLineNumber(43, label11);
+      methodVisitor.visitFrame(
+          Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"});
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label29 = new Label();
+      methodVisitor.visitLabel(label29);
+      methodVisitor.visitLineNumber(44, label29);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("Caught IncompatibleClassChangeError when calling B.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      methodVisitor.visitLabel(label28);
+      methodVisitor.visitLineNumber(47, label28);
+      methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      methodVisitor.visitTypeInsn(NEW, "com/android/tools/r8/shaking/C");
+      methodVisitor.visitInsn(DUP);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/C", "<init>", "()V", false);
+      methodVisitor.visitVarInsn(ASTORE, 3);
+      Label label30 = new Label();
+      methodVisitor.visitLabel(label30);
+      methodVisitor.visitLineNumber(48, label30);
+      methodVisitor.visitVarInsn(ALOAD, 3);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/C", "m1", "()V", false);
+      Label label31 = new Label();
+      methodVisitor.visitLabel(label31);
+      methodVisitor.visitLineNumber(49, label31);
+      methodVisitor.visitVarInsn(ALOAD, 3);
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "com/android/tools/r8/shaking/C", "m3", "()V", false);
+      Label label32 = new Label();
+      methodVisitor.visitLabel(label32);
+      methodVisitor.visitLineNumber(50, label32);
+      methodVisitor.visitInsn(RETURN);
+      Label label33 = new Label();
+      methodVisitor.visitLabel(label33);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IllegalAccessError;", null, label23, label3, 3);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IncompatibleClassChangeError;", null, label24, label6, 3);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IllegalAccessError;", null, label26, label9, 3);
+      methodVisitor.visitLocalVariable(
+          "exception", "Ljava/lang/IncompatibleClassChangeError;", null, label29, label28, 3);
+      methodVisitor.visitLocalVariable("args", "[Ljava/lang/String;", null, label12, label33, 0);
+      methodVisitor.visitLocalVariable(
+          "a", "Lcom/android/tools/r8/shaking/A;", null, label13, label33, 1);
+      methodVisitor.visitLocalVariable(
+          "b", "Lcom/android/tools/r8/shaking/B;", null, label0, label33, 2);
+      methodVisitor.visitLocalVariable(
+          "c", "Lcom/android/tools/r8/shaking/C;", null, label30, label33, 3);
+      methodVisitor.visitMaxs(2, 4);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
+
+class ADump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8, ACC_SUPER, "com/android/tools/r8/shaking/A", null, "java/lang/Object", null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(53, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label1, 0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m1", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(56, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(57, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m2", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(60, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m2()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(61, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m3", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(64, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(65, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m4", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(68, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In A.m4()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(69, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/A;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
+
+class BDump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8,
+        ACC_SUPER,
+        "com/android/tools/r8/shaking/B",
+        null,
+        "com/android/tools/r8/shaking/A",
+        null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(72, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/A", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label1, 0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PRIVATE, "m1", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(76, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(77, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PRIVATE, "m2", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(81, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m2()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(82, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_STATIC, "m3", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(86, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(87, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_STATIC, "m4", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(91, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In B.m4()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(92, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/B;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}
+
+class CDump implements Opcodes {
+
+  public static byte[] dump() {
+
+    ClassWriter classWriter = new ClassWriter(0);
+    MethodVisitor methodVisitor;
+
+    classWriter.visit(
+        V1_8,
+        ACC_SUPER,
+        "com/android/tools/r8/shaking/C",
+        null,
+        "com/android/tools/r8/shaking/B",
+        null);
+
+    classWriter.visitSource("NonVirtualOverrideTestDump.java", null);
+
+    {
+      methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(95, label0);
+      methodVisitor.visitVarInsn(ALOAD, 0);
+      methodVisitor.visitMethodInsn(
+          INVOKESPECIAL, "com/android/tools/r8/shaking/B", "<init>", "()V", false);
+      methodVisitor.visitInsn(RETURN);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/C;", null, label0, label1, 0);
+      methodVisitor.visitMaxs(1, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m1", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(98, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In C.m1()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(99, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/C;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    {
+      methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "m3", "()V", null, null);
+      methodVisitor.visitCode();
+      Label label0 = new Label();
+      methodVisitor.visitLabel(label0);
+      methodVisitor.visitLineNumber(102, label0);
+      methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      methodVisitor.visitLdcInsn("In C.m3()");
+      methodVisitor.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+      Label label1 = new Label();
+      methodVisitor.visitLabel(label1);
+      methodVisitor.visitLineNumber(103, label1);
+      methodVisitor.visitInsn(RETURN);
+      Label label2 = new Label();
+      methodVisitor.visitLabel(label2);
+      methodVisitor.visitLocalVariable(
+          "this", "Lcom/android/tools/r8/shaking/C;", null, label0, label2, 0);
+      methodVisitor.visitMaxs(2, 1);
+      methodVisitor.visitEnd();
+    }
+    classWriter.visitEnd();
+
+    return classWriter.toByteArray();
+  }
+}