Search in sources :

Example 56 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class AsmClassGenerator method loadWrapper.

public void loadWrapper(Expression argument) {
    MethodVisitor mv = controller.getMethodVisitor();
    ClassNode goalClass = argument.getType();
    visitClassExpression(new ClassExpression(goalClass));
    if (goalClass.isDerivedFromGroovyObject()) {
        createGroovyObjectWrapperMethod.call(mv);
    } else {
        createPojoWrapperMethod.call(mv);
    }
    controller.getOperandStack().remove(1);
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 57 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class AsmClassGenerator method visitClosureListExpression.

public void visitClosureListExpression(ClosureListExpression expression) {
    MethodVisitor mv = controller.getMethodVisitor();
    controller.getCompileStack().pushVariableScope(expression.getVariableScope());
    List<Expression> expressions = expression.getExpressions();
    final int size = expressions.size();
    // init declarations
    LinkedList<DeclarationExpression> declarations = new LinkedList<DeclarationExpression>();
    for (int i = 0; i < size; i++) {
        Expression expr = expressions.get(i);
        if (expr instanceof DeclarationExpression) {
            declarations.add((DeclarationExpression) expr);
            DeclarationExpression de = (DeclarationExpression) expr;
            BinaryExpression be = new BinaryExpression(de.getLeftExpression(), de.getOperation(), de.getRightExpression());
            expressions.set(i, be);
            de.setRightExpression(ConstantExpression.NULL);
            visitDeclarationExpression(de);
        }
    }
    LinkedList instructions = new LinkedList();
    BytecodeSequence seq = new BytecodeSequence(instructions);
    BlockStatement bs = new BlockStatement();
    bs.addStatement(seq);
    Parameter closureIndex = new Parameter(ClassHelper.int_TYPE, "__closureIndex");
    ClosureExpression ce = new ClosureExpression(new Parameter[] { closureIndex }, bs);
    ce.setVariableScope(expression.getVariableScope());
    // to keep stack height put a null on stack
    instructions.add(ConstantExpression.NULL);
    // init table
    final Label dflt = new Label();
    final Label tableEnd = new Label();
    final Label[] labels = new Label[size];
    instructions.add(new BytecodeInstruction() {

        public void visit(MethodVisitor mv) {
            mv.visitVarInsn(ILOAD, 1);
            mv.visitTableSwitchInsn(0, size - 1, dflt, labels);
        }
    });
    // visit cases
    for (int i = 0; i < size; i++) {
        final Label label = new Label();
        Object expr = expressions.get(i);
        final boolean isStatement = expr instanceof Statement;
        labels[i] = label;
        instructions.add(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitLabel(label);
                // so expressions need to pop the alibi null
                if (!isStatement)
                    mv.visitInsn(POP);
            }
        });
        instructions.add(expr);
        instructions.add(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitJumpInsn(GOTO, tableEnd);
            }
        });
    }
    // default case
    {
        instructions.add(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitLabel(dflt);
            }
        });
        ConstantExpression text = new ConstantExpression("invalid index for closure");
        ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
        ThrowStatement ts = new ThrowStatement(cce);
        instructions.add(ts);
    }
    // return
    instructions.add(new BytecodeInstruction() {

        public void visit(MethodVisitor mv) {
            mv.visitLabel(tableEnd);
            mv.visitInsn(ARETURN);
        }
    });
    // load main Closure
    visitClosureExpression(ce);
    // we need later an array to store the curried
    // closures, so we create it here and ave it
    // in a temporary variable
    BytecodeHelper.pushConstant(mv, size);
    mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
    int listArrayVar = controller.getCompileStack().defineTemporaryVariable("_listOfClosures", true);
    // add curried versions
    for (int i = 0; i < size; i++) {
        // stack: closure
        // we need to create a curried closure version
        // so we store the type on stack
        mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/CurriedClosure");
        // stack: closure, type
        // for a constructor call we need the type two times
        // and the closure after them
        mv.visitInsn(DUP2);
        mv.visitInsn(SWAP);
        // stack: closure,type,type,closure
        // so we can create the curried closure
        mv.visitInsn(ICONST_1);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitInsn(DUP);
        mv.visitInsn(ICONST_0);
        mv.visitLdcInsn(i);
        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
        mv.visitInsn(AASTORE);
        mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/CurriedClosure", "<init>", "(Lgroovy/lang/Closure;[Ljava/lang/Object;)V", false);
        // stack: closure,curriedClosure
        // we need to save the result
        mv.visitVarInsn(ALOAD, listArrayVar);
        mv.visitInsn(SWAP);
        BytecodeHelper.pushConstant(mv, i);
        mv.visitInsn(SWAP);
        mv.visitInsn(AASTORE);
    // stack: closure
    }
    // we don't need the closure any longer, so remove it
    mv.visitInsn(POP);
    // we load the array and create a list from it
    mv.visitVarInsn(ALOAD, listArrayVar);
    createListMethod.call(mv);
    // remove the temporary variable to keep the
    // stack clean
    controller.getCompileStack().removeVar(listArrayVar);
    controller.getOperandStack().pop();
}
Also used : CaseStatement(org.codehaus.groovy.ast.stmt.CaseStatement) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) AssertStatement(org.codehaus.groovy.ast.stmt.AssertStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) WhileStatement(org.codehaus.groovy.ast.stmt.WhileStatement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ThrowStatement(org.codehaus.groovy.ast.stmt.ThrowStatement) DoWhileStatement(org.codehaus.groovy.ast.stmt.DoWhileStatement) ContinueStatement(org.codehaus.groovy.ast.stmt.ContinueStatement) BreakStatement(org.codehaus.groovy.ast.stmt.BreakStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) SynchronizedStatement(org.codehaus.groovy.ast.stmt.SynchronizedStatement) SwitchStatement(org.codehaus.groovy.ast.stmt.SwitchStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) Label(org.objectweb.asm.Label) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) LinkedList(java.util.LinkedList) MethodVisitor(org.objectweb.asm.MethodVisitor) Parameter(org.codehaus.groovy.ast.Parameter) ThrowStatement(org.codehaus.groovy.ast.stmt.ThrowStatement)

Example 58 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class BinaryExpressionHelper method loadInitValue.

private void loadInitValue(ClassNode type) {
    MethodVisitor mv = controller.getMethodVisitor();
    if (ClassHelper.isPrimitiveType(type)) {
        mv.visitLdcInsn(0);
    } else {
        mv.visitInsn(ACONST_NULL);
    }
    controller.getOperandStack().push(type);
}
Also used : MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 59 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class BinaryIntExpressionHelper method writeSpaceship.

/**
     * writes the spaceship operator, type should be COMPARE_TO
     * @param type the token type
     * @return true if a successful spaceship operator write
     */
protected boolean writeSpaceship(int type, boolean simulate) {
    if (type != COMPARE_TO)
        return false;
    /*  
           we will actually do
         
          (x < y) ? -1 : ((x == y) ? 0 : 1)
          which is the essence of what the call with Integers would do
          this compiles to something along
          
              <x>
              <y>
              IF_ICMPGE L1
              ICONST_M1
              GOTO L2
          L1
              <x>
              <y>
              IF_ICMPNE L3
              ICONST_0
              GOTO L2
          L3
              ICONST_1
          L2
          
          since the operators are already on the stack and we don't want
          to load them again, we will instead duplicate them. This will
          require some pop actions in the branches!
          
              DUP2          (operands: IIII) 
              IF_ICMPGE L1  (operands: II)
              ICONST_M1     (operands: III)
              GOTO L2
          L1
              -----         (operands: II)
              IF_ICMPNE L3  (operands: -)
              ICONST_0      (operands: I)
              GOTO L2
          L3
              - jump from L1 branch to here (operands: -)
              ICONST_1      (operands: I)
          L2  
          - if jump from GOTO L2 we have III, but need only I
          - if from L3 branch we get only I
          
          this means we have to pop of II before loading -1
          
        */
    if (!simulate) {
        MethodVisitor mv = getController().getMethodVisitor();
        // duplicate int arguments
        mv.visitInsn(DUP2);
        Label l1 = new Label();
        mv.visitJumpInsn(IF_ICMPGE, l1);
        // no jump, so -1, need to pop off surplus II
        mv.visitInsn(POP2);
        mv.visitInsn(ICONST_M1);
        Label l2 = new Label();
        mv.visitJumpInsn(GOTO, l2);
        mv.visitLabel(l1);
        Label l3 = new Label();
        mv.visitJumpInsn(IF_ICMPNE, l3);
        mv.visitInsn(ICONST_0);
        mv.visitJumpInsn(GOTO, l2);
        mv.visitLabel(l3);
        mv.visitInsn(ICONST_1);
        getController().getOperandStack().replace(ClassHelper.int_TYPE, 2);
    }
    return true;
}
Also used : Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 60 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class ClosureWriter method addGeneratedClosureConstructorCall.

public boolean addGeneratedClosureConstructorCall(ConstructorCallExpression call) {
    ClassNode classNode = controller.getClassNode();
    if (!classNode.declaresInterface(ClassHelper.GENERATED_CLOSURE_Type))
        return false;
    AsmClassGenerator acg = controller.getAcg();
    OperandStack operandStack = controller.getOperandStack();
    MethodVisitor mv = controller.getMethodVisitor();
    mv.visitVarInsn(ALOAD, 0);
    ClassNode callNode = classNode.getSuperClass();
    TupleExpression arguments = (TupleExpression) call.getArguments();
    if (arguments.getExpressions().size() != 2)
        throw new GroovyBugError("expected 2 arguments for closure constructor super call, but got" + arguments.getExpressions().size());
    arguments.getExpression(0).visit(acg);
    operandStack.box();
    arguments.getExpression(1).visit(acg);
    operandStack.box();
    //TODO: replace with normal String, p not needed
    Parameter p = new Parameter(ClassHelper.OBJECT_TYPE, "_p");
    String descriptor = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, new Parameter[] { p, p });
    mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(callNode), "<init>", descriptor, false);
    operandStack.remove(2);
    return true;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) GroovyBugError(org.codehaus.groovy.GroovyBugError) Parameter(org.codehaus.groovy.ast.Parameter) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

MethodVisitor (org.objectweb.asm.MethodVisitor)630 Label (org.objectweb.asm.Label)186 ClassWriter (org.objectweb.asm.ClassWriter)116 Type (org.objectweb.asm.Type)59 ClassNode (org.codehaus.groovy.ast.ClassNode)57 FieldVisitor (org.objectweb.asm.FieldVisitor)56 ClassVisitor (org.objectweb.asm.ClassVisitor)47 ClassReader (org.objectweb.asm.ClassReader)43 ArrayList (java.util.ArrayList)32 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)30 Test (org.junit.Test)29 AnnotationVisitor (org.objectweb.asm.AnnotationVisitor)29 List (java.util.List)23 LinkedList (java.util.LinkedList)22 Parameter (org.codehaus.groovy.ast.Parameter)22 InterfaceHelperClassNode (org.codehaus.groovy.ast.InterfaceHelperClassNode)18 AsmClassGenerator (org.codehaus.groovy.classgen.AsmClassGenerator)18 BytecodeExpression (org.codehaus.groovy.classgen.BytecodeExpression)18 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)17 Method (java.lang.reflect.Method)16