|  | // 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(); | 
|  | } | 
|  | } |