Example usage for org.objectweb.asm.tree InsnList add

List of usage examples for org.objectweb.asm.tree InsnList add

Introduction

In this page you can find the example usage for org.objectweb.asm.tree InsnList add.

Prototype

public void add(final InsnList insnList) 

Source Link

Document

Adds the given instructions to the end of this list.

Usage

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Copies a local variable on to the stack.
 * @param variable variable within the local variable table to load from
 * @return instructions to load a local variable on to the stack
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if {@code variable} has been released
 *//*from  w  ww. j  a  v a 2 s  .c o  m*/
public static InsnList loadVar(Variable variable) {
    Validate.notNull(variable);

    InsnList ret = new InsnList();
    switch (variable.getType().getSort()) {
    case Type.BOOLEAN:
    case Type.BYTE:
    case Type.CHAR:
    case Type.SHORT:
    case Type.INT:
        ret.add(new VarInsnNode(Opcodes.ILOAD, variable.getIndex()));
        break;
    case Type.LONG:
        ret.add(new VarInsnNode(Opcodes.LLOAD, variable.getIndex()));
        break;
    case Type.FLOAT:
        ret.add(new VarInsnNode(Opcodes.FLOAD, variable.getIndex()));
        break;
    case Type.DOUBLE:
        ret.add(new VarInsnNode(Opcodes.DLOAD, variable.getIndex()));
        break;
    case Type.OBJECT:
    case Type.ARRAY:
        ret.add(new VarInsnNode(Opcodes.ALOAD, variable.getIndex()));
        ret.add(new TypeInsnNode(Opcodes.CHECKCAST, variable.getType().getInternalName()));
        break;
    default:
        throw new IllegalStateException(); // should never happen, there is code in Variable/VariableTable to make sure invalid
                                           // types aren't set
    }

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Pops the stack in to the the local variable table. You may run in to problems if the item on top of the stack isn't of the same type
 * as the variable it's being put in to.
 * @param variable variable within the local variable table to save to
 * @return instructions to pop an item off the top of the stack and save it to {@code variable}
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if {@code variable} has been released
 *//*from   w  w  w .jav  a  2 s  .c o m*/
public static InsnList saveVar(Variable variable) {
    Validate.notNull(variable);

    InsnList ret = new InsnList();
    switch (variable.getType().getSort()) {
    case Type.BOOLEAN:
    case Type.BYTE:
    case Type.CHAR:
    case Type.SHORT:
    case Type.INT:
        ret.add(new VarInsnNode(Opcodes.ISTORE, variable.getIndex()));
        break;
    case Type.LONG:
        ret.add(new VarInsnNode(Opcodes.LSTORE, variable.getIndex()));
        break;
    case Type.FLOAT:
        ret.add(new VarInsnNode(Opcodes.FSTORE, variable.getIndex()));
        break;
    case Type.DOUBLE:
        ret.add(new VarInsnNode(Opcodes.DSTORE, variable.getIndex()));
        break;
    case Type.OBJECT:
    case Type.ARRAY:
        ret.add(new VarInsnNode(Opcodes.ASTORE, variable.getIndex()));
        break;
    default:
        throw new IllegalStateException(); // should never happen, there is code in Variable/VariableTable to make sure invalid
                                           // types aren't set
    }

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Calls a constructor with a set of arguments. After execution the stack should have an extra item pushed on it: the object that was
 * created by this constructor./*ww  w .j  av  a2s  .  co m*/
 * @param constructor constructor to call
 * @param args constructor argument instruction lists -- each instruction list must leave one item on the stack of the type expected
 * by the constructor
 * @return instructions to invoke a constructor
 * @throws NullPointerException if any argument is {@code null} or array contains {@code null}
 * @throws IllegalArgumentException if the length of {@code args} doesn't match the number of parameters in {@code constructor}
 */
public static InsnList construct(Constructor<?> constructor, InsnList... args) {
    Validate.notNull(constructor);
    Validate.notNull(args);
    Validate.noNullElements(args);
    Validate.isTrue(constructor.getParameterCount() == args.length);

    InsnList ret = new InsnList();

    Type clsType = Type.getType(constructor.getDeclaringClass());
    Type methodType = Type.getType(constructor);

    ret.add(new TypeInsnNode(Opcodes.NEW, clsType.getInternalName()));
    ret.add(new InsnNode(Opcodes.DUP));
    for (InsnList arg : args) {
        ret.add(arg);
    }
    ret.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, clsType.getInternalName(), "<init>",
            methodType.getDescriptor(), false));

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Compares two integers and performs some action if the integers are equal.
 * @param lhs left hand side instruction list -- must leave an int on top of the stack
 * @param rhs right hand side instruction list -- must leave an int on top of the stack
 * @param action action to perform if results of {@code lhs} and {@code rhs} are equal
 * @return instructions instruction list to perform some action if two ints are equal
 * @throws NullPointerException if any argument is {@code null}
 *//*  w w  w  .  ja va  2 s. com*/
public static InsnList ifIntegersEqual(InsnList lhs, InsnList rhs, InsnList action) {
    Validate.notNull(lhs);
    Validate.notNull(rhs);
    Validate.notNull(action);

    InsnList ret = new InsnList();

    LabelNode notEqualLabelNode = new LabelNode();

    ret.add(lhs);
    ret.add(rhs);
    ret.add(new JumpInsnNode(Opcodes.IF_ICMPNE, notEqualLabelNode));
    ret.add(action);
    ret.add(notEqualLabelNode);

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
     * Compares two objects and performs some action if the objects are the same (uses == to check if same, not the equals method).
     * @param lhs left hand side instruction list -- must leave an object on top of the stack
     * @param rhs right hand side instruction list -- must leave an object on top of the stack
     * @param action action to perform if results of {@code lhs} and {@code rhs} are equal
     * @return instructions instruction list to perform some action if two objects are equal
     * @throws NullPointerException if any argument is {@code null}
     *//*from   w ww.ja  v  a  2 s  .  co  m*/
public static InsnList ifObjectsEqual(InsnList lhs, InsnList rhs, InsnList action) {
    Validate.notNull(lhs);
    Validate.notNull(rhs);
    Validate.notNull(action);

    InsnList ret = new InsnList();

    LabelNode notEqualLabelNode = new LabelNode();

    ret.add(lhs);
    ret.add(rhs);
    ret.add(new JumpInsnNode(Opcodes.IF_ACMPNE, notEqualLabelNode));
    ret.add(action);
    ret.add(notEqualLabelNode);

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * For each element in an object array, performs an action.
 * @param counterVar parameter used to keep track of count in loop
 * @param arrayLenVar parameter used to keep track of array length
 * @param array object array instruction list -- must leave an array on top of the stack
 * @param action action to perform on each element -- element will be at top of stack and must be consumed by these instructions
 * @return instructions instruction list to perform some action if two ints are equal
 * @throws NullPointerException if any argument is {@code null}
 */// w  ww .  ja  va2s. c o m
public static InsnList forEach(Variable counterVar, Variable arrayLenVar, InsnList array, InsnList action) {
    Validate.notNull(counterVar);
    Validate.notNull(arrayLenVar);
    Validate.notNull(array);
    Validate.notNull(action);
    Validate.isTrue(counterVar.getType().equals(Type.INT_TYPE));
    Validate.isTrue(arrayLenVar.getType().equals(Type.INT_TYPE));

    InsnList ret = new InsnList();

    LabelNode doneLabelNode = new LabelNode();
    LabelNode loopLabelNode = new LabelNode();

    // put zero in to counterVar
    ret.add(new LdcInsnNode(0)); // int
    ret.add(new VarInsnNode(Opcodes.ISTORE, counterVar.getIndex())); //

    // load array we'll be traversing over
    ret.add(array); // object[]

    // put array length in to arrayLenVar
    ret.add(new InsnNode(Opcodes.DUP)); // object[], object[]
    ret.add(new InsnNode(Opcodes.ARRAYLENGTH)); // object[], int
    ret.add(new VarInsnNode(Opcodes.ISTORE, arrayLenVar.getIndex())); // object[]

    // loopLabelNode: test if counterVar == arrayLenVar, if it does then jump to doneLabelNode
    ret.add(loopLabelNode);
    ret.add(new VarInsnNode(Opcodes.ILOAD, counterVar.getIndex())); // object[], int
    ret.add(new VarInsnNode(Opcodes.ILOAD, arrayLenVar.getIndex())); // object[], int, int
    ret.add(new JumpInsnNode(Opcodes.IF_ICMPEQ, doneLabelNode)); // object[]

    // load object from object[]
    ret.add(new InsnNode(Opcodes.DUP)); // object[], object[]
    ret.add(new VarInsnNode(Opcodes.ILOAD, counterVar.getIndex())); // object[], object[], int
    ret.add(new InsnNode(Opcodes.AALOAD)); // object[], object

    // call action
    ret.add(action); // object[]

    // increment counter var and goto loopLabelNode
    ret.add(new IincInsnNode(counterVar.getIndex(), 1)); // object[]
    ret.add(new JumpInsnNode(Opcodes.GOTO, loopLabelNode)); // object[]

    // doneLabelNode: pop object[] off of stack
    ret.add(doneLabelNode);
    ret.add(new InsnNode(Opcodes.POP)); //

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Calls a method with a set of arguments. After execution the stack may have an extra item pushed on it: the object that was returned
 * by this method (if any)./*w ww.j a v a 2s .  c o m*/
 * @param method method to call
 * @param args method argument instruction lists -- each instruction list must leave one item on the stack of the type expected
 * by the method (note that if this is a non-static method, the first argument must always evaluate to the "this" pointer/reference)
 * @return instructions to invoke a method
 * @throws NullPointerException if any argument is {@code null} or array contains {@code null}
 * @throws IllegalArgumentException if the length of {@code args} doesn't match the number of parameters in {@code method}
 */
public static InsnList call(Method method, InsnList... args) {
    Validate.notNull(method);
    Validate.notNull(args);
    Validate.noNullElements(args);

    InsnList ret = new InsnList();

    for (InsnList arg : args) {
        ret.add(arg);
    }

    Type clsType = Type.getType(method.getDeclaringClass());
    Type methodType = Type.getType(method);

    if ((method.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
        Validate.isTrue(method.getParameterCount() == args.length);
        ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, clsType.getInternalName(), method.getName(),
                methodType.getDescriptor(), false));
    } else if (method.getDeclaringClass().isInterface()) {
        Validate.isTrue(method.getParameterCount() + 1 == args.length);
        ret.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, clsType.getInternalName(), method.getName(),
                methodType.getDescriptor(), true));
    } else {
        Validate.isTrue(method.getParameterCount() + 1 == args.length);
        ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, clsType.getInternalName(), method.getName(),
                methodType.getDescriptor(), false));
    }

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Generates instructions to throw an exception of type {@link RuntimeException} with a constant message.
 * @param message message of exception/*  ww  w.j  a v a  2s .  c  om*/
 * @return instructions to throw an exception
 * @throws NullPointerException if any argument is {@code null}
 */
public static InsnList throwException(String message) {
    Validate.notNull(message);

    InsnList ret = new InsnList();

    ret.add(new TypeInsnNode(Opcodes.NEW, "java/lang/RuntimeException"));
    ret.add(new InsnNode(Opcodes.DUP));
    ret.add(new LdcInsnNode(message));
    ret.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException", "<init>",
            "(Ljava/lang/String;)V", false));
    ret.add(new InsnNode(Opcodes.ATHROW));

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Generates instructions for a switch table. This does not automatically generate jumps at the end of each default/case statement. It's
 * your responsibility to either add the relevant jumps, throws, or returns at each default/case statement, otherwise the code will
 * just fall through (which is likely not what you want).
 * @param indexInsnList instructions to calculate the index -- must leave an int on top of the stack
 * @param defaultInsnList instructions to execute on default statement -- must leave the stack unchanged
 * @param caseStartIdx the number which the case statements start at
 * @param caseInsnLists instructions to execute on each case statement -- must leave the stack unchanged
 * @return instructions for a table switch
 * @throws NullPointerException if any argument is {@code null} or contains {@code null}
 * @throws IllegalArgumentException if any numeric argument is {@code < 0}, or if {@code caseInsnLists} is empty
 *//*from ww  w. j  ava2s.  c  o  m*/
public static InsnList tableSwitch(InsnList indexInsnList, InsnList defaultInsnList, int caseStartIdx,
        InsnList... caseInsnLists) {
    Validate.notNull(defaultInsnList);
    Validate.notNull(indexInsnList);
    Validate.isTrue(caseStartIdx >= 0);
    Validate.notNull(caseInsnLists);
    Validate.noNullElements(caseInsnLists);
    Validate.isTrue(caseInsnLists.length > 0);
    InsnList ret = new InsnList();

    LabelNode defaultLabelNode = new LabelNode();
    LabelNode[] caseLabelNodes = new LabelNode[caseInsnLists.length];

    for (int i = 0; i < caseInsnLists.length; i++) {
        caseLabelNodes[i] = new LabelNode();
    }

    ret.add(indexInsnList);
    ret.add(new TableSwitchInsnNode(caseStartIdx, caseStartIdx + caseInsnLists.length - 1, defaultLabelNode,
            caseLabelNodes));

    for (int i = 0; i < caseInsnLists.length; i++) {
        LabelNode caseLabelNode = caseLabelNodes[i];
        InsnList caseInsnList = caseInsnLists[i];
        if (caseInsnList != null) {
            ret.add(caseLabelNode);
            ret.add(caseInsnList);
        }
    }

    if (defaultInsnList != null) {
        ret.add(defaultLabelNode);
        ret.add(defaultInsnList);
    }

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java

License:Open Source License

/**
 * Generates instructions for a try-catch block.
 * @param tryCatchBlockNode try catch block node to populate to with label with relevant information
 * @param exceptionType exception type to catch ({@code null} means catch any exception)
 * @param tryInsnList instructions to execute for try block
 * @param catchInsnList instructions to execute for catch block
 * @return instructions for a try catch block
 * @throws NullPointerException if any argument other than {@code exceptionType} is {@code null} or contains {@code null}
 * @throws IllegalArgumentException if {@code exceptionType} is not an object type (technically must inherit from {@link Throwable},
 * but no way to check this)// w  w  w. j a  va 2s .c  o  m
 */
public static InsnList tryCatchBlock(TryCatchBlockNode tryCatchBlockNode, Type exceptionType,
        InsnList tryInsnList, InsnList catchInsnList) {
    Validate.notNull(tryInsnList);
    // exceptionType can be null
    Validate.notNull(catchInsnList);
    if (exceptionType != null) {
        Validate.isTrue(exceptionType.getSort() == Type.OBJECT);
    }

    InsnList ret = new InsnList();

    LabelNode tryLabelNode = new LabelNode();
    LabelNode catchLabelNode = new LabelNode();
    LabelNode endLabelNode = new LabelNode();

    tryCatchBlockNode.start = tryLabelNode;
    tryCatchBlockNode.end = catchLabelNode;
    tryCatchBlockNode.handler = catchLabelNode;
    tryCatchBlockNode.type = exceptionType == null ? null : exceptionType.getInternalName();

    ret.add(tryLabelNode);
    ret.add(tryInsnList);
    ret.add(new JumpInsnNode(Opcodes.GOTO, endLabelNode));
    ret.add(catchLabelNode);
    ret.add(catchInsnList);
    ret.add(endLabelNode);
    return ret;
}