Search in sources :

Example 76 with MethodVisitor

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

the class StatementWriter method writeDoWhileLoop.

public void writeDoWhileLoop(DoWhileStatement loop) {
    controller.getAcg().onLineNumber(loop, "visitDoWhileLoop");
    writeStatementLabel(loop);
    MethodVisitor mv = controller.getMethodVisitor();
    controller.getCompileStack().pushLoop(loop.getStatementLabels());
    Label breakLabel = controller.getCompileStack().getBreakLabel();
    Label continueLabel = controller.getCompileStack().getContinueLabel();
    mv.visitLabel(continueLabel);
    loop.getLoopBlock().visit(controller.getAcg());
    loop.getBooleanExpression().visit(controller.getAcg());
    controller.getOperandStack().jump(IFEQ, continueLabel);
    mv.visitLabel(breakLabel);
    controller.getCompileStack().pop();
}
Also used : Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 77 with MethodVisitor

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

the class CompileStack method clear.

/**
     * Clears the state of the class. This method should be called
     * after a MethodNode is visited. Note that a call to init will
     * fail if clear is not called before
     */
public void clear() {
    if (stateStack.size() > 1) {
        int size = stateStack.size() - 1;
        throw new GroovyBugError("the compile stack contains " + size + " more push instruction" + (size == 1 ? "" : "s") + " than pops.");
    }
    if (lhsStack.size() > 1) {
        int size = lhsStack.size() - 1;
        throw new GroovyBugError("lhs stack is supposed to be empty, but has " + size + " elements left.");
    }
    if (implicitThisStack.size() > 1) {
        int size = implicitThisStack.size() - 1;
        throw new GroovyBugError("implicit 'this' stack is supposed to be empty, but has " + size + " elements left.");
    }
    clear = true;
    MethodVisitor mv = controller.getMethodVisitor();
    // br experiment with local var table so debuggers can retrieve variable names
    if (true) {
        //AsmClassGenerator.CREATE_DEBUG_INFO) {
        if (thisEndLabel == null)
            setEndLabels();
        if (!scope.isInStaticContext()) {
            // write "this"
            mv.visitLocalVariable("this", className, null, thisStartLabel, thisEndLabel, 0);
        }
        for (Iterator iterator = usedVariables.iterator(); iterator.hasNext(); ) {
            BytecodeVariable v = (BytecodeVariable) iterator.next();
            ClassNode t = v.getType();
            if (v.isHolder())
                t = ClassHelper.REFERENCE_TYPE;
            String type = BytecodeHelper.getTypeDescription(t);
            Label start = v.getStartLabel();
            Label end = v.getEndLabel();
            mv.visitLocalVariable(v.getName(), type, null, start, end, v.getIndex());
        }
    }
    //exception table writing
    for (ExceptionTableEntry ep : typedExceptions) {
        mv.visitTryCatchBlock(ep.start, ep.end, ep.goal, ep.sig);
    }
    //exception table writing
    for (ExceptionTableEntry ep : untypedExceptions) {
        mv.visitTryCatchBlock(ep.start, ep.end, ep.goal, ep.sig);
    }
    pop();
    typedExceptions.clear();
    untypedExceptions.clear();
    stackVariables.clear();
    usedVariables.clear();
    scope = null;
    finallyBlocks.clear();
    resetVariableIndex(false);
    superBlockNamedLabels.clear();
    currentBlockNamedLabels.clear();
    namedLoopBreakLabel.clear();
    namedLoopContinueLabel.clear();
    continueLabel = null;
    breakLabel = null;
    thisStartLabel = null;
    thisEndLabel = null;
    mv = null;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) GroovyBugError(org.codehaus.groovy.GroovyBugError) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 78 with MethodVisitor

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

the class InvocationWriter method prepareConstructorCall.

protected String prepareConstructorCall(ConstructorNode cn) {
    String owner = BytecodeHelper.getClassInternalName(cn.getDeclaringClass());
    MethodVisitor mv = controller.getMethodVisitor();
    mv.visitTypeInsn(NEW, owner);
    mv.visitInsn(DUP);
    return owner;
}
Also used : MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 79 with MethodVisitor

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

the class InvocationWriter method writeDirectMethodCall.

