Example usage for org.objectweb.asm Opcodes DUP_X2

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

Introduction

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

Prototype

int DUP_X2

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

Click Source Link

Usage

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

License:Open Source License

/**
 * Generates a DUP_X2 instruction.
 */
public void dupX2() {
    visitInsn(Opcodes.DUP_X2);
}

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

License:Open Source License

/**
 * stack an argument array containing all the values which need to be bound to parameters or local variables
 * in the rule or a null pointer if no bindings are required. this method also inserts a copy of the array
 * below the initial two top entries if any of the bindings can potentially be updated by the rule, allowing
 * the updated values to be written back on return from the call to the rule engine.
 * @param saveSlot a local variable slot containing either the return value which the trigger method is about
 * to return or the Throwable the method is about to throw. this is only valid if, respectively, the rule
 * location is AT EXIT/AFTER INVOKE or AT THROW and the rule body contains a reference to the return value ($!)
 * or throwable value ($@)./*from w ww.  ja v  a 2 s  .  c  o  m*/
 * @return true if the rule may update the argument array and hence if a copy of the array has been inserted
 * below the initial two top entries otherwise false.
 */
private boolean doArgLoad(int saveSlot) {
    if (callArrayBindings.size() == 0) {
        push((org.objectweb.asm.Type) null);
        return false;
    }

    // create the array used to pass the bindings

    int arraySize = callArrayBindings.size();

    push(arraySize);
    Type objectType = Type.getType(Object.class);
    newArray(objectType);

    // check if any of the bindings gets updated. if so we need to stash a copy of the bindings array
    // below the key and owner so we can pull out the updated values and update local var/param slots
    // once the call ahs completed

    boolean doUpdates = false;

    for (int i = 0; i < arraySize; i++) {
        Binding binding = callArrayBindings.get(i);
        if (binding.isUpdated()) {
            doUpdates = true;
            break;
        }
    }

    if (doUpdates) {
        // insert copy of array below first two call arguments
        // [.. key owner bindings ] ==> [.. bindings key owner bindings ]
        mv.visitInsn(Opcodes.DUP_X2);
    }

    // now install required values into bindings array
    for (int i = 0; i < arraySize; i++) {
        Binding binding = callArrayBindings.get(i);
        dup();
        push(i);
        if (binding.isParam()) {
            int idx = binding.getIndex() - 1;
            loadArg(idx);
            box(argumentTypes[idx]);
        } else if (binding.isLocalVar()) {
            int idx = binding.getLocalIndex();
            loadLocal(idx);
            box(getLocalType(idx));
        } else if (binding.isParamCount()) {
            int count = argumentTypes.length;
            push(count);
            box(Type.INT_TYPE);
        } else if (binding.isParamArray()) {
            int count = argumentTypes.length;
            push(count + 1);
            newArray(objectType);
            dup();
            push(0);
            if ((access & Opcodes.ACC_STATIC) == 0) {
                loadThis();
            } else {
                push((Type) null);
            }
            arrayStore(objectType);
            for (int idx = 0; idx < count; idx++) {
                dup();
                push(idx + 1);
                loadArg(idx);
                box(argumentTypes[idx]);
                arrayStore(objectType);
            }
        } else if (binding.isInvokeParamArray()) {
            loadLocal(saveSlot);
        } else if (binding.isTriggerClass()) {
            String triggerClassName = TypeHelper.internalizeClass(getTriggerClassName());
            visitLdcInsn(triggerClassName);
        } else if (binding.isTriggerMethod()) {
            String triggerMethodName = name + TypeHelper.internalizeDescriptor(descriptor);
            visitLdcInsn(triggerMethodName);
        } else if (binding.isThrowable() | binding.isReturn()) {
            loadLocal(saveSlot);
            box(saveValueType);
        }
        arrayStore(objectType);
    }

    return doUpdates;
}

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

License:Open Source License

/**
 * plant code to copy back any updated values from the argument array to the relevant local variable slots
 *///from ww  w .  j a v  a 2 s. co  m
