Search in sources :

Example 21 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 22 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)

Example 23 with MethodVisitor

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

the class InvocationWriter method finnishConstructorCall.

protected void finnishConstructorCall(ConstructorNode cn, String ownerDescriptor, int argsToRemove) {
    String desc = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, cn.getParameters());
    MethodVisitor mv = controller.getMethodVisitor();
    mv.visitMethodInsn(INVOKESPECIAL, ownerDescriptor, "<init>", desc, false);
    controller.getOperandStack().remove(argsToRemove);
    controller.getOperandStack().push(cn.getDeclaringClass());
}
Also used : MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 24 with MethodVisitor

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

the class InvocationWriter method coerce.

public void coerce(ClassNode from, ClassNode target) {
    if (from.isDerivedFrom(target))
        return;
    MethodVisitor mv = controller.getMethodVisitor();
    OperandStack os = controller.getOperandStack();
    os.box();
    (new ClassExpression(target)).visit(controller.getAcg());
    os.remove(1);
    asTypeMethod.call(mv);
    BytecodeHelper.doCast(mv, target);
    os.replace(target);
}
Also used : MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 25 with MethodVisitor

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

the class OperandStack method load.

public void load(ClassNode type, int idx) {
    MethodVisitor mv = controller.getMethodVisitor();
    BytecodeHelper.load(mv, type, idx);
    push(type);
}
Also used : MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

MethodVisitor (org.objectweb.asm.MethodVisitor)403 Label (org.objectweb.asm.Label)114 ClassNode (org.codehaus.groovy.ast.ClassNode)57 ClassWriter (org.objectweb.asm.ClassWriter)33 Type (org.objectweb.asm.Type)33 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)30 ArrayList (java.util.ArrayList)27 Test (org.junit.Test)23 ClassVisitor (org.objectweb.asm.ClassVisitor)23 Parameter (org.codehaus.groovy.ast.Parameter)22 LinkedList (java.util.LinkedList)19 InterfaceHelperClassNode (org.codehaus.groovy.ast.InterfaceHelperClassNode)18 AsmClassGenerator (org.codehaus.groovy.classgen.AsmClassGenerator)18 BytecodeExpression (org.codehaus.groovy.classgen.BytecodeExpression)18 FieldVisitor (org.objectweb.asm.FieldVisitor)18 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)17 ClassReader (org.objectweb.asm.ClassReader)17 List (java.util.List)16 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)16 MethodDescription (net.bytebuddy.description.method.MethodDescription)15