|  | // Copyright (c) 2018, 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.debuginfo; | 
|  |  | 
|  | import org.objectweb.asm.AnnotationVisitor; | 
|  | import org.objectweb.asm.ClassWriter; | 
|  | import org.objectweb.asm.FieldVisitor; | 
|  | import org.objectweb.asm.Label; | 
|  | import org.objectweb.asm.MethodVisitor; | 
|  | import org.objectweb.asm.Opcodes; | 
|  |  | 
|  | public class KotlinReflectionDump implements Opcodes { | 
|  |  | 
|  | private static final String reflectionFactory = | 
|  | "java/lang/Object"; // "kotlin/jvm/internal/ReflectionFactory"; | 
|  | private static final String kClass = "java/lang/Object"; // "kotlin/reflect/KClass"; | 
|  | private static final String INTERNAL_NAME = "kotlin/jvm/internal/Reflection"; | 
|  | public static final String CLASS_NAME = INTERNAL_NAME.replace('/', '.'); | 
|  |  | 
|  | public static byte[] dump() throws Exception { | 
|  |  | 
|  | ClassWriter cw = new ClassWriter(0); | 
|  | FieldVisitor fv; | 
|  | MethodVisitor mv; | 
|  | AnnotationVisitor av0; | 
|  |  | 
|  | cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, INTERNAL_NAME, null, "java/lang/Object", null); | 
|  |  | 
|  | cw.visitSource("Reflection.java", null); | 
|  |  | 
|  | { | 
|  | fv = | 
|  | cw.visitField( | 
|  | ACC_PRIVATE + ACC_FINAL + ACC_STATIC, | 
|  | "factory", | 
|  | "L" + reflectionFactory + ";", | 
|  | null, | 
|  | null); | 
|  | fv.visitEnd(); | 
|  | } | 
|  | { | 
|  | fv = | 
|  | cw.visitField( | 
|  | ACC_FINAL + ACC_STATIC, | 
|  | "REFLECTION_NOT_AVAILABLE", | 
|  | "Ljava/lang/String;", | 
|  | null, | 
|  | " (Kotlin reflection is not available)"); | 
|  | fv.visitEnd(); | 
|  | } | 
|  | { | 
|  | fv = | 
|  | cw.visitField( | 
|  | ACC_PRIVATE + ACC_FINAL + ACC_STATIC, | 
|  | "EMPTY_K_CLASS_ARRAY", | 
|  | "[L" + kClass + ";", | 
|  | null, | 
|  | null); | 
|  | fv.visitEnd(); | 
|  | } | 
|  | method0(cw); | 
|  | mainMethod(cw); | 
|  | cw.visitEnd(); | 
|  |  | 
|  | return cw.toByteArray(); | 
|  | } | 
|  |  | 
|  | private static void mainMethod(ClassWriter cw) { | 
|  | MethodVisitor mv = | 
|  | cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); | 
|  | mv.visitCode(); | 
|  | mv.visitInsn(RETURN); | 
|  | mv.visitMaxs(0, 1); | 
|  | mv.visitEnd(); | 
|  | } | 
|  |  | 
|  | private static void method0(ClassWriter cw) { | 
|  | MethodVisitor mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); | 
|  | Label[] labels = new Label[18]; | 
|  | for (int i = 0; i < labels.length; i++) { | 
|  | labels[i] = new Label(); | 
|  | } | 
|  | mv.visitCode(); | 
|  | mv.visitTryCatchBlock(labels[0], labels[1], labels[2], "java/lang/ClassCastException"); | 
|  | mv.visitTryCatchBlock(labels[0], labels[1], labels[3], "java/lang/ClassNotFoundException"); | 
|  | mv.visitTryCatchBlock(labels[0], labels[1], labels[4], "java/lang/InstantiationException"); | 
|  | mv.visitTryCatchBlock(labels[0], labels[1], labels[5], "java/lang/IllegalAccessException"); | 
|  | mv.visitLabel(labels[0]); | 
|  | mv.visitLineNumber(33, labels[0]); | 
|  | mv.visitLdcInsn("kotlin.reflect.jvm.internal.ReflectionFactoryImpl"); | 
|  | mv.visitMethodInsn( | 
|  | INVOKESTATIC, "java/lang/Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false); | 
|  | mv.visitVarInsn(ASTORE, 1); | 
|  | mv.visitLabel(labels[6]); | 
|  | mv.visitLineNumber(34, labels[6]); | 
|  | mv.visitVarInsn(ALOAD, 1); | 
|  | mv.visitMethodInsn( | 
|  | INVOKEVIRTUAL, "java/lang/Class", "newInstance", "()Ljava/lang/Object;", false); | 
|  | mv.visitTypeInsn(CHECKCAST, reflectionFactory); | 
|  | mv.visitVarInsn(ASTORE, 0); | 
|  | mv.visitLabel(labels[1]); | 
|  | mv.visitLineNumber(39, labels[1]); | 
|  | mv.visitJumpInsn(GOTO, labels[7]); | 
|  | mv.visitLabel(labels[2]); | 
|  | mv.visitLineNumber(36, labels[2]); | 
|  | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/ClassCastException"}); | 
|  | mv.visitVarInsn(ASTORE, 1); | 
|  | mv.visitLabel(labels[8]); | 
|  | mv.visitInsn(ACONST_NULL); | 
|  | mv.visitVarInsn(ASTORE, 0); | 
|  | mv.visitLabel(labels[9]); | 
|  | mv.visitLineNumber(39, labels[9]); | 
|  | mv.visitJumpInsn(GOTO, labels[7]); | 
|  | mv.visitLabel(labels[3]); | 
|  | mv.visitLineNumber(37, labels[3]); | 
|  | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/ClassNotFoundException"}); | 
|  | mv.visitVarInsn(ASTORE, 1); | 
|  | mv.visitLabel(labels[10]); | 
|  | mv.visitInsn(ACONST_NULL); | 
|  | mv.visitVarInsn(ASTORE, 0); | 
|  | mv.visitLabel(labels[11]); | 
|  | mv.visitLineNumber(39, labels[11]); | 
|  | mv.visitJumpInsn(GOTO, labels[7]); | 
|  | mv.visitLabel(labels[4]); | 
|  | mv.visitLineNumber(38, labels[4]); | 
|  | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/InstantiationException"}); | 
|  | mv.visitVarInsn(ASTORE, 1); | 
|  | mv.visitLabel(labels[12]); | 
|  | mv.visitInsn(ACONST_NULL); | 
|  | mv.visitVarInsn(ASTORE, 0); | 
|  | mv.visitLabel(labels[13]); | 
|  | mv.visitLineNumber(39, labels[13]); | 
|  | mv.visitJumpInsn(GOTO, labels[7]); | 
|  | mv.visitLabel(labels[5]); | 
|  | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IllegalAccessException"}); | 
|  | mv.visitVarInsn(ASTORE, 1); | 
|  | mv.visitLabel(labels[14]); | 
|  | mv.visitInsn(ACONST_NULL); | 
|  | mv.visitVarInsn(ASTORE, 0); | 
|  | mv.visitLabel(labels[7]); | 
|  | mv.visitLineNumber(41, labels[7]); | 
|  | mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {reflectionFactory}, 0, null); | 
|  | mv.visitVarInsn(ALOAD, 0); | 
|  | mv.visitJumpInsn(IFNULL, labels[15]); | 
|  | mv.visitVarInsn(ALOAD, 0); | 
|  | mv.visitJumpInsn(GOTO, labels[16]); | 
|  | mv.visitLabel(labels[15]); | 
|  | mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); | 
|  | mv.visitTypeInsn(NEW, reflectionFactory); | 
|  | mv.visitInsn(DUP); | 
|  | mv.visitMethodInsn(INVOKESPECIAL, reflectionFactory, "<init>", "()V", false); | 
|  | mv.visitLabel(labels[16]); | 
|  | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {reflectionFactory}); | 
|  | mv.visitFieldInsn(PUTSTATIC, INTERNAL_NAME, "factory", "L" + reflectionFactory + ";"); | 
|  | mv.visitLabel(labels[17]); | 
|  | mv.visitLineNumber(46, labels[17]); | 
|  | mv.visitInsn(ICONST_0); | 
|  | mv.visitTypeInsn(ANEWARRAY, kClass); | 
|  | mv.visitFieldInsn(PUTSTATIC, INTERNAL_NAME, "EMPTY_K_CLASS_ARRAY", "[L" + kClass + ";"); | 
|  | mv.visitInsn(RETURN); | 
|  | mv.visitLocalVariable( | 
|  | "implClass", "Ljava/lang/Class;", "Ljava/lang/Class<*>;", labels[6], labels[1], 1); | 
|  | mv.visitLocalVariable("e", "Ljava/lang/ClassCastException;", null, labels[8], labels[9], 1); | 
|  | mv.visitLocalVariable( | 
|  | "e", "Ljava/lang/ClassNotFoundException;", null, labels[10], labels[11], 1); | 
|  | mv.visitLocalVariable( | 
|  | "e", "Ljava/lang/InstantiationException;", null, labels[12], labels[13], 1); | 
|  | mv.visitLocalVariable( | 
|  | "e", "Ljava/lang/IllegalAccessException;", null, labels[14], labels[7], 1); | 
|  | mv.visitLocalVariable("impl", "L" + reflectionFactory + ";", null, labels[1], labels[17], 0); | 
|  | mv.visitMaxs(2, 2); | 
|  | mv.visitEnd(); | 
|  | } | 
|  | } |