Search in sources :

Example 31 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy-core by groovy.

the class CallSiteWriter method generateGetCallSiteArray.

private void generateGetCallSiteArray() {
    int visibility = (controller.getClassNode() instanceof InterfaceHelperClassNode) ? MOD_PUBSS : MOD_PRIVSS;
    MethodVisitor mv = controller.getClassVisitor().visitMethod(visibility, GET_CALLSITE_METHOD, GET_CALLSITE_DESC, null, null);
    controller.setMethodVisitor(mv);
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, controller.getInternalClassName(), "$callSiteArray", "Ljava/lang/ref/SoftReference;");
    Label l0 = new Label();
    mv.visitJumpInsn(IFNULL, l0);
    mv.visitFieldInsn(GETSTATIC, controller.getInternalClassName(), "$callSiteArray", "Ljava/lang/ref/SoftReference;");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ref/SoftReference", "get", "()Ljava/lang/Object;", false);
    mv.visitTypeInsn(CHECKCAST, "org/codehaus/groovy/runtime/callsite/CallSiteArray");
    mv.visitInsn(DUP);
    mv.visitVarInsn(ASTORE, 0);
    Label l1 = new Label();
    mv.visitJumpInsn(IFNONNULL, l1);
    mv.visitLabel(l0);
    mv.visitMethodInsn(INVOKESTATIC, controller.getInternalClassName(), "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", false);
    mv.visitVarInsn(ASTORE, 0);
    mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference");
    mv.visitInsn(DUP);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V", false);
    mv.visitFieldInsn(PUTSTATIC, controller.getInternalClassName(), "$callSiteArray", "Ljava/lang/ref/SoftReference;");
    mv.visitLabel(l1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "array", "[Lorg/codehaus/groovy/runtime/callsite/CallSite;");
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 32 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy-core by groovy.

the class Verifier method addGroovyObjectInterfaceAndMethods.

protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
    if (!node.isDerivedFromGroovyObject())
        node.addInterface(ClassHelper.make(GroovyObject.class));
    FieldNode metaClassField = getMetaClassField(node);
    if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
        metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
        addMethod(node, !Modifier.isAbstract(node.getModifiers()), "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                Label nullLabel = new Label();
                /**
                             *  the code is:
                             *  if (this.metaClass==null) {
                             *      this.metaClass = this.$getStaticMetaClass
                             *      return this.metaClass
                             *  } else {
                             *      return this.metaClass
                             *  }
                             *  with the optimization that the result of the
                             *  first this.metaClass is duped on the operand
                             *  stack and reused for the return in the else part
                             */
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitInsn(DUP);
                mv.visitJumpInsn(IFNULL, nullLabel);
                mv.visitInsn(ARETURN);
                mv.visitLabel(nullLabel);
                mv.visitInsn(POP);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitInsn(DUP);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitInsn(ARETURN);
            }
        }));
    }
    Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
    if (!node.hasMethod("setMetaClass", parameters)) {
        metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
        Statement setMetaClassCode;
        if (Modifier.isFinal(metaClassField.getModifiers())) {
            ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
            ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
            setMetaClassCode = new ExpressionStatement(cce);
        } else {
            List list = new ArrayList();
            list.add(new BytecodeInstruction() {

                public void visit(MethodVisitor mv) {
                    /**
                         * the code is (meta class is stored in 1):
                         * this.metaClass = <1>
                         */
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                    mv.visitInsn(RETURN);
                }
            });
            setMetaClassCode = new BytecodeSequence(list);
        }
        addMethod(node, !Modifier.isAbstract(node.getModifiers()), "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
    }
    if (!node.hasMethod("invokeMethod", INVOKE_METHOD_PARAMS)) {
        VariableExpression vMethods = new VariableExpression("method");
        VariableExpression vArguments = new VariableExpression("arguments");
        VariableScope blockScope = new VariableScope();
        blockScope.putReferencedLocalVariable(vMethods);
        blockScope.putReferencedLocalVariable(vArguments);
        addMethod(node, !Modifier.isAbstract(node.getModifiers()), "invokeMethod", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, INVOKE_METHOD_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true);
                mv.visitInsn(ARETURN);
            }
        }));
    }
    if (!node.hasMethod("getProperty", GET_PROPERTY_PARAMS)) {
        addMethod(node, !Modifier.isAbstract(node.getModifiers()), "getProperty", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, GET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true);
                mv.visitInsn(ARETURN);
            }
        }));
    }
    if (!node.hasMethod("setProperty", SET_PROPERTY_PARAMS)) {
        addMethod(node, !Modifier.isAbstract(node.getModifiers()), "setProperty", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true);
                mv.visitInsn(RETURN);
            }
        }));
    }
}
Also used : Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Label(org.objectweb.asm.Label) ArrayList(java.util.ArrayList) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) MethodVisitor(org.objectweb.asm.MethodVisitor) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ArrayList(java.util.ArrayList) List(java.util.List)

