private void createStaticInitializer() { final MethodVisitor mv = cv.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode(); patchStaticInitializer(mv); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); }
public static void endVisit( MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) { try { mv.visitMaxs(-1, -1); mv.visitEnd(); } catch (ProcessCanceledException e) { throw e; } catch (Throwable t) { String bytecode = renderByteCodeIfAvailable(mv); throw new CompilationException( "wrong code generated" + (description != null ? " for " + description : "") + t.getClass().getName() + " " + t.getMessage() + (bytecode != null ? "\nbytecode:\n" + bytecode : ""), t, method); } }
public byte[] buildClass(ClassDefinition core) throws IOException, IntrospectionException, SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { Class coreKlazz = core.getDefinedClass(); String coreName = coreKlazz.getName(); String wrapperName = coreName + "Wrapper"; ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); FieldVisitor fv; MethodVisitor mv; cw.visit( V1_5, ACC_PUBLIC + ACC_SUPER, BuildUtils.getInternalType(wrapperName), BuildUtils.getTypeDescriptor(coreName) + "Lorg/drools/factmodel/traits/CoreWrapper<" + BuildUtils.getTypeDescriptor(coreName) + ">;", BuildUtils.getInternalType(coreName), new String[] { Type.getInternalName(CoreWrapper.class), Type.getInternalName(Externalizable.class) }); { fv = cw.visitField(ACC_PRIVATE, "core", BuildUtils.getTypeDescriptor(coreName), null, null); fv.visitEnd(); } { fv = cw.visitField( ACC_PRIVATE, TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class), "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;", null); fv.visitEnd(); } { fv = cw.visitField( ACC_PRIVATE, TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class), "Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;", null); fv.visitEnd(); } { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, BuildUtils.getInternalType(coreName), "<init>", "()V"); // mv.visitVarInsn( ALOAD, 0 ); // mv.visitTypeInsn( NEW, Type.getInternalName( HashMap.class ) ); // mv.visitInsn( DUP ); // mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( HashMap.class ), // "<init>", "()V" ); // mv.visitFieldInsn( PUTFIELD, // BuildUtils.getInternalType( wrapperName ), // TraitableBean.MAP_FIELD_NAME, // Type.getDescriptor( Map.class ) ); // mv.visitVarInsn( ALOAD, 0 ); // mv.visitTypeInsn( NEW, Type.getInternalName( VetoableTypedMap.class ) ); // mv.visitInsn( DUP ); // mv.visitTypeInsn( NEW, Type.getInternalName( HashMap.class ) ); // mv.visitInsn( DUP ); // mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( HashMap.class ), // "<init>", "()V" ); // mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( VetoableTypedMap.class // ), "<init>", "(" + Type.getDescriptor( Map.class ) + ")V" ); // mv.visitFieldInsn( PUTFIELD, // BuildUtils.getInternalType( wrapperName ), // TraitableBean.TRAITSET_FIELD_NAME, // Type.getDescriptor( Map.class ) ); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } if (coreKlazz == null || needsMethod(coreKlazz, "getCore")) { { mv = cw.visitMethod( ACC_PUBLIC, "getCore", "()" + Type.getDescriptor(Object.class), "()" + BuildUtils.getTypeDescriptor(coreName), null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getDynamicProperties")) { { mv = cw.visitMethod( ACC_PUBLIC, "getDynamicProperties", "()" + Type.getDescriptor(Map.class), "()Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); mv = cw.visitMethod( ACC_PUBLIC, "setDynamicProperties", "(" + Type.getDescriptor(Map.class) + ")V", "(Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;)V", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getTraitMap")) { { mv = cw.visitMethod( ACC_PUBLIC, "getTraitMap", "()" + Type.getDescriptor(Map.class), "()Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); Label l0 = new Label(); mv.visitJumpInsn(IFNONNULL, l0); mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(NEW, Type.getInternalName(VetoableTypedMap.class)); mv.visitInsn(DUP); mv.visitTypeInsn(NEW, Type.getInternalName(HashMap.class)); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(HashMap.class), "<init>", "()V"); mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName(VetoableTypedMap.class), "<init>", "(" + Type.getDescriptor(Map.class) + ")V"); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitLabel(l0); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "setTraitMap", Map.class)) { { mv = cw.visitMethod(ACC_PUBLIC, "setTraitMap", "(Ljava/util/Map;)V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitTypeInsn(NEW, Type.getInternalName(VetoableTypedMap.class)); mv.visitInsn(DUP); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName(VetoableTypedMap.class), "<init>", "(" + Type.getDescriptor(Map.class) + ")V"); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "addTrait", String.class, Thing.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "addTrait", "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")V", "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")V", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class)); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(VetoableTypedMap.class), "putSafe", "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")" + Type.getDescriptor(Thing.class)); mv.visitInsn(POP); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getTrait", String.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "getTrait", "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "get", "(" + Type.getDescriptor(Object.class) + ")" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "hasTrait", String.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "hasTrait", "(" + Type.getDescriptor(String.class) + ")Z", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "containsKey", "(" + Type.getDescriptor(Object.class) + ")Z"); mv.visitInsn(IRETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "removeTrait", String.class)) { { mv = cw.visitMethod( ACC_PUBLIC, "removeTrait", "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class), null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "remove", "(" + Type.getDescriptor(Object.class) + ")" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } if (coreKlazz == null || needsMethod(coreKlazz, "getTraits")) { { mv = cw.visitMethod( ACC_PUBLIC, "getTraits", "()" + Type.getDescriptor(Collection.class), "()Ljava/util/Collection<Ljava/lang/String;>;", null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getTraitMap", "()" + Type.getDescriptor(Map.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(Map.class), "keySet", "()" + Type.getDescriptor(Set.class)); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } } { mv = cw.visitMethod( ACC_PUBLIC, "writeExternal", "(" + Type.getDescriptor(ObjectOutput.class) + ")V", null, new String[] {Type.getInternalName(IOException.class)}); mv.visitCode(); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "getCore", "()" + Type.getDescriptor(Object.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), "writeObject", "(" + Type.getDescriptor(Object.class) + ")V"); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), "writeObject", "(" + Type.getDescriptor(Object.class) + ")V"); mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), "writeObject", "(" + Type.getDescriptor(Object.class) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "readExternal", "(" + Type.getDescriptor(ObjectInput.class) + ")V", null, new String[] { Type.getInternalName(IOException.class), Type.getInternalName(ClassNotFoundException.class) }); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), "readObject", "()" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType(coreName)); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), "readObject", "()" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Map.class)); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.MAP_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), "readObject", "()" + Type.getDescriptor(Object.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Map.class)); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "init", "(" + BuildUtils.getTypeDescriptor(coreName) + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn( PUTFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } Method[] ms = coreKlazz.getMethods(); for (Method method : ms) { if (Modifier.isFinal(method.getModifiers())) { continue; } String signature = TraitFactory.buildSignature(method); { mv = cw.visitMethod(ACC_PUBLIC, method.getName(), signature, null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), "core", BuildUtils.getTypeDescriptor(coreName)); int j = 1; for (Class arg : method.getParameterTypes()) { mv.visitVarInsn(BuildUtils.varType(arg.getName()), j++); } mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(coreName), method.getName(), signature); mv.visitInsn(BuildUtils.returnType(method.getReturnType().getName())); int stack = TraitFactory.getStackSize(method); mv.visitMaxs(0, 0); mv.visitEnd(); } } { mv = cw.visitMethod( ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "init", "(" + Type.getDescriptor(Object.class) + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType(coreName)); mv.visitMethodInsn( INVOKEVIRTUAL, BuildUtils.getInternalType(wrapperName), "init", "(" + BuildUtils.getTypeDescriptor(coreName) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "denyTrait", "(" + Type.getDescriptor(Class.class) + ")V", null, new String[] {Type.getInternalName(LogicalTypeInconsistencyException.class)}); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(VetoableTypedMap.class), "addToVetoable", "(" + Type.getDescriptor(Class.class) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } { mv = cw.visitMethod( ACC_PUBLIC, "allowTrait", "(" + Type.getDescriptor(Class.class) + ")V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, BuildUtils.getInternalType(wrapperName), TraitableBean.TRAITSET_FIELD_NAME, Type.getDescriptor(Map.class)); mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class)); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn( INVOKEVIRTUAL, Type.getInternalName(VetoableTypedMap.class), "removeFromVetoable", "(" + Type.getDescriptor(Class.class) + ")V"); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); }
private static void generateFirstActivity(ApplicationWriter aw) { ClassVisitor cv; MethodVisitor mv; cv = aw.visitClass(ACC_PUBLIC, "Lft/nevo/FirstActivity;", null, "Landroid/app/Activity;", null); cv.visit(0, ACC_PUBLIC, "Lft/nevo/FirstActivity;", null, "Landroid/app/Activity;", null); cv.visitSource("FirstActivity.java", null); { mv = cv.visitMethod(ACC_PUBLIC + ACC_CONSTRUCTOR, "<init>", "V", null, null); mv.visitCode(); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLineNumber(6, l0); mv.visitMethodInsn( INSN_INVOKE_DIRECT, "Landroid/app/Activity;", "<init>", "V", new int[] {0}); mv.visitInsn(INSN_RETURN_VOID); mv.visitMaxs(1, 0); mv.visitEnd(); } { mv = cv.visitMethod(ACC_PUBLIC, "onCreate", "VLandroid/os/Bundle;", null, null); mv.visitCode(); mv.visitParameters(new String[] {"savedInstanceState"}); Label l0 = new Label(); mv.visitLabel(l0); mv.visitLineNumber(10, l0); mv.visitMethodInsn( INSN_INVOKE_SUPER, "Landroid/app/Activity;", "onCreate", "VLandroid/os/Bundle;", new int[] {1, 2}); Label l1 = new Label(); mv.visitLabel(l1); mv.visitLineNumber(11, l1); mv.visitVarInsn(INSN_CONST_HIGH16, 0, 2130903040); mv.visitMethodInsn( INSN_INVOKE_VIRTUAL, "Lft/nevo/FirstActivity;", "setContentView", "VI", new int[] {1, 0}); Label l2 = new Label(); mv.visitLabel(l2); mv.visitLineNumber(14, l2); mv.visitInsn(INSN_RETURN_VOID); mv.visitMaxs(3, 0); mv.visitEnd(); } { mv = cv.visitMethod(ACC_PUBLIC, "myMethod", "V", null, null); mv.visitCode(); // Added code. Label label1 = new Label(); Label label2 = new Label(); mv.visitLabel(label1); mv.visitJumpInsn(INSN_GOTO_16, label2, 0, 0); mv.visitJumpInsn(INSN_GOTO_16, label2, 0, 0); // NOPs are inserted here. for (int i = 0; i < MethodAdapterResizeGoto8BitsDoubleRefs.NB_NOPS; i++) { mv.visitInsn(INSN_NOP); } mv.visitLabel(label2); mv.visitJumpInsn(INSN_GOTO_16, label1, 0, 0); mv.visitJumpInsn(INSN_GOTO_16, label1, 0, 0); mv.visitInsn(INSN_RETURN_VOID); mv.visitMaxs(1, 0); mv.visitEnd(); } cv.visitEnd(); }
/** * Makes the given method visitor visit this method. * * @param mv a method visitor. */ public void accept(final MethodVisitor mv) { // visits the method parameters int i, j, n; n = parameters == null ? 0 : parameters.size(); for (i = 0; i < n; i++) { ParameterNode parameter = parameters.get(i); mv.visitParameter(parameter.name, parameter.access); } // visits the method attributes if (annotationDefault != null) { AnnotationVisitor av = mv.visitAnnotationDefault(); AnnotationNode.accept(av, null, annotationDefault); if (av != null) { av.visitEnd(); } } n = visibleAnnotations == null ? 0 : visibleAnnotations.size(); for (i = 0; i < n; ++i) { AnnotationNode an = visibleAnnotations.get(i); an.accept(mv.visitAnnotation(an.desc, true)); } n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size(); for (i = 0; i < n; ++i) { AnnotationNode an = invisibleAnnotations.get(i); an.accept(mv.visitAnnotation(an.desc, false)); } n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size(); for (i = 0; i < n; ++i) { TypeAnnotationNode an = visibleTypeAnnotations.get(i); an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, true)); } n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations.size(); for (i = 0; i < n; ++i) { TypeAnnotationNode an = invisibleTypeAnnotations.get(i); an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, false)); } n = visibleParameterAnnotations == null ? 0 : visibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List<?> l = visibleParameterAnnotations[i]; if (l == null) { continue; } for (j = 0; j < l.size(); ++j) { AnnotationNode an = (AnnotationNode) l.get(j); an.accept(mv.visitParameterAnnotation(i, an.desc, true)); } } n = invisibleParameterAnnotations == null ? 0 : invisibleParameterAnnotations.length; for (i = 0; i < n; ++i) { List<?> l = invisibleParameterAnnotations[i]; if (l == null) { continue; } for (j = 0; j < l.size(); ++j) { AnnotationNode an = (AnnotationNode) l.get(j); an.accept(mv.visitParameterAnnotation(i, an.desc, false)); } } if (visited) { instructions.resetLabels(); } n = attrs == null ? 0 : attrs.size(); for (i = 0; i < n; ++i) { mv.visitAttribute(attrs.get(i)); } // visits the method's code if (instructions.size() > 0) { mv.visitCode(); // visits try catch blocks n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size(); for (i = 0; i < n; ++i) { tryCatchBlocks.get(i).updateIndex(i); tryCatchBlocks.get(i).accept(mv); } // visits instructions instructions.accept(mv); // visits local variables n = localVariables == null ? 0 : localVariables.size(); for (i = 0; i < n; ++i) { localVariables.get(i).accept(mv); } // visits local variable annotations n = visibleLocalVariableAnnotations == null ? 0 : visibleLocalVariableAnnotations.size(); for (i = 0; i < n; ++i) { visibleLocalVariableAnnotations.get(i).accept(mv, true); } n = invisibleLocalVariableAnnotations == null ? 0 : invisibleLocalVariableAnnotations.size(); for (i = 0; i < n; ++i) { invisibleLocalVariableAnnotations.get(i).accept(mv, false); } // visits maxs mv.visitMaxs(maxStack, maxLocals); visited = true; } mv.visitEnd(); }
@NotNull public InlineResult doTransform( @NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper) { final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>(); ClassBuilder classBuilder = createClassBuilder(); final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>(); reader.accept( new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) { @Override public void visit( int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) { InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name); super.visit(version, access, name, signature, superName, interfaces); } @Override public void visitInnerClass( @NotNull String name, String outerName, String innerName, int access) { innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access)); } @Override public MethodVisitor visitMethod( int access, @NotNull String name, @NotNull String desc, String signature, String[] exceptions) { MethodNode node = new MethodNode(access, name, desc, signature, exceptions); if (name.equals("<init>")) { if (constructor != null) throw new RuntimeException( "Lambda, SAM or anonymous object should have only one constructor"); constructor = node; } else { methodsToTransform.add(node); } return node; } @Override public FieldVisitor visitField( int access, @NotNull String name, @NotNull String desc, String signature, Object value) { addUniqueField(name); if (InlineCodegenUtil.isCapturedFieldName(name)) { return null; } else { return super.visitField(access, name, desc, signature, value); } } @Override public void visitSource(String source, String debug) { sourceInfo = source; debugInfo = debug; } @Override public void visitEnd() {} }, ClassReader.SKIP_FRAMES); if (!inliningContext.isInliningLambda) { if (debugInfo != null && !debugInfo.isEmpty()) { sourceMapper = SourceMapper.Companion.createFromSmap(SMAPParser.parse(debugInfo)); } else { // seems we can't do any clever mapping cause we don't know any about original class name sourceMapper = IdenticalSourceMapper.INSTANCE; } if (sourceInfo != null && !InlineCodegenUtil.GENERATE_SMAP) { classBuilder.visitSource(sourceInfo, debugInfo); } } else { if (sourceInfo != null) { classBuilder.visitSource(sourceInfo, debugInfo); } sourceMapper = IdenticalSourceMapper.INSTANCE; } ParametersBuilder allCapturedParamBuilder = ParametersBuilder.newBuilder(); ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder(); List<CapturedParamInfo> additionalFakeParams = extractParametersMappingAndPatchConstructor( constructor, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper); List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>(); for (MethodNode next : methodsToTransform) { MethodVisitor deferringVisitor = newMethod(classBuilder, next); InlineResult funResult = inlineMethodAndUpdateGlobalResult( anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false); Type returnType = Type.getReturnType(next.desc); if (!AsmUtil.isPrimitive(returnType)) { String oldFunReturnType = returnType.getInternalName(); String newFunReturnType = funResult.getChangedTypes().get(oldFunReturnType); if (newFunReturnType != null) { inliningContext.typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType); } } deferringMethods.add(deferringVisitor); } for (MethodVisitor method : deferringMethods) { method.visitEnd(); } generateConstructorAndFields( classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams); SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder); ClassVisitor visitor = classBuilder.getVisitor(); for (InnerClassNode node : innerClassNodes) { visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access); } writeOuterInfo(visitor); classBuilder.done(); anonymousObjectGen.setNewLambdaType(newLambdaType); return transformationResult; }
private void generateConstructorAndFields( @NotNull ClassBuilder classBuilder, @NotNull ParametersBuilder allCapturedBuilder, @NotNull ParametersBuilder constructorInlineBuilder, @NotNull AnonymousObjectGeneration anonymousObjectGen, @NotNull FieldRemapper parentRemapper, @NotNull List<CapturedParamInfo> constructorAdditionalFakeParams) { List<Type> descTypes = new ArrayList<Type>(); Parameters constructorParams = constructorInlineBuilder.buildParameters(); int[] capturedIndexes = new int[constructorParams.getReal().size() + constructorParams.getCaptured().size()]; int index = 0; int size = 0; // complex processing cause it could have super constructor call params for (ParameterInfo info : constructorParams) { if (!info.isSkipped()) { // not inlined if (info.isCaptured() || info instanceof CapturedParamInfo) { capturedIndexes[index] = size; index++; } if (size != 0) { // skip this descTypes.add(info.getType()); } size += info.getType().getSize(); } } String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, descTypes.toArray(new Type[descTypes.size()])); // TODO for inline method make public class anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor); MethodVisitor constructorVisitor = classBuilder.newMethod( NO_ORIGIN, AsmUtil.NO_FLAG_PACKAGE_PRIVATE, "<init>", constructorDescriptor, null, ArrayUtil.EMPTY_STRING_ARRAY); // initialize captured fields List<NewJavaField> newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured()); List<FieldInfo> fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo(newLambdaType, newFieldsWithSkipped); int paramIndex = 0; InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor); for (int i = 0; i < fieldInfoWithSkipped.size(); i++) { FieldInfo fieldInfo = fieldInfoWithSkipped.get(i); if (!newFieldsWithSkipped.get(i).getSkip()) { AsmUtil.genAssignInstanceFieldFromParam( fieldInfo, capturedIndexes[paramIndex], capturedFieldInitializer); } paramIndex++; } // then transform constructor // HACK: in inlinining into constructor we access original captured fields with field access not // local var // but this fields added to general params (this assumes local var access) not captured one, // so we need to add them to captured params for (CapturedParamInfo info : constructorAdditionalFakeParams) { CapturedParamInfo fake = constructorInlineBuilder.addCapturedParamCopy(info); if (fake.getLambda() != null) { // set remap value to skip this fake (captured with lambda already skipped) StackValue composed = StackValue.field( fake.getType(), oldObjectType, fake.getNewFieldName(), false, StackValue.LOCAL_0); fake.setRemapValue(composed); } } inlineMethodAndUpdateGlobalResult( anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true); constructorVisitor.visitEnd(); AsmUtil.genClosureFields( TransformationUtilsKt.toNameTypePair( TransformationUtilsKt.filterSkipped(newFieldsWithSkipped)), classBuilder); }
public void generateMethod( @NotNull JvmDeclarationOrigin origin, @NotNull FunctionDescriptor functionDescriptor, @NotNull MethodContext methodContext, @NotNull FunctionGenerationStrategy strategy) { OwnerKind contextKind = methodContext.getContextKind(); if (isInterface(functionDescriptor.getContainingDeclaration()) && functionDescriptor.getVisibility() == Visibilities.PRIVATE && contextKind != OwnerKind.DEFAULT_IMPLS) { return; } JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, contextKind); Method asmMethod = jvmSignature.getAsmMethod(); int flags = getMethodAsmFlags(functionDescriptor, contextKind); boolean isNative = NativeKt.hasNativeAnnotation(functionDescriptor); if (isNative && owner instanceof MultifileClassFacadeContext) { // Native methods are only defined in facades and do not need package part implementations return; } MethodVisitor mv = v.newMethod( origin, flags, asmMethod.getName(), asmMethod.getDescriptor(), jvmSignature.getGenericsSignature(), getThrownExceptions(functionDescriptor, typeMapper)); if (CodegenContextUtil.isImplClassOwner(owner)) { v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod); } generateMethodAnnotations(functionDescriptor, asmMethod, mv); generateParameterAnnotations( functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor)); generateBridges(functionDescriptor); boolean staticInCompanionObject = AnnotationUtilKt.isPlatformStaticInCompanionObject(functionDescriptor); if (staticInCompanionObject) { ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen(); parentBodyCodegen.addAdditionalTask( new JvmStaticGenerator(functionDescriptor, origin, state)); } if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES || isAbstractMethod(functionDescriptor, contextKind)) { generateLocalVariableTable( mv, jvmSignature, functionDescriptor, getThisTypeForFunction(functionDescriptor, methodContext, typeMapper), new Label(), new Label(), contextKind); mv.visitEnd(); return; } if (!isNative) { generateMethodBody( mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen); } else if (staticInCompanionObject) { // native @JvmStatic foo() in companion object should delegate to the static native function // moved to the outer class mv.visitCode(); FunctionDescriptor staticFunctionDescriptor = JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor); JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature( memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null)); Type owningType = typeMapper.mapClass( (ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration()); generateDelegateToMethodBody( false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName()); } endVisit(mv, null, origin.getElement()); }
/** * Visits the end of the method. This method, which is the last one to be called, is used to * inform the visitor that all the annotations and attributes of the method have been visited. */ public void visitEnd() { if (mv != null) { mv.visitEnd(); } }