protected boolean writeDirectMethodCall(MethodNode target, boolean implicitThis, Expression receiver, TupleExpression args) {
    if (target == null)
        return false;
    String methodName = target.getName();
    CompileStack compileStack = controller.getCompileStack();
    OperandStack operandStack = controller.getOperandStack();
    ClassNode declaringClass = target.getDeclaringClass();
    ClassNode classNode = controller.getClassNode();
    MethodVisitor mv = controller.getMethodVisitor();
    int opcode = INVOKEVIRTUAL;
    if (target.isStatic()) {
        opcode = INVOKESTATIC;
    } else if (target.isPrivate() || ((receiver instanceof VariableExpression && ((VariableExpression) receiver).isSuperExpression()))) {
        opcode = INVOKESPECIAL;
    } else if (declaringClass.isInterface()) {
        opcode = INVOKEINTERFACE;
    }
    // handle receiver
    int argumentsToRemove = 0;
    if (opcode != INVOKESTATIC) {
        if (receiver != null) {
            // todo: fix inner class case
            if (implicitThis && !classNode.isDerivedFrom(declaringClass) && !classNode.implementsInterface(declaringClass) && classNode instanceof InnerClassNode) {
                // we are calling an outer class method
                compileStack.pushImplicitThis(false);
                if (controller.isInClosure()) {
                    new VariableExpression("thisObject").visit(controller.getAcg());
                } else {
                    Expression expr = new PropertyExpression(new ClassExpression(declaringClass), "this");
                    expr.visit(controller.getAcg());
                }
            } else {
                compileStack.pushImplicitThis(implicitThis);
                receiver.visit(controller.getAcg());
            }
            operandStack.doGroovyCast(declaringClass);
            compileStack.popImplicitThis();
            argumentsToRemove++;
        } else {
            mv.visitIntInsn(ALOAD, 0);
            operandStack.push(classNode);
            argumentsToRemove++;
        }
    }
    int stackSize = operandStack.getStackLength();
    String owner = BytecodeHelper.getClassInternalName(declaringClass);
    ClassNode receiverType = receiver != null ? controller.getTypeChooser().resolveType(receiver, classNode) : declaringClass;
    if (opcode == INVOKEVIRTUAL && ClassHelper.OBJECT_TYPE.equals(declaringClass)) {
        // avoid using a narrowed type if the method is defined on object because it can interfere
        // with delegate type inference in static compilation mode and trigger a ClassCastException
        receiverType = declaringClass;
    }
    if (opcode == INVOKEVIRTUAL) {
        if (!receiverType.equals(declaringClass) && !ClassHelper.OBJECT_TYPE.equals(declaringClass) && !receiverType.isArray() && !receiverType.isInterface() && // e.g int.getClass()
        !ClassHelper.isPrimitiveType(receiverType) && receiverType.isDerivedFrom(declaringClass)) {
            owner = BytecodeHelper.getClassInternalName(receiverType);
            ClassNode top = operandStack.getTopOperand();
            if (!receiverType.equals(top)) {
                mv.visitTypeInsn(CHECKCAST, owner);
            }
        } else if (target.isPublic() && (!Modifier.isPublic(declaringClass.getModifiers()) && !receiverType.equals(declaringClass)) && receiverType.isDerivedFrom(declaringClass) && !receiverType.getPackageName().equals(classNode.getPackageName())) {
            // package private class, public method
            // see GROOVY-6962
            owner = BytecodeHelper.getClassInternalName(receiverType);
        }
    }
    loadArguments(args.getExpressions(), target.getParameters());
    String desc = BytecodeHelper.getMethodDescriptor(target.getReturnType(), target.getParameters());
    mv.visitMethodInsn(opcode, owner, methodName, desc, opcode == INVOKEINTERFACE);
    ClassNode ret = target.getReturnType().redirect();
    if (ret == ClassHelper.VOID_TYPE) {
        ret = ClassHelper.OBJECT_TYPE;
        mv.visitInsn(ACONST_NULL);
    }
    argumentsToRemove += (operandStack.getStackLength() - stackSize);
    controller.getOperandStack().remove(argumentsToRemove);
    controller.getOperandStack().push(ret);
    return true;
}
Also used : MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 80 with MethodVisitor

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

the class InvocationWriter method castNonPrimitiveToBool.

public void castNonPrimitiveToBool(ClassNode last) {
    MethodVisitor mv = controller.getMethodVisitor();
    BytecodeHelper.unbox(mv, ClassHelper.boolean_TYPE);
}
Also used : 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