Example 33 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy-core by groovy.

the class StaticInvocationWriter method makeCall.

@Override
public void makeCall(final Expression origin, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe, final boolean implicitThis) {
    ClassNode dynamicCallReturnType = origin.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION);
    if (dynamicCallReturnType != null) {
        StaticTypesWriterController staticController = (StaticTypesWriterController) controller;
        if (origin instanceof MethodCallExpression) {
            ((MethodCallExpression) origin).setMethodTarget(null);
        }
        InvocationWriter dynamicInvocationWriter = staticController.getRegularInvocationWriter();
        dynamicInvocationWriter.makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
        return;
    }
    if (tryImplicitReceiver(origin, message, arguments, adapter, safe, spreadSafe, implicitThis)) {
        return;
    }
    // if call is spread safe, replace it with a for in loop
    if (spreadSafe && origin instanceof MethodCallExpression) {
        MethodVisitor mv = controller.getMethodVisitor();
        CompileStack compileStack = controller.getCompileStack();
        TypeChooser typeChooser = controller.getTypeChooser();
        OperandStack operandStack = controller.getOperandStack();
        ClassNode classNode = controller.getClassNode();
        int counter = labelCounter.incrementAndGet();
        // create an empty arraylist
        VariableExpression result = new VariableExpression("spreadresult" + counter, StaticCompilationVisitor.ARRAYLIST_CLASSNODE);
        ConstructorCallExpression cce = new ConstructorCallExpression(StaticCompilationVisitor.ARRAYLIST_CLASSNODE, ArgumentListExpression.EMPTY_ARGUMENTS);
        cce.setNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, StaticCompilationVisitor.ARRAYLIST_CONSTRUCTOR);
        DeclarationExpression declr = new DeclarationExpression(result, Token.newSymbol("=", origin.getLineNumber(), origin.getColumnNumber()), cce);
        declr.visit(controller.getAcg());
        operandStack.pop();
        // if (receiver != null)
        receiver.visit(controller.getAcg());
        Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
        mv.visitJumpInsn(IFNULL, ifnull);
        // receiver consumed by if()
        operandStack.remove(1);
        Label nonull = compileStack.createLocalLabel("nonull_" + counter);
        mv.visitLabel(nonull);
        ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(typeChooser.resolveType(receiver, classNode));
        Parameter iterator = new Parameter(componentType, "for$it$" + counter);
        VariableExpression iteratorAsVar = new VariableExpression(iterator);
        MethodCallExpression origMCE = (MethodCallExpression) origin;
        MethodCallExpression newMCE = new MethodCallExpression(iteratorAsVar, origMCE.getMethodAsString(), origMCE.getArguments());
        newMCE.setImplicitThis(false);
        newMCE.setMethodTarget(origMCE.getMethodTarget());
        newMCE.setSafe(true);
        MethodCallExpression add = new MethodCallExpression(result, "add", newMCE);
        add.setImplicitThis(false);
        add.setMethodTarget(StaticCompilationVisitor.ARRAYLIST_ADD_METHOD);
        // for (e in receiver) { result.add(e?.method(arguments) }
        ForStatement stmt = new ForStatement(iterator, receiver, new ExpressionStatement(add));
        stmt.visit(controller.getAcg());
        // else { empty list }
        mv.visitLabel(ifnull);
        // end of if/else
        // return result list
        result.visit(controller.getAcg());
    } else if (safe && origin instanceof MethodCallExpression) {
        // wrap call in an IFNULL check
        MethodVisitor mv = controller.getMethodVisitor();
        CompileStack compileStack = controller.getCompileStack();
        OperandStack operandStack = controller.getOperandStack();
        int counter = labelCounter.incrementAndGet();
        // if (receiver != null)
        ExpressionAsVariableSlot slot = new ExpressionAsVariableSlot(controller, receiver);
        slot.visit(controller.getAcg());
        operandStack.box();
        Label ifnull = compileStack.createLocalLabel("ifnull_" + counter);
        mv.visitJumpInsn(IFNULL, ifnull);
        // receiver consumed by if()
        operandStack.remove(1);
        Label nonull = compileStack.createLocalLabel("nonull_" + counter);
        mv.visitLabel(nonull);
        MethodCallExpression origMCE = (MethodCallExpression) origin;
        MethodCallExpression newMCE = new MethodCallExpression(new VariableSlotLoader(slot.getType(), slot.getIndex(), controller.getOperandStack()), origMCE.getMethodAsString(), origMCE.getArguments());
        MethodNode methodTarget = origMCE.getMethodTarget();
        newMCE.setMethodTarget(methodTarget);
        newMCE.setSafe(false);
        newMCE.setImplicitThis(origMCE.isImplicitThis());
        newMCE.setSourcePosition(origMCE);
        newMCE.visit(controller.getAcg());
        compileStack.removeVar(slot.getIndex());
        ClassNode returnType = operandStack.getTopOperand();
        if (ClassHelper.isPrimitiveType(returnType) && !ClassHelper.VOID_TYPE.equals(returnType)) {
            operandStack.box();
        }
        Label endof = compileStack.createLocalLabel("endof_" + counter);
        mv.visitJumpInsn(GOTO, endof);
        mv.visitLabel(ifnull);
        // else { null }
        mv.visitInsn(ACONST_NULL);
        mv.visitLabel(endof);
    } else {
        if ((adapter == AsmClassGenerator.getGroovyObjectField || adapter == AsmClassGenerator.getField) && origin instanceof AttributeExpression) {
            String pname = ((PropertyExpression) origin).getPropertyAsString();
            CallSiteWriter callSiteWriter = controller.getCallSiteWriter();
            if (pname != null && callSiteWriter instanceof StaticTypesCallSiteWriter) {
                StaticTypesCallSiteWriter stcsw = (StaticTypesCallSiteWriter) callSiteWriter;
                TypeChooser typeChooser = controller.getTypeChooser();
                if (stcsw.makeGetField(receiver, typeChooser.resolveType(receiver, controller.getClassNode()), pname, safe, false, true)) {
                    return;
                }
            }
        }
        super.makeCall(origin, receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement)

Example 34 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy-core by groovy.

the class StaticInvocationWriter method loadArguments.

protected void loadArguments(List<Expression> argumentList, Parameter[] para) {
    if (para.length == 0)
        return;
    ClassNode lastParaType = para[para.length - 1].getOriginType();
    AsmClassGenerator acg = controller.getAcg();
    TypeChooser typeChooser = controller.getTypeChooser();
    OperandStack operandStack = controller.getOperandStack();
    ClassNode lastArgType = argumentList.size() > 0 ? typeChooser.resolveType(argumentList.get(argumentList.size() - 1), controller.getClassNode()) : null;
    if (lastParaType.isArray() && ((argumentList.size() > para.length) || ((argumentList.size() == (para.length - 1)) && !lastParaType.equals(lastArgType)) || ((argumentList.size() == para.length && lastArgType != null && !lastArgType.isArray()) && (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(lastArgType, lastParaType.getComponentType()))) || ClassHelper.GSTRING_TYPE.equals(lastArgType) && ClassHelper.STRING_TYPE.equals(lastParaType.getComponentType()))) {
        int stackLen = operandStack.getStackLength() + argumentList.size();
        MethodVisitor mv = controller.getMethodVisitor();
        MethodVisitor orig = mv;
        //mv = new org.objectweb.asm.util.TraceMethodVisitor(mv);
        controller.setMethodVisitor(mv);
        // first parameters as usual
        for (int i = 0; i < para.length - 1; i++) {
            Expression expression = argumentList.get(i);
            expression.visit(acg);
            if (!isNullConstant(expression)) {
                operandStack.doGroovyCast(para[i].getType());
            }
        }
        // last parameters wrapped in an array
        List<Expression> lastParams = new LinkedList<Expression>();
        for (int i = para.length - 1; i < argumentList.size(); i++) {
            lastParams.add(argumentList.get(i));
        }
        ArrayExpression array = new ArrayExpression(lastParaType.getComponentType(), lastParams);
        array.visit(acg);
        // adjust stack length
        while (operandStack.getStackLength() < stackLen) {
            operandStack.push(ClassHelper.OBJECT_TYPE);
        }
        if (argumentList.size() == para.length - 1) {
            operandStack.remove(1);
        }
    } else if (argumentList.size() == para.length) {
        for (int i = 0; i < argumentList.size(); i++) {
            Expression expression = argumentList.get(i);
            expression.visit(acg);
            if (!isNullConstant(expression)) {
                operandStack.doGroovyCast(para[i].getType());
            }
        }
    } else {
        // method call with default arguments
        ClassNode classNode = controller.getClassNode();
        Expression[] arguments = new Expression[para.length];
        for (int i = 0, j = 0; i < para.length; i++) {
            Parameter curParam = para[i];
            ClassNode curParamType = curParam.getType();
            Expression curArg = j < argumentList.size() ? argumentList.get(j) : null;
            Expression initialExpression = (Expression) curParam.getNodeMetaData(StaticTypesMarker.INITIAL_EXPRESSION);
            if (initialExpression == null && curParam.hasInitialExpression())
                initialExpression = curParam.getInitialExpression();
            if (initialExpression == null && curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION) != null) {
                initialExpression = (Expression) curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION);
            }
            ClassNode curArgType = curArg == null ? null : typeChooser.resolveType(curArg, classNode);
            if (initialExpression != null && !compatibleArgumentType(curArgType, curParamType)) {
                // use default expression
                arguments[i] = initialExpression;
            } else {
                arguments[i] = curArg;
                j++;
            }
        }
        for (int i = 0; i < arguments.length; i++) {
            Expression expression = arguments[i];
            expression.visit(acg);
            if (!isNullConstant(expression)) {
                operandStack.doGroovyCast(para[i].getType());
            }
        }
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Parameter(org.codehaus.groovy.ast.Parameter) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator) LinkedList(java.util.LinkedList) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 35 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy-core by groovy.