private void doArgUpdate() {
    // at entry the top of the stack contains the object array
    // for an AT EXIT rule the entry below this is the return value

    Type objectType = Type.getType(Object.class);
    int arraySize = callArrayBindings.size();
    int lastUpdated = -1;
    int returnIdx = -1;

    // identify which is the last index we will need to update. n.b. if we find a return value we will
    // update that last

    for (int i = 0; i < arraySize; i++) {
        Binding binding = callArrayBindings.get(i);
        if (binding.isUpdated()) {
            lastUpdated = i;
            if (binding.isReturn()) {
                returnIdx = i;
            }
        }
    }

    // if the return value is updated it gets done last
    if (returnIdx >= 0) {
        lastUpdated = returnIdx;
    }

    // write back all other args then stack new return value and drop old one
    for (int i = 0; i < arraySize; i++) {
        Binding binding = callArrayBindings.get(i);
        if (binding.isUpdated() && !binding.isReturn()) {
            // if this is the last update then we consume the arguments array
            // otherwise we need to copy it
            if (i != lastUpdated) {
                dup();
            }
            push(i);
            arrayLoad(objectType);
            if (binding.isParam()) {
                int idx = binding.getIndex() - 1;
                unbox(argumentTypes[idx]);
                storeArg(idx);
            } else if (binding.isLocalVar()) {
                int idx = binding.getLocalIndex();
                unbox(getLocalType(idx));
                storeLocal(idx);
            }
        }
    }

    // if we had a return value to process then the args array will still be on top of the stack above
    // the old return value

    if (returnIdx >= 0) {
        // get rid of old return value remembering to use the correct type for $!
        // which varies depending if this is an AT EXIT or AFTER CALL rule
        if (saveValueType.getSize() == 2) {
            mv.visitInsn(Opcodes.DUP_X2);
            mv.visitInsn(Opcodes.POP);
            mv.visitInsn(Opcodes.POP2);
        } else {
            mv.visitInsn(Opcodes.SWAP);
            mv.visitInsn(Opcodes.POP);
        }

        push(returnIdx);
        arrayLoad(objectType);
        // use the correct type for $! which varies depending if this is an AT EXIT or AFTER CALL rule
        unbox(saveValueType);
    }
}

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);//from w ww . j a  v  a  2  s .co  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.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 {//from   www .  j a v  a  2  s.  c  o  m
        // 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 {// w  w  w. j a  va2 s. 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.Variable.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);

    int currentStack = compileContext.getStackCount();
    int size = ((type.getNBytes() > 4) ? 2 : 1);
    int max;//  w  w w  . java 2 s.  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) {
        // [... val1 val2 ==> ... val1 val2 val1 val2]
        mv.visitInsn(Opcodes.DUP2);
    } else {
        // [... val ==> ... val val]
        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
        // [... val1 val2 val1 val2 helper ==> ... val1 val2 helper val1 val2 helper]
        mv.visitInsn(Opcodes.DUP_X2);
        // [... val1 val2 helper val1 val2 helper ==> ... val1 val2 helper val1 val2]
        mv.visitInsn(Opcodes.POP);
    } else {
        // we can just swap the two values
        // [... val val helper ==> ... val helper val]
        mv.visitInsn(Opcodes.SWAP);
    }
    // stack the name for the variable and swap below the value
    mv.visitLdcInsn(name);
    if (size == 2) {
        // use a DUP_X2 to push a copy below the value then pop the redundant value
        // [... val1 val2 helper val1 val2 name ==> [... val1 val2 helper name val1 val2 name]
        mv.visitInsn(Opcodes.DUP_X2);
        // this is the high water mark
        compileContext.addStackCount(5);
        // [... val1 val2 helper name val1 val2 name ==> [... val1 val2 helper name val1 val2]
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);
        // and now we have the desired arrangement for the call[.. val1 val2 helper name val1 val2]
    } 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
        // [... val helper val name ==> ... val helper name val]
        mv.visitInsn(Opcodes.SWAP);
        // and now we have the desired arrangement for the call[.. val helper name val]
    }

    // 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.mbte.groovypp.compiler.bytecode.BytecodeExpr.java

License:Apache License

public void swapObjectWith(ClassNode type, MethodVisitor mv) {
    if (type == long_TYPE || type == double_TYPE) {
        mv.visitInsn(Opcodes.DUP_X2);
        mv.visitInsn(Opcodes.POP);/*from   w  ww.  ja  v  a  2 s.  com*/
    } else {
        mv.visitInsn(Opcodes.SWAP);
    }
}

From source file:org.mbte.groovypp.compiler.bytecode.BytecodeExpr.java

License:Apache License

public static void dup_x2(ClassNode type, MethodVisitor mv) {
    if (type == double_TYPE || type == long_TYPE)
        mv.visitInsn(Opcodes.DUP2_X2);/*from  w  w  w.j av a2  s. com*/
    else
        mv.visitInsn(Opcodes.DUP_X2);
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**     
 * @param type/*  www  .j  a v a  2s .  c o  m*/
 * @return the DUP_X2 or DUP2_X2 instruction, depending on type.
 */
private static int getDupX2OpCode(JavaTypeName type) {

    switch (type.getTag()) {
    case JavaTypeName.BOOLEAN_TAG:
    case JavaTypeName.BYTE_TAG:
    case JavaTypeName.SHORT_TAG:
    case JavaTypeName.CHAR_TAG:
    case JavaTypeName.INT_TAG:
    case JavaTypeName.FLOAT_TAG:
    case JavaTypeName.ARRAY_TAG:
    case JavaTypeName.OBJECT_TAG:
        return Opcodes.DUP_X2;

    case JavaTypeName.LONG_TAG:
    case JavaTypeName.DOUBLE_TAG:
        return Opcodes.DUP2_X2;

    case JavaTypeName.VOID_TAG:
    default: {
        throw new IllegalArgumentException("invalid type: " + type);
    }
    }
}