blob: ac2a8ff41f2a7e6166007e0a3e38351433d6a400 [file] [log] [blame]
// 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();
}
}