the class StaticInvocationWriter method writeDirectMethodCall.

@Override
protected boolean writeDirectMethodCall(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args) {
    if (target == null)
        return false;
    if (target instanceof ExtensionMethodNode) {
        ExtensionMethodNode emn = (ExtensionMethodNode) target;
        MethodNode node = emn.getExtensionMethodNode();
        String methodName = target.getName();
        MethodVisitor mv = controller.getMethodVisitor();
        int argumentsToRemove = 0;
        List<Expression> argumentList = new LinkedList<Expression>(args.getExpressions());
        if (emn.isStaticExtension()) {
            // it's a static extension method
            argumentList.add(0, ConstantExpression.NULL);
        } else {
            argumentList.add(0, receiver);
        }
        Parameter[] parameters = node.getParameters();
        loadArguments(argumentList, parameters);
        String owner = BytecodeHelper.getClassInternalName(node.getDeclaringClass());
        String desc = BytecodeHelper.getMethodDescriptor(target.getReturnType(), parameters);
        mv.visitMethodInsn(INVOKESTATIC, owner, methodName, desc, false);
        ClassNode ret = target.getReturnType().redirect();
        if (ret == ClassHelper.VOID_TYPE) {
            ret = ClassHelper.OBJECT_TYPE;
            mv.visitInsn(ACONST_NULL);
        }
        argumentsToRemove += argumentList.size();
        controller.getOperandStack().remove(argumentsToRemove);
        controller.getOperandStack().push(ret);
        return true;
    } else {
        if (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS) {
            // wrap arguments into an array
            ArrayExpression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions());
            return super.writeDirectMethodCall(target, implicitThis, receiver, new ArgumentListExpression(arr));
        }
        ClassNode classNode = controller.getClassNode();
        if (classNode.isDerivedFrom(ClassHelper.CLOSURE_TYPE) && controller.isInClosure() && !target.isPublic() && target.getDeclaringClass() != classNode) {
            if (!tryBridgeMethod(target, receiver, implicitThis, args)) {
                // replace call with an invoker helper call
                ArrayExpression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions());
                MethodCallExpression mce = new MethodCallExpression(INVOKERHELER_RECEIVER, target.isStatic() ? "invokeStaticMethod" : "invokeMethodSafe", new ArgumentListExpression(target.isStatic() ? new ClassExpression(target.getDeclaringClass()) : receiver, new ConstantExpression(target.getName()), arr));
                mce.setMethodTarget(target.isStatic() ? INVOKERHELPER_INVOKESTATICMETHOD : INVOKERHELPER_INVOKEMETHOD);
                mce.visit(controller.getAcg());
                return true;
            }
            return true;
        }
        if (target.isPrivate()) {
            if (tryPrivateMethod(target, implicitThis, receiver, args, classNode))
                return true;
        } else if (target.isProtected()) {
            ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
            boolean isThisOrSuper = false;
            if (receiver instanceof VariableExpression) {
                isThisOrSuper = ((VariableExpression) receiver).isThisExpression() || ((VariableExpression) receiver).isSuperExpression();
            }
            if (!implicitThis && !isThisOrSuper && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node, target.getDeclaringClass())) {
                ASTNode src = receiver == null ? args : receiver;
                controller.getSourceUnit().addError(new SyntaxException("Method " + target.getName() + " is protected in " + target.getDeclaringClass().toString(false), src.getLineNumber(), src.getColumnNumber(), src.getLastLineNumber(), src.getLastColumnNumber()));
            }
        }
        if (receiver != null) {
            if (!(receiver instanceof VariableExpression) || !((VariableExpression) receiver).isSuperExpression()) {
                // in order to avoid calls to castToType, which is the dynamic behaviour, we make sure that we call CHECKCAST instead
                // then replace the top operand type
                Expression checkCastReceiver = new CheckcastReceiverExpression(receiver, target);
                return super.writeDirectMethodCall(target, implicitThis, checkCastReceiver, args);
            }
        }
        return super.writeDirectMethodCall(target, implicitThis, receiver, args);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedList(java.util.LinkedList) MethodVisitor(org.objectweb.asm.MethodVisitor) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) SyntaxException(org.codehaus.groovy.syntax.SyntaxException) ASTNode(org.codehaus.groovy.ast.ASTNode) Parameter(org.codehaus.groovy.ast.Parameter) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode)

Aggregations

MethodVisitor (org.objectweb.asm.MethodVisitor)407 Label (org.objectweb.asm.Label)114 ClassNode (org.codehaus.groovy.ast.ClassNode)57 ClassWriter (org.objectweb.asm.ClassWriter)34 Type (org.objectweb.asm.Type)34 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