Example usage for org.objectweb.asm Opcodes DUP

List of usage examples for org.objectweb.asm Opcodes DUP

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes DUP.

Prototype

int DUP

To view the source code for org.objectweb.asm Opcodes DUP.

Click Source Link

Usage

From source file:org.jboss.arquillian.extension.jacoco.container.ArquillianRuntime.java

License:Apache License

public int generateDataAccessor(long classid, String classname, int probecount, MethodVisitor mv) {
    // 1. Create parameter array:
    generateArgumentArray(classid, classname, probecount, mv);
    // stack[0]: [Ljava/lang/Object;

    mv.visitInsn(Opcodes.DUP);

    // stack[1]: [Ljava/lang/Object;
    // stack[0]: [Ljava/lang/Object;

    // 2. Invoke ArquillianRuntime:
    mv.visitMethodInsn(Opcodes.INVOKESTATIC,
            "org/jboss/arquillian/extension/jacoco/container/ArquillianRuntime", "getInstance",
            "()Lorg/jboss/arquillian/extension/jacoco/container/ArquillianRuntime;");

    // stack[2]: LArquillianRuntime;
    // stack[1]: [Ljava/lang/Object;
    // stack[0]: [Ljava/lang/Object;

    mv.visitInsn(Opcodes.SWAP);// w  ww  .  ja  v  a 2 s .  co  m

    // stack[2]: [Ljava/lang/Object;
    // stack[1]: LArquillianRuntime;
    // stack[0]: [Ljava/lang/Object;

    // 3. Invoke ArquillianRuntime swapExecutionData, gets the boolean[] in Object[0]:
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
            "org/jboss/arquillian/extension/jacoco/container/ArquillianRuntime", "swapExecutionData",
            "([Ljava/lang/Object;)V");

    // Stack[0]: [Ljava/lang/Object;

    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitInsn(Opcodes.AALOAD);
    mv.visitTypeInsn(Opcodes.CHECKCAST, InstrSupport.DATAFIELD_DESC);

    // Stack[0]: [Z;

    return 5;
}

From source file:org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.java

License:Open Source License

/**
 * Generates a DUP instruction.
 */
public void dup() {
    visitInsn(Opcodes.DUP);
}

From source file:org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.java

License:Open Source License

private int doReturnOrThrowSave() {
    // allocate a slot for the return or throwable on top of the stack
    // stash the value into the slot and return the slot idx

    int saveValueSlot = newLocal(saveValueType);
    if (saveValueType.getSize() == 2) {
        visitInsn(Opcodes.DUP2);//from w  ww. j a  va2s.  com
    } else {
        visitInsn(Opcodes.DUP);
    }
    storeLocal(saveValueSlot);

    return saveValueSlot;
}

From source file:org.jboss.byteman.rule.expression.ArrayExpression.java

License:Open Source License

@Override
public void compileAssign(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    Type valueType = arrayRef.getType().getBaseType();
    int currentStack = compileContext.getStackCount();
    boolean isTwoWords = (valueType.getNBytes() > 4);
    int toPop = 0;
    int size = (isTwoWords ? 2 : 1);

    // value to be assigned is TOS and will already be coerced to the correct value type
    // copy it so we can install the copy and leave the original as a a return value on the stack
    if (isTwoWords) {
        // [... val1 val2 ==> ... val1 val2 val1 val2]
        mv.visitInsn(Opcodes.DUP2);//w ww . ja  v a2  s.  c o  m
    } else {
        // [... val ==> ... val val]
        mv.visitInsn(Opcodes.DUP);
    }
    compileContext.addStackCount(size);

    // compile load of array reference -- adds 1 to stack height
    arrayRef.compile(mv, compileContext);
    // for each index expression compile the expression and the do an array load
    Iterator<Expression> iterator = idxList.iterator();

    while (iterator.hasNext()) {
        Expression idxExpr = iterator.next();
        if (iterator.hasNext()) {
            // dereference the array to get an embedded array
            // compile expression index -- adds 1 to height
            idxExpr.compile(mv, compileContext);
            // make sure the index is an integer
            compileTypeConversion(idxExpr.getType(), Type.I, mv, compileContext);
            // fetch embedded array pop 2 and add 1
            mv.visitInsn(Opcodes.AALOAD);
            compileContext.addStackCount(-1);
            valueType = valueType.getBaseType();
        } else {
            if (isTwoWords) {
                // stack is [..., val1, val2, val1, val2, aref ] and we want [..., val1, val2, aref, val1, val2 ]
                mv.visitInsn(Opcodes.DUP_X2); // ==>  [..., val1, val2, aref. val1, val2, aref ]
                compileContext.addStackCount(1);
                mv.visitInsn(Opcodes.POP); // ==> [..., val1, val2, aref. val1, val2 ]
                compileContext.addStackCount(-1);
            } else {
                // stack is [..., val, val, aref ] and we want [..., val, aref, val ]
                mv.visitInsn(Opcodes.SWAP);
            }
            // compile expression index -- adds 1 to height
            idxExpr.compile(mv, compileContext);
            // make sure the index is an integer
            compileTypeConversion(idxExpr.getType(), Type.I, mv, compileContext);
            if (isTwoWords) {
                // stack is [..., val1, val2, aref, val1, val2, idx] and we want [..., val1, val2, aref, idx, val1, val2 ]
                mv.visitInsn(Opcodes.DUP_X2); // ==> [..., val1, val2, aref, idx, val1, val2, idx]
                compileContext.addStackCount(1);
                mv.visitInsn(Opcodes.POP); // ==> [..., val1, val2, aref, idx, val1, val2 ]
                compileContext.addStackCount(-1);
            } else {
                // stack is [..., val, aref, val, idx] and we want [..., val, aref, idx, val ]
                mv.visitInsn(Opcodes.SWAP);
            }
            // now we can do the array store
            if (valueType.isObject() || valueType.isArray()) {
                // compile load object - pops 3
                mv.visitInsn(Opcodes.AASTORE);
                toPop = -3;
            } else if (valueType == Type.Z || valueType == Type.B) {
                // compile load byte - pops 3
                mv.visitInsn(Opcodes.BASTORE);
                toPop = -3;
            } else if (valueType == Type.S) {
                // compile load short - pops 3
                mv.visitInsn(Opcodes.SASTORE);
                toPop = -3;
            } else if (valueType == Type.C) {
                // compile load char - pops 3
                mv.visitInsn(Opcodes.CASTORE);
                toPop = -3;
            } else if (valueType == Type.I) {
                // compile load int - pops 3
                mv.visitInsn(Opcodes.IASTORE);
                toPop = -3;
            } else if (valueType == Type.J) {
                // compile load long - pops 4
                mv.visitInsn(Opcodes.LASTORE);
                toPop = -4;
            } else if (valueType == Type.F) {
                // compile load float - pops 3
                mv.visitInsn(Opcodes.FASTORE);
                toPop = -3;
            } else if (valueType == Type.D) {
                // compile load double - pops 4
                mv.visitInsn(Opcodes.DASTORE);
                toPop = -4;
            }
            compileContext.addStackCount(toPop);
            if (iterator.hasNext()) {
                assert valueType.isArray();
                valueType = valueType.getBaseType();
            }
        }
    }

    // check stack height
    if (compileContext.getStackCount() != currentStack) {
        throw new CompileException("ArrayExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + currentStack);
    }

    // we needed room for an aray and an index or for a one or two word result
    // but the recursive evaluations will have made sure the max stack is big enough
    // so there is no need to update the maximum stack height
}

From source file:org.jboss.byteman.rule.expression.ArrayInitExpression.java

License:Open Source License

public void compile(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    Type baseType = getType().getBaseType();
    int currentStack = compileContext.getStackCount();
    int expected = 1;
    int length = elements.size();

    // stack array size and then create the array
    mv.visitLdcInsn(length);//from   w ww  .  ja v  a2s . c  o m
    compileContext.addStackCount(1);
    // new array pops count and pushes array so no change to stack size
    if (baseType.isArray()) {
        mv.visitMultiANewArrayInsn(getType().getInternalName(), 1);
    } else if (baseType.isObject()) {
        mv.visitTypeInsn(Opcodes.ANEWARRAY, baseType.getInternalName());
    } else {
        int operand = 0;
        if (baseType.equals(Type.Z)) {
            operand = Opcodes.T_BOOLEAN;
        } else if (baseType.equals(Type.B)) {
            operand = Opcodes.T_BYTE;
        } else if (baseType.equals(Type.S)) {
            operand = Opcodes.T_SHORT;
        } else if (baseType.equals(Type.C)) {
            operand = Opcodes.T_CHAR;
        } else if (baseType.equals(Type.I)) {
            operand = Opcodes.T_INT;
        } else if (baseType.equals(Type.J)) {
            operand = Opcodes.T_LONG;
        } else if (baseType.equals(Type.F)) {
            operand = Opcodes.T_FLOAT;
        } else if (baseType.equals(Type.D)) {
            operand = Opcodes.T_DOUBLE;
        }
        mv.visitIntInsn(Opcodes.NEWARRAY, operand);
    }

    int idx = 0;
    boolean isTwoWords = (baseType.getNBytes() > 4);

    for (Expression element : elements) {
        int toPop = 0;
        // copy array so we can assign it -- adds one to height
        mv.visitInsn(Opcodes.DUP);
        // compile expression index -- adds 1 to height
        mv.visitLdcInsn(idx++);
        compileContext.addStackCount(2);
        // compile value -- adds one or two words to height
        element.compile(mv, compileContext);
        // ensure we have the correct value type
        compileContext.compileTypeConversion(element.type, baseType);
        // now we can do the array store
        if (baseType.isObject() || baseType.isArray()) {
            // compile load object - pops 3
            mv.visitInsn(Opcodes.AASTORE);
            toPop = -3;
        } else if (baseType == Type.Z || baseType == Type.B) {
            // compile load byte - pops 3
            mv.visitInsn(Opcodes.BASTORE);
            toPop = -3;
        } else if (baseType == Type.S) {
            // compile load short - pops 3
            mv.visitInsn(Opcodes.SASTORE);
            toPop = -3;
        } else if (baseType == Type.C) {
            // compile load char - pops 3
            mv.visitInsn(Opcodes.CASTORE);
            toPop = -3;
        } else if (baseType == Type.I) {
            // compile load int - pops 3
            mv.visitInsn(Opcodes.IASTORE);
            toPop = -3;
        } else if (baseType == Type.J) {
            // compile load long - pops 4
            mv.visitInsn(Opcodes.LASTORE);
            toPop = -4;
        } else if (baseType == Type.F) {
            // compile load float - pops 3
            mv.visitInsn(Opcodes.FASTORE);
            toPop = -3;
        } else if (baseType == Type.D) {
            // compile load double - pops 4
            mv.visitInsn(Opcodes.DASTORE);
            toPop = -4;
        }
        // pop the appropriate number of elements off the stack
        compileContext.addStackCount(toPop);
    }

    // check stack height
    if (compileContext.getStackCount() != currentStack + expected) {
        throw new CompileException("ArrayInitExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + expected));
    }

    // no need to update stack max
}

From source file:org.jboss.byteman.rule.expression.ComparisonExpression.java

License:Open Source License

public void compile(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    Expression oper0 = getOperand(0);
    Expression oper1 = getOperand(1);

    int removed = 0;

    // evaluate the operands and ensure the reuslt is of the correct type for comparison adds 2
    oper0.compile(mv, compileContext);//from  ww w .ja  va2s  . c o  m
    compileTypeConversion(oper0.getType(), comparisonType, mv, compileContext);
    oper1.compile(mv, compileContext);
    compileTypeConversion(oper1.getType(), comparisonType, mv, compileContext);

    // now do the appropriate type of comparison
    if (comparisonType == type.B || comparisonType == type.S || comparisonType == type.S
            || comparisonType == type.I) {
        Label elsetarget = new Label();
        Label endtarget = new Label();
        // we remove 2 words from the stack and then add 1 back
        removed = 2;
        switch (oper) {
        case LT:
            mv.visitJumpInsn(Opcodes.IF_ICMPGE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case LE:
            mv.visitJumpInsn(Opcodes.IF_ICMPGT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GT:
            mv.visitJumpInsn(Opcodes.IF_ICMPLE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GE:
            mv.visitJumpInsn(Opcodes.IF_ICMPLT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case EQ:
            mv.visitJumpInsn(Opcodes.IF_ICMPNE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case NE:
            mv.visitJumpInsn(Opcodes.IF_ICMPEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        }
    } else if (comparisonType == type.J || comparisonType == type.F || comparisonType == type.D) {
        if (comparisonType == type.J) {
            mv.visitInsn(Opcodes.LCMP);
            // we remove four words from the stack and add 1 back
            removed = 4;
        } else if (comparisonType == type.F) {
            // we remove two words from the stack and add 1 back
            removed = 2;
            mv.visitInsn(Opcodes.FCMPG);
        } else if (comparisonType == type.D) {
            // we remove four words from the stack and add 1 back
            removed = 4;
            mv.visitInsn(Opcodes.DCMPG);
        }
        Label elsetarget = new Label();
        Label endtarget = new Label();
        switch (oper) {
        case LT:
            mv.visitJumpInsn(Opcodes.IFGE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case LE:
            mv.visitJumpInsn(Opcodes.IFGT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GT:
            mv.visitJumpInsn(Opcodes.IFLE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GE:
            mv.visitJumpInsn(Opcodes.IFLT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case EQ:
            mv.visitJumpInsn(Opcodes.IFNE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case NE:
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        }
    } else if (comparable) {
        // we add a further two words setting up the relevant test then remove them
        // and also remove the original two words replacing them with a single word
        removed = 4;
        compileContext.addStackCount(2);
        // we need to deal with null values correctly
        // if op1 == null || op2 == null
        // then
        //   EQ:
        //   push value1 == value2
        //   NE:
        //   push value1 != value2
        //   ow:
        //   push false
        // else
        //   execute compareTo or equals and test for the desired outcome
        // end if
        Label splittarget = new Label(); // else
        Label jointarget = new Label(); // end if
        mv.visitInsn(Opcodes.DUP2); // [... op1, op2 ] ==> [... op1, op2, op1,  op2]
        mv.visitInsn(Opcodes.POP); // [... op1, op2, op1, op2 ] ==> [... op1, op2, op1]
        // if op1 == null
        mv.visitJumpInsn(Opcodes.IFNULL, splittarget); // [... op1, op2, op1] ==> [... op1, op2]
        mv.visitInsn(Opcodes.DUP); // [... op1, op2 ] ==> [... op1, op2, op2]
        // || op2 == null
        mv.visitJumpInsn(Opcodes.IFNULL, splittarget); // [... op1, op2, op2] ==> [... op1, op2]
        // so, it is ok to call compareTo leaving an int or equals leaving a boolean
        if (oper != EQ && oper != NE) {
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Comparable", "compareTo",
                    "(Ljava/lang/Object;)I");
        } else {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
        }
        // now if we did a compareTo we need to generate the required boolean
        Label elsetarget = new Label();
        Label endtarget = new Label();
        // if needed the convert the compareTo result to the required boolean outcome
        switch (oper) {
        case LT:
            mv.visitJumpInsn(Opcodes.IFGE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case LE:
            mv.visitJumpInsn(Opcodes.IFGT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GT:
            mv.visitJumpInsn(Opcodes.IFLE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GE:
            mv.visitJumpInsn(Opcodes.IFLT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case NE:
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(true);
            mv.visitLabel(endtarget);
            break;
        }
        // skip to the join point
        mv.visitJumpInsn(Opcodes.GOTO, jointarget);
        // label the split point
        mv.visitLabel(splittarget);
        if (oper == EQ) {
            elsetarget = new Label();
            endtarget = new Label();
            mv.visitJumpInsn(Opcodes.IF_ACMPEQ, elsetarget);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(true);
            mv.visitLabel(endtarget);
        } else if (oper == NE) {
            elsetarget = new Label();
            endtarget = new Label();
            mv.visitJumpInsn(Opcodes.IF_ACMPNE, elsetarget);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(true);
            mv.visitLabel(endtarget);
        } else {
            // pop the operands and stack false
            mv.visitInsn(Opcodes.POP2);
            mv.visitLdcInsn(false);
        }
        // label the join point
        mv.visitLabel(jointarget);
    } else if (comparisonType == Type.Z) {
        // unboxed booleans need special treatment
        // we remove two words replacing them with a single word
        removed = 2;
        Label elsetarget = new Label();
        Label endtarget = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
        // on this branch for EQ the stacked value is what we need and for NE
        // the stacked value needs flipping
        if (oper == NE) {
            Label elsetarget2 = new Label();
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget2);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget2);
            mv.visitLdcInsn(true);
        }
        mv.visitJumpInsn(Opcodes.GOTO, endtarget);
        mv.visitLabel(elsetarget);
        // on this branch for NE the stacked value is what we need and for EQ
        // the stacked value needs flipping
        if (oper == EQ) {
            Label elsetarget2 = new Label();
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget2);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget2);
            mv.visitLdcInsn(true);
        }
        mv.visitLabel(endtarget);

    } else if (comparisonType == Type.BOOLEAN) {
        // boxed booleans need special treatment
        // we remove two words replacing them with a single word
        removed = 2;
        Label elsetarget = new Label();
        Label endtarget = new Label();
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java.lang.Boolean", "equals", "(Ljava/lang/Boolean;)Z");
        if (oper == NE) {
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
        }
    } else {
        // we remove two words replacing them with a single word
        removed = 2;
        Label elsetarget = new Label();
        Label endtarget = new Label();
        if (oper == EQ) {
            mv.visitJumpInsn(Opcodes.IF_ACMPNE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
        } else {
            mv.visitJumpInsn(Opcodes.IF_ACMPEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
        }
    }
    compileContext.addStackCount(1 - removed);
}

From source file:org.jboss.byteman.rule.expression.DollarExpression.java

License:Open Source License

@Override
public void compileAssign(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    String targetName = binding.getName();

    int currentStack = compileContext.getStackCount();
    int size = ((type.getNBytes() > 4) ? 2 : 1);

    if (index == HELPER_IDX) {
        // not allowed to reassign the helper binding
        throw new CompileException("DollarExpression.compileAssign : invalid assignment to helper binding $$");
    } else {/*  w w w.  ja  v a 2s . c om*/
        // value to be assigned is TOS and will already be coerced to the correct value type
        // copy it so we leave it as a a return value on the stack
        if (size == 2) {
            mv.visitInsn(Opcodes.DUP2);
        } else {
            mv.visitInsn(Opcodes.DUP);
        }
        // stack the current helper then insert it below the value
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        if (size == 2) {
            // use a DUP_X2 to push a copy below the value then pop the redundant value
            mv.visitInsn(Opcodes.DUP_X2);
            mv.visitInsn(Opcodes.POP);
        } else {
            // we can just swap the two values
            mv.visitInsn(Opcodes.SWAP);
        }
        // stack the name for the variable and swap below the value
        mv.visitLdcInsn(targetName);
        if (size == 2) {
            // use a DUP_X2 to push a copy below the value then pop the redundant value
            mv.visitInsn(Opcodes.DUP_X2);
            // this is the high water mark
            // at this point the stack has gone from [ .. val1 val2]  to [.. val1 val2 helper name val1 val2 name]
            compileContext.addStackCount(5);
            mv.visitInsn(Opcodes.POP);
            compileContext.addStackCount(-1);
        } else {
            // this is the high water mark
            // at this point the stack has gone from [ .. val]  to [.. val helper val name]
            compileContext.addStackCount(3);
            // we can just swap the two values
            mv.visitInsn(Opcodes.SWAP);
        }
        // ensure we have an object
        compileObjectConversion(type, Type.OBJECT, mv, compileContext);

        // call the setBinding method
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "setBinding",
                "(Ljava/lang/String;Ljava/lang/Object;)V");

        // the call will remove 3 from the stack height
        compileContext.addStackCount(-3);

        // ok, the stack height should be as it was
        if (compileContext.getStackCount() != currentStack) {
            throw new CompileException("variable.compileAssignment : invalid stack height "
                    + compileContext.getStackCount() + " expecting " + currentStack);
        }
    }
}

From source file:org.jboss.byteman.rule.expression.FieldExpression.java

License:Open Source License

@Override
public void compileAssign(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    if (indirectStatic != null) {
        // this is just wrapping a static field expression so compile it
        indirectStatic.compileAssign(mv, compileContext);
    } else {/*from  w  w w .  j  ava 2s .  c  o  m*/
        // make sure we are at the right source line
        compileContext.notifySourceLine(line);

        int currentStack = compileContext.getStackCount();
        int size = (type.getNBytes() > 4 ? 2 : 1);

        // copy the value so we leave it as a result
        if (size == 1) {
            // this means at the maximum we add 1 to the current stack
            // [.. val] ==> [.. val val]
            mv.visitInsn(Opcodes.DUP);
        } else {
            // [.. val1 val2] ==> [.. val1 val2 val1 val2]
            mv.visitInsn(Opcodes.DUP2);
        }
        compileContext.addStackCount(size);
        // compile the owner expression and swap with the value
        owner.compile(mv, compileContext);
        if (size == 1) {
            // [.. val val owner] ==> [.. val owner val]
            mv.visitInsn(Opcodes.SWAP);
        } else {
            // we have to use a DUP_X2 and a POP to insert the owner below the two word value
            // i.e. [.. val1 val2 val1 val2] ==> [.. val1 val2 val1 val2 owner] ==>
            //              [.. val1 val2 owner val1 val2 owner] ==> [.. val1 val2 owner val1 val2]
            mv.visitInsn(Opcodes.DUP_X2);
            compileContext.addStackCount(1);
            mv.visitInsn(Opcodes.POP);
            compileContext.addStackCount(-1);
        }
        if (isPublicField) {
            // now compile a field update
            String ownerType = Type.internalName(field.getDeclaringClass());
            String fieldName = field.getName();
            String fieldType = Type.internalName(field.getType(), true);
            mv.visitFieldInsn(Opcodes.PUTFIELD, ownerType, fieldName, fieldType);
            // we removed the owner and the value
            compileContext.addStackCount(-(1 + size));
        } else {
            // since this is a private field we need to do the update using reflection
            // box the value to an object if necessary
            if (type.isPrimitive()) {
                compileBox(Type.boxType(type), mv, compileContext);
            }
            // stack the helper and then dupx2 it so it goes under the owner and value
            // [.. val(s) owner  valObj ==> val(s) owner valObj helper ]
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            // [.. val(s) owner  valObj helper ==> val(s) helper owner valObj helper ]
            mv.visitInsn(Opcodes.DUP_X2);
            // stack now has 2 more words so count them
            compileContext.addStackCount(2);
            // now pop the redundant top word and stack the field index instead
            // [.. val(s) helper owner valObj helper ==> val(s) helper owner valObj index ]
            mv.visitInsn(Opcodes.POP);
            mv.visitLdcInsn(fieldIndex);
            // use the HelperAdapter method setAccessibleField to set the field value
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class),
                    "setAccessibleField", "(Ljava/lang/Object;Ljava/lang/Object;I)V");
            // we popped four args
            compileContext.addStackCount(-4);
        }

        // check the stack height is ok
        if (compileContext.getStackCount() != currentStack) {
            throw new CompileException("FieldExpression.compileAssign : invalid stack height "
                    + compileContext.getStackCount() + " expecting " + (currentStack));
        }
    }
}

From source file:org.jboss.byteman.rule.expression.MethodExpression.java

License:Open Source License

public void compile(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    int currentStack = compileContext.getStackCount();
    int extraParams = 0; // space used by stacked args after conversion
    int expected = 0;

    // no need for type conversion as return type was derived from method
    if (type.getNBytes() > 4) {
        expected = 2;/*from w w  w.ja v  a 2s  .  c om*/
    } else if (type != Type.VOID) {
        expected = 1;
    } else {
        expected = 0;
    }

    int argCount = arguments.size();

    if (isPublicMethod) {
        // we can just do this as a direct call
        // stack the recipient if necessary then stack the args and then invoke the method
        if (recipient != null) {
            // compile code for recipient
            recipient.compile(mv, compileContext);

            extraParams += 1;
        }

        for (int i = 0; i < argCount; i++) {
            Expression argument = arguments.get(i);
            Type argType = argumentTypes.get(i);
            Type paramType = paramTypes.get(i);
            // compile code to stack argument and type convert if necessary
            argument.compile(mv, compileContext);
            compileTypeConversion(argType, paramType, mv, compileContext);
            // allow for stacked paramType value
            extraParams += (paramType.getNBytes() > 4 ? 2 : 1);
        }

        // enable triggering before we call the method
        // this adds an extra value to the stack so modify the compile context to ensure
        // we increase the maximum height if necessary
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "enableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);

        // ok, now just call the method -- removes extraParams words

        String ownerName = Type.internalName(method.getDeclaringClass());

        if (recipient == null) {
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, ownerName, method.getName(), getDescriptor());
        } else if (method.getDeclaringClass().isInterface()) {
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, ownerName, method.getName(), getDescriptor());
        } else {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ownerName, method.getName(), getDescriptor());
        }
        // decrement the stack height to account for stacked param values (removed) and return value (added)
        compileContext.addStackCount(expected - extraParams);

        // now disable triggering again
        // this temporarily adds an extra value to the stack -- n.b. we *must* increment and
        // then decrement the stack height even though we bumped the max before the call. in
        // some cases the stack may be larger after the method call than before e.g. calling
        // a static which returns a value or calling a non-static which returns a long/double

        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "disableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);
    } else {
        // if we are calling a method by reflection then we need to stack the current helper then
        // the recipient or null if there is none and then build an object array on the stack
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        compileContext.addStackCount(1);
        if (recipient != null) {
            // compile code for recipient
            recipient.compile(mv, compileContext);
        } else {
            mv.visitInsn(Opcodes.ACONST_NULL);
            compileContext.addStackCount(1);
        }

        // stack arg count then create a new array
        mv.visitLdcInsn(argCount);
        compileContext.addStackCount(1);
        // this just swaps one word for another
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");

        // duplicate the array, stack the index, compile code to generate the arg and the do an array put
        for (int i = 0; i < argCount; i++) {
            mv.visitInsn(Opcodes.DUP);
            mv.visitLdcInsn(i);
            // that was two extra words
            compileContext.addStackCount(2);
            Expression argument = arguments.get(i);
            Type argType = argumentTypes.get(i);
            Type paramType = paramTypes.get(i);
            // compile code to stack argument and type convert/box if necessary
            argument.compile(mv, compileContext);
            compileTypeConversion(argType, paramType, mv, compileContext);
            compileBox(paramType, mv, compileContext);
            // that's 3 extra words which now get removed
            mv.visitInsn(Opcodes.AASTORE);
            compileContext.addStackCount(-3);
        }
        // now stack the method object index
        mv.visitLdcInsn(methodIndex);
        compileContext.addStackCount(1);

        // enable triggering before we call the method
        // this adds an extra value to the stack so modify the compile context to ensure
        // we increase the maximum height if necessary
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "enableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);

        // ok, we  now have the recipient, args array and method index on the stack
        // so we can call the HelperAdapter method  to do the actual reflective invocation
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class),
                "invokeAccessibleMethod", "(Ljava/lang/Object;[Ljava/lang/Object;I)Ljava/lang/Object;");
        // we popped 4 words and left one in its place
        compileContext.addStackCount(-3);
        if (type == Type.VOID) {
            mv.visitInsn(Opcodes.POP);
            compileContext.addStackCount(-1);
        } else {
            // do any necessary casting and/or unboxing
            compileTypeConversion(Type.OBJECT, type, mv, compileContext);
        }

        // now disable triggering again
        // this temporarily adds an extra value to the stack -- n.b. no need to increment and
        // then decrement the stack height here because the previous enable call will already have
        // bumped the max when we had 4 slots on the stack and any return value on the stack will
        // occupy at most 2 slots

        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "disableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);
    }

    // ensure we have only increased the stack by the return value size
    if (compileContext.getStackCount() != currentStack + expected) {
        throw new CompileException("MethodExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + expected));
    }

    // no need to update max stack since compiling the  recipient or arguments will
    // have done so (and there will be no change if there was no such compile call)
}

From source file:org.jboss.byteman.rule.expression.NewExpression.java

License:Open Source License

public void compile(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    int currentStack = compileContext.getStackCount();
    int expected = 1;
    int extraParams = 0;

    if (arrayDimCount == 0) {
        // ok, we need to create the new instance and then initialise it.

        // create the new instance -- adds 1 to stack
        String instantiatedClassName = type.getInternalName();
        mv.visitTypeInsn(Opcodes.NEW, instantiatedClassName);
        compileContext.addStackCount(1);
        // copy the exception so we can init it
        mv.visitInsn(Opcodes.DUP);
        compileContext.addStackCount(1);

        int argCount = arguments.size();

        // stack each of the arguments to the constructor
        for (int i = 0; i < argCount; i++) {
            Type argType = argumentTypes.get(i);
            Type paramType = paramTypes.get(i);
            int paramCount = (paramType.getNBytes() > 4 ? 2 : 1);

            // track extra storage used after type conversion
            extraParams += (paramCount);
            arguments.get(i).compile(mv, compileContext);
            compileTypeConversion(argType, paramType, mv, compileContext);
        }/*from w  w w  .j a v a 2  s .c  o  m*/

        // construct the exception
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, instantiatedClassName, "<init>", getDescriptor());

        // modify the stack height to account for the removed exception and params
        compileContext.addStackCount(-(extraParams + 1));
    } else {
        // TODO !!! implement compilation for array types !!!
        if (arrayDimCount == 1) {
            // we can use a NEWARRAY or ANEWARRAY
            Type baseType = type.getBaseType();
            // compile first array dimension adds 1 to stack
            arrayDims.get(0).compile(mv, compileContext);
            // compile new array op -- pops 1 and adds 1 to stack
            if (baseType.isObject()) {
                mv.visitTypeInsn(Opcodes.ANEWARRAY, baseType.getInternalName());
                // } else if (baseType.isArray()) {  // cannot happen!!!
            } else {
                int operand = 0;
                if (baseType.equals(Type.Z)) {
                    operand = Opcodes.T_BOOLEAN;
                } else if (baseType.equals(Type.B)) {
                    operand = Opcodes.T_BYTE;
                } else if (baseType.equals(Type.S)) {
                    operand = Opcodes.T_SHORT;
                } else if (baseType.equals(Type.C)) {
                    operand = Opcodes.T_CHAR;
                } else if (baseType.equals(Type.I)) {
                    operand = Opcodes.T_INT;
                } else if (baseType.equals(Type.J)) {
                    operand = Opcodes.T_LONG;
                } else if (baseType.equals(Type.F)) {
                    operand = Opcodes.T_FLOAT;
                } else if (baseType.equals(Type.D)) {
                    operand = Opcodes.T_DOUBLE;
                }
                mv.visitIntInsn(Opcodes.NEWARRAY, operand);
            }
        } else {
            // we need to use MULTIANEWARRAY

            for (int i = 0; i < arrayDimDefinedCount; i++) {
                // compile next array dimension adds 1 to stack
                arrayDims.get(i).compile(mv, compileContext);
            }
            // execute the MULTIANEWARRAY operation -- pops arrayDims operands and pushes 1
            mv.visitMultiANewArrayInsn(type.getInternalName(), arrayDimDefinedCount);
            compileContext.addStackCount(1 - arrayDimDefinedCount);
        }
    }

    if (compileContext.getStackCount() != currentStack + expected) {
        throw new CompileException("NewExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + expected));
    }
}