Example usage for org.objectweb.asm MethodVisitor visitLdcInsn

List of usage examples for org.objectweb.asm MethodVisitor visitLdcInsn

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitLdcInsn.

Prototype

public void visitLdcInsn(final Object value) 

Source Link

Document

Visits a LDC instruction.

Usage

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);
    compileContext.addStackCount(1);/*  w  w  w.  j  a  v  a2s  . c  o m*/
    // 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.BooleanLiteral.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);

    // load a boolean constant
    mv.visitLdcInsn(value);

    // increment stack height and update maximmum if necessary
    compileContext.addStackCount(1);/*from w  w w .ja  v  a 2s  .  c om*/
}

From source file:org.jboss.byteman.rule.expression.ClassLiteralExpression.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;

    // TODO -- this is only ok if the class is accessible
    // we will need to use a helper method for non-accessible classes
    mv.visitLdcInsn(org.objectweb.asm.Type.getType(ownerType.getTargetClass()));
    // we added one object
    compileContext.addStackCount(1);/*from   w w w.ja  v a  2 s. co m*/
    // check the stack height is ok
    if (compileContext.getStackCount() != currentStack + expected) {
        throw new CompileException("ClassLiteralExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + expected));
    }
}

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  . j  a  v  a  2  s  .  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

public void compile(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 expected = (type.getNBytes() > 4 ? 2 : 1);

    // TODO//ww  w.  jav a2 s.co m
    // optimise compile of trigger class and trigger method just to push the required String literal
    // ditto for $# or any other binding which is known in advance
    if (index == HELPER_IDX) {
        // reference to the current helper so just stack this
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        compileContext.addStackCount(1);
    } else {
        // stack the current helper
        // stack the name for the variable
        // call the getBinding method
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitLdcInsn(targetName);
        compileContext.addStackCount(2);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "getBinding",
                "(Ljava/lang/String;)Ljava/lang/Object;");
        compileContext.addStackCount(-1);
        // perform any necessary type conversion
        if (type.isPrimitive()) {
            // cast down to the boxed type then do an unbox
            Type boxType = Type.boxType(type);
            compileObjectConversion(Type.OBJECT, boxType, mv, compileContext);
            compileUnbox(boxType, type, mv, compileContext);
        } else {
            // cast down to the required type
            compileObjectConversion(Type.OBJECT, type, mv, compileContext);
        }
    }

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

}

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 {// ww  w  .j a v a  2 s.  com
        // 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

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 = (type.getNBytes() > 4 ? 2 : 1);

    if (indirectStatic != null) {
        // this is just wrapping a static field expression so compile it
        indirectStatic.compile(mv, compileContext);
    } else if (isArrayLength) {
        owner.compile(mv, compileContext);
        mv.visitInsn(Opcodes.ARRAYLENGTH);
        // we removed the owner and replaced with expected words
        compileContext.addStackCount(expected - 1);
    } else {// w ww . j av  a  2  s  .  c  o m
        if (isPublicField) {
            // we can use GETFIELD to access a public field
            String ownerType = Type.internalName(field.getDeclaringClass());
            String fieldName = field.getName();
            String fieldType = Type.internalName(field.getType(), true);
            // compile the owner expression
            owner.compile(mv, compileContext);
            mv.visitFieldInsn(Opcodes.GETFIELD, ownerType, fieldName, fieldType);
            // we removed the owner and replaced with expected words
            compileContext.addStackCount(expected - 1);
        } else {
            // since this is a private field we need to do the access using reflection
            // stack the helper, owner and the field index
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            compileContext.addStackCount(1);
            owner.compile(mv, compileContext);
            mv.visitLdcInsn(fieldIndex);
            compileContext.addStackCount(1);
            // use the HelperAdapter method getAccessibleField to get the field value
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class),
                    "getAccessibleField", "(Ljava/lang/Object;I)Ljava/lang/Object;");
            // we popped three words and added one object as result
            compileContext.addStackCount(-2);
            // convert Object to primitive or cast to subtype if required
            compileTypeConversion(Type.OBJECT, type, mv, compileContext);
        }
    }
    // check the stack height is ok
    if (compileContext.getStackCount() != currentStack + expected) {
        throw new CompileException("FieldExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + expected));
    }
}

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  ww . j a v a  2  s  .  com
        // 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.LogicalExpression.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 currentStack = compileContext.getStackCount();

    // compile the first expression and make sure it is a boolean -- adds 1 to stack height
    oper0.compile(mv, compileContext);//w  ww. j  av  a2  s  .  co m
    if (oper0.getType() == Type.BOOLEAN) {
        compileBooleanConversion(Type.BOOLEAN, type.Z, mv, compileContext);
    }
    // plant a test and branch
    Label nextLabel = new Label();
    Label endLabel = new Label();
    if (oper == AND) {
        // only try next if we got true here
        mv.visitJumpInsn(Opcodes.IFNE, nextLabel);
        // ok, the first branch was false so stack a false for the result and skip to the end
        mv.visitLdcInsn(false);
        mv.visitJumpInsn(Opcodes.GOTO, endLabel);
    } else {
        // only try next if we got false here
        mv.visitJumpInsn(Opcodes.IFEQ, nextLabel);
        // ok, the first branch was true so stack a true for the result and skip to the end
        mv.visitLdcInsn(true);
        mv.visitJumpInsn(Opcodes.GOTO, endLabel);
    }
    // in either case if we get here the if test removed 1 from the stack
    compileContext.addStackCount(-1);
    // the else branch -- adds 1 to stack height
    mv.visitLabel(nextLabel);
    oper1.compile(mv, compileContext);
    if (oper0.getType() == Type.BOOLEAN) {
        compileBooleanConversion(Type.BOOLEAN, type.Z, mv, compileContext);
    }
    // the final result is the result of the second oper which is on the stack already
    // This is the end, my beau-tiful friend
    mv.visitLabel(endLabel);
    // in either case if we get here we should have one extra value on the stack
    // check stack height
    if (compileContext.getStackCount() != currentStack + 1) {
        throw new CompileException("LogicalExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + 1));
    }
}

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  ww  w . ja  va  2 s.  c o m
    } 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)
}