Search in sources :

Example 11 with AsmClassGenerator

use of org.codehaus.groovy.classgen.AsmClassGenerator in project groovy by apache.

the class BinaryExpressionMultiTypeDispatcher method doAssignmentToArray.

private boolean doAssignmentToArray(BinaryExpression binExp) {
    if (!isAssignmentToArray(binExp))
        return false;
    // we need to handle only assignment to arrays combined with an operation
    // special here. e.g x[a] += b
    int operation = removeAssignment(binExp.getOperation().getType());
    ClassNode current = getController().getClassNode();
    Expression leftExp = binExp.getLeftExpression();
    ClassNode leftType = getController().getTypeChooser().resolveType(leftExp, current);
    Expression rightExp = binExp.getRightExpression();
    ClassNode rightType = getController().getTypeChooser().resolveType(rightExp, current);
    int operationType = getOperandType(leftType);
    BinaryExpressionWriter bew = binExpWriter[operationType];
    boolean simulationSuccess = bew.arrayGet(LEFT_SQUARE_BRACKET, true);
    simulationSuccess = simulationSuccess && bew.write(operation, true);
    simulationSuccess = simulationSuccess && bew.arraySet(true);
    if (!simulationSuccess)
        return false;
    AsmClassGenerator acg = getController().getAcg();
    OperandStack operandStack = getController().getOperandStack();
    CompileStack compileStack = getController().getCompileStack();
    // for x[a] += b we have the structure:
    //   x = left(left(binExp))), b = right(binExp), a = right(left(binExp)))
    // for array set we need these values on stack: array, index, right 
    // for array get we need these values on stack: array, index
    // to eval the expression we need x[a] = x[a]+b
    // -> arraySet(x,a, x[a]+b) 
    // -> arraySet(x,a, arrayGet(x,a,b))
    // --> x,a, x,a, b as operands
    // --> load x, load a, DUP2, call arrayGet, load b, call operation,call arraySet
    // since we cannot DUP2 here easily we will save the subscript and DUP x
    // --> sub=a, load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call arraySet
    BinaryExpression arrayWithSubscript = (BinaryExpression) leftExp;
    Expression subscript = arrayWithSubscript.getRightExpression();
    // load array index: sub=a [load x, DUP, load sub, call arrayGet, load b, call operation, load sub, call arraySet]
    subscript.visit(acg);
    operandStack.doGroovyCast(int_TYPE);
    int subscriptValueId = compileStack.defineTemporaryVariable("$sub", ClassHelper.int_TYPE, true);
    // load array: load x and DUP [load sub, call arrayGet, load b, call operation, load sub, call arraySet] 
    arrayWithSubscript.getLeftExpression().visit(acg);
    operandStack.doGroovyCast(leftType.makeArray());
    operandStack.dup();
    // array get: load sub, call arrayGet [load b, call operation, load sub, call arraySet]
    operandStack.load(ClassHelper.int_TYPE, subscriptValueId);
    bew.arrayGet(LEFT_SQUARE_BRACKET, false);
    operandStack.replace(leftType, 2);
    // complete rhs: load b, call operation [load sub, call arraySet]
    binExp.getRightExpression().visit(acg);
    if (!(bew instanceof BinaryObjectExpressionHelper)) {
        // in primopts we convert to the left type for supported binary operations
        operandStack.doGroovyCast(leftType);
    }
    bew.write(operation, false);
    // let us save that value for the return
    operandStack.dup();
    int resultValueId = compileStack.defineTemporaryVariable("$result", rightType, true);
    // array set: load sub, call arraySet []
    operandStack.load(ClassHelper.int_TYPE, subscriptValueId);
    operandStack.swap();
    bew.arraySet(false);
    // 3 operands, the array, the index and the value!
    operandStack.remove(3);
    // load return value
    operandStack.load(rightType, resultValueId);
    // cleanup
    compileStack.removeVar(resultValueId);
    compileStack.removeVar(subscriptValueId);
    return true;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) Expression(org.codehaus.groovy.ast.expr.Expression) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator)

Example 12 with AsmClassGenerator

use of org.codehaus.groovy.classgen.AsmClassGenerator 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)

Example 13 with AsmClassGenerator

use of org.codehaus.groovy.classgen.AsmClassGenerator in project groovy-core by groovy.

the class ClosureWriter method loadReference.

public static void loadReference(String name, WriterController controller) {
    CompileStack compileStack = controller.getCompileStack();
    MethodVisitor mv = controller.getMethodVisitor();
    ClassNode classNode = controller.getClassNode();
    AsmClassGenerator acg = controller.getAcg();
    // an already declared variable.
    if (!compileStack.containsVariable(name) && compileStack.getScope().isReferencedClassVariable(name)) {
        acg.visitFieldExpression(new FieldExpression(classNode.getDeclaredField(name)));
    } else {
        BytecodeVariable v = compileStack.getVariable(name, !classNodeUsesReferences(controller.getClassNode()));
        if (v == null) {
            // variable is not on stack because we are
            // inside a nested Closure and this variable
            // was not used before
            // then load it from the Closure field
            FieldNode field = classNode.getDeclaredField(name);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, controller.getInternalClassName(), name, BytecodeHelper.getTypeDescription(field.getType()));
        } else {
            mv.visitVarInsn(ALOAD, v.getIndex());
        }
        controller.getOperandStack().push(ClassHelper.REFERENCE_TYPE);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator) MethodVisitor(org.objectweb.asm.MethodVisitor) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression)

Example 14 with AsmClassGenerator

use of org.codehaus.groovy.classgen.AsmClassGenerator in project groovy-core by groovy.

the class BinaryExpressionHelper method evaluateEqual.

public void evaluateEqual(BinaryExpression expression, boolean defineVariable) {
    AsmClassGenerator acg = controller.getAcg();
    CompileStack compileStack = controller.getCompileStack();
    OperandStack operandStack = controller.getOperandStack();
    Expression rightExpression = expression.getRightExpression();
    Expression leftExpression = expression.getLeftExpression();
    ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
    if (defineVariable && rightExpression instanceof EmptyExpression && !(leftExpression instanceof TupleExpression)) {
        VariableExpression ve = (VariableExpression) leftExpression;
        BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false);
        operandStack.loadOrStoreVariable(var, false);
        return;
    }
    // let's evaluate the RHS and store the result
    ClassNode rhsType;
    if (rightExpression instanceof ListExpression && lhsType.isArray()) {
        ListExpression list = (ListExpression) rightExpression;
        ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions());
        array.setSourcePosition(list);
        array.visit(acg);
    } else if (rightExpression instanceof EmptyExpression) {
        rhsType = leftExpression.getType();
        loadInitValue(rhsType);
    } else {
        rightExpression.visit(acg);
    }
    rhsType = operandStack.getTopOperand();
    boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression);
    int rhsValueId;
    if (directAssignment) {
        VariableExpression var = (VariableExpression) leftExpression;
        if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(rhsType)) {
            // GROOVY-5570: if a closure shared variable is a primitive type, it must be boxed
            rhsType = ClassHelper.getWrapper(rhsType);
            operandStack.box();
        }
        // form as it is closure shared
        if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNull(rightExpression)) {
            operandStack.doGroovyCast(var.getOriginType());
            // these two are never reached in bytecode and only there 
            // to avoid verifyerrors and compiler infrastructure hazzle
            operandStack.box();
            operandStack.doGroovyCast(lhsType);
        }
        // normal type transformation 
        if (!ClassHelper.isPrimitiveType(lhsType) && isNull(rightExpression)) {
            operandStack.replace(lhsType);
        } else {
            operandStack.doGroovyCast(lhsType);
        }
        rhsType = lhsType;
        rhsValueId = compileStack.defineVariable(var, lhsType, true).getIndex();
    } else {
        rhsValueId = compileStack.defineTemporaryVariable("$rhs", rhsType, true);
    }
    //TODO: if rhs is VariableSlotLoader already, then skip crating a new one
    BytecodeExpression rhsValueLoader = new VariableSlotLoader(rhsType, rhsValueId, operandStack);
    // assignment for subscript
    if (leftExpression instanceof BinaryExpression) {
        BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
        if (leftBinExpr.getOperation().getType() == Types.LEFT_SQUARE_BRACKET) {
            assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader);
        }
        compileStack.removeVar(rhsValueId);
        return;
    }
    compileStack.pushLHS(true);
    // multiple declaration
    if (leftExpression instanceof TupleExpression) {
        TupleExpression tuple = (TupleExpression) leftExpression;
        int i = 0;
        for (Expression e : tuple.getExpressions()) {
            VariableExpression var = (VariableExpression) e;
            MethodCallExpression call = new MethodCallExpression(rhsValueLoader, "getAt", new ArgumentListExpression(new ConstantExpression(i)));
            call.visit(acg);
            i++;
            if (defineVariable) {
                operandStack.doGroovyCast(var);
                compileStack.defineVariable(var, true);
                operandStack.remove(1);
            } else {
                acg.visitVariableExpression(var);
            }
        }
    } else // single declaration
    if (defineVariable) {
        rhsValueLoader.visit(acg);
        operandStack.remove(1);
        compileStack.popLHS();
        return;
    } else // normal assignment
    {
        int mark = operandStack.getStackLength();
        // to leave a copy of the rightExpression value on the stack after the assignment.
        rhsValueLoader.visit(acg);
        TypeChooser typeChooser = controller.getTypeChooser();
        ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode());
        operandStack.doGroovyCast(targetType);
        leftExpression.visit(acg);
        operandStack.remove(operandStack.getStackLength() - mark);
    }
    compileStack.popLHS();
    // return value of assignment
    rhsValueLoader.visit(acg);
    compileStack.removeVar(rhsValueId);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ElvisOperatorExpression(org.codehaus.groovy.ast.expr.ElvisOperatorExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) TernaryExpression(org.codehaus.groovy.ast.expr.TernaryExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression)

Example 15 with AsmClassGenerator

use of org.codehaus.groovy.classgen.AsmClassGenerator in project groovy-core by groovy.

the class BinaryExpressionHelper method evaluateCompareExpression.

protected void evaluateCompareExpression(MethodCaller compareMethod, BinaryExpression expression) {
    Expression leftExp = expression.getLeftExpression();
    TypeChooser typeChooser = controller.getTypeChooser();
    ClassNode cn = controller.getClassNode();
    ClassNode leftType = typeChooser.resolveType(leftExp, cn);
    Expression rightExp = expression.getRightExpression();
    ClassNode rightType = typeChooser.resolveType(rightExp, cn);
    boolean done = false;
    if (ClassHelper.isPrimitiveType(leftType) && ClassHelper.isPrimitiveType(rightType)) {
        BinaryExpressionMultiTypeDispatcher helper = new BinaryExpressionMultiTypeDispatcher(getController());
        done = helper.doPrimitiveCompare(leftType, rightType, expression);
    }
    if (!done) {
        AsmClassGenerator acg = controller.getAcg();
        OperandStack operandStack = controller.getOperandStack();
        leftExp.visit(acg);
        operandStack.box();
        rightExp.visit(acg);
        operandStack.box();
        compareMethod.call(controller.getMethodVisitor());
        ClassNode resType = ClassHelper.boolean_TYPE;
        if (compareMethod == findRegexMethod) {
            resType = ClassHelper.OBJECT_TYPE;
        }
        operandStack.replace(resType, 2);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ElvisOperatorExpression(org.codehaus.groovy.ast.expr.ElvisOperatorExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) TernaryExpression(org.codehaus.groovy.ast.expr.TernaryExpression) AsmClassGenerator(org.codehaus.groovy.classgen.AsmClassGenerator)

Aggregations

AsmClassGenerator (org.codehaus.groovy.classgen.AsmClassGenerator)45 ClassNode (org.codehaus.groovy.ast.ClassNode)21 MethodVisitor (org.objectweb.asm.MethodVisitor)18 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)14 Expression (org.codehaus.groovy.ast.expr.Expression)14 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)14 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)14 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)10 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)10 FieldExpression (org.codehaus.groovy.ast.expr.FieldExpression)10 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)10 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)10 Label (org.objectweb.asm.Label)10 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)8 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)8 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)8 ElvisOperatorExpression (org.codehaus.groovy.ast.expr.ElvisOperatorExpression)8 EmptyExpression (org.codehaus.groovy.ast.expr.EmptyExpression)8 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)8 PostfixExpression (org.codehaus.groovy.ast.expr.PostfixExpression)8