Example usage for org.objectweb.asm Opcodes INVOKEVIRTUAL

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

Introduction

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

Prototype

int INVOKEVIRTUAL

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

Click Source Link

Usage

From source file:com.nway.spring.jdbc.bean.AsmBeanProcessor.java

License:Apache License

private void visitMethodWrap(MethodVisitor mv, int index, String beanSignature, int beanType,
        String writeMethod, String processorName) {

    mv.visitVarInsn(Opcodes.ALOAD, 3);//from   ww  w  . j a v  a2  s  .co  m
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitVarInsn(Opcodes.ALOAD, 1);

    visitInsn(mv, index);

    switch (beanType) {
    case PROPERTY_TYPE_INTEGER:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getInt", "(I)I", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "integerValue", "(IZ)Ljava/lang/Integer;",
                false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Integer;)V", false);
        break;
    case PROPERTY_TYPE_LONG:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getLong", "(I)J", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "longValue", "(JZ)Ljava/lang/Long;", false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Long;)V", false);
        break;
    case PROPERTY_TYPE_BOOLEAN:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getBoolean", "(I)Z", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "booleanValue", "(ZZ)Ljava/lang/Boolean;",
                false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Boolean;)V", false);
        break;
    case PROPERTY_TYPE_FLOAT:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getFloat", "(I)F", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "floatValue", "(FZ)Ljava/lang/Float;", false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Float;)V", false);
        break;
    case PROPERTY_TYPE_DOUBLE:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getDouble", "(I)D", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "doubleValue", "(DZ)Ljava/lang/Double;",
                false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Double;)V", false);
        break;
    case PROPERTY_TYPE_BYTE:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getByte", "(I)B", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "byteValue", "(BZ)Ljava/lang/Byte;", false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Byte;)V", false);
        break;
    case PROPERTY_TYPE_SHORT:
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "getShort", "(I)S", true);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/sql/ResultSet", "wasNull", "()Z", true);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, processorName, "shortValue", "(SZ)Ljava/lang/Short;", false);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, beanSignature, writeMethod, "(Ljava/lang/Short;)V", false);
        break;
    }
}

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

License:Open Source License

/**
 * Generates instructions for printing out a string constant using {@link System#out}. This is useful for debugging. For example, you
 * can print out lines around your instrumented code to make sure that what you think is being run is actually being run.
 * @param text text to print out/*from  ww  w .j  a  va 2 s. co  m*/
 * @return instructions to call System.out.println with a string constant
 * @throws NullPointerException if any argument is {@code null}
 */
public static InsnList debugPrint(String text) {
    Validate.notNull(text);

    InsnList ret = new InsnList();

    ret.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
    ret.add(new LdcInsnNode(text));
    ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V",
            false));

    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)./*from  w  w  w  . j a v  a2 s.co  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

private static InsnList loadOperandStack(Variable arrayStackVar, Variable tempObjectVar,
        Frame<BasicValue> frame, int start, int end) {
    Validate.notNull(arrayStackVar);//  w ww .ja va2 s  . c o  m
    Validate.notNull(tempObjectVar);
    Validate.notNull(frame);
    Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class)));
    Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class)));
    validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex());
    Validate.isTrue(start >= 0);
    Validate.isTrue(end >= start); // end is exclusive
    Validate.isTrue(end <= frame.getStackSize());

    InsnList ret = new InsnList();

    // Restore the stack
    for (int i = start; i < end; i++) {
        BasicValue basicValue = frame.getStack(i);
        Type type = basicValue.getType();

        // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
        // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
        // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby
        // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is
        // not a real class and can never be a real class -- null is a reserved word in Java).
        if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) {
            ret.add(new InsnNode(Opcodes.ACONST_NULL));
            continue;
        }

        // Load item from stack storage array
        ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex()));
        ret.add(new LdcInsnNode(i));
        ret.add(new InsnNode(Opcodes.AALOAD));

        // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack.
        switch (type.getSort()) {
        case Type.BOOLEAN:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z",
                    false));
            break;
        case Type.BYTE:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false));
            break;
        case Type.SHORT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false));
            break;
        case Type.CHAR:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C",
                    false));
            break;
        case Type.INT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false));
            break;
        case Type.FLOAT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false));
            break;
        case Type.LONG:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false));
            break;
        case Type.DOUBLE:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false));
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName()));
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalArgumentException();
        }
    }

    return ret;
}

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

License:Open Source License

/**
 * Generates instructions to save the operand stack to an object array.
 * @param arrayStackVar variable that the object array containing operand stack is stored
 * @param tempObjectVar variable to use for temporary objects
 * @param frame execution frame at the instruction where the operand stack is to be saved
 * @return instructions to save the operand stack in to an array and save it to the local variables table
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong
 * type// w  w w .j  a  v a2 s.c  o m
 */
public static InsnList saveOperandStack(Variable arrayStackVar, Variable tempObjectVar,
        Frame<BasicValue> frame) {
    Validate.notNull(arrayStackVar);
    Validate.notNull(tempObjectVar);
    Validate.notNull(frame);
    Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class)));
    Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class)));
    validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex());

    InsnList ret = new InsnList();

    // Create stack storage array and save it in local vars table
    ret.add(new LdcInsnNode(frame.getStackSize()));
    ret.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"));
    ret.add(new VarInsnNode(Opcodes.ASTORE, arrayStackVar.getIndex()));

    // Save the stack
    for (int i = frame.getStackSize() - 1; i >= 0; i--) {
        BasicValue basicValue = frame.getStack(i);
        Type type = basicValue.getType();

        // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
        // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
        // point in the code so we can avoid saving it (but we still need to do a POP to get rid of it). When we load it back up, we can
        // simply push a null in to that slot, thereby keeping the same 'Lnull;' type.
        if ("Lnull;".equals(type.getDescriptor())) {
            ret.add(new InsnNode(Opcodes.POP));
            continue;
        }

        // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack.
        switch (type.getSort()) {
        case Type.BOOLEAN:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf",
                    "(Z)Ljava/lang/Boolean;"));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.BYTE:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;",
                    false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.SHORT:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf",
                    "(S)Ljava/lang/Short;", false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.CHAR:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf",
                    "(C)Ljava/lang/Character;", false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.INT:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf",
                    "(I)Ljava/lang/Integer;", false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.FLOAT:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf",
                    "(F)Ljava/lang/Float;", false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.LONG:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;",
                    false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.DOUBLE:
            ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf",
                    "(D)Ljava/lang/Double;", false));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalArgumentException();
        }

        // Store item in to stack storage array
        ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex()));
        ret.add(new LdcInsnNode(i));
        ret.add(new VarInsnNode(Opcodes.ALOAD, tempObjectVar.getIndex()));
        ret.add(new InsnNode(Opcodes.AASTORE));
    }

    // Restore the stack
    for (int i = 0; i < frame.getStackSize(); i++) {
        BasicValue basicValue = frame.getStack(i);
        Type type = basicValue.getType();

        // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
        // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
        // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby
        // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is
        // not a real class and can never be a real class -- null is a reserved word in Java).
        if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) {
            ret.add(new InsnNode(Opcodes.ACONST_NULL));
            continue;
        }

        // Load item from stack storage array
        ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex()));
        ret.add(new LdcInsnNode(i));
        ret.add(new InsnNode(Opcodes.AALOAD));

        // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack.
        switch (type.getSort()) {
        case Type.BOOLEAN:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z",
                    false));
            break;
        case Type.BYTE:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false));
            break;
        case Type.SHORT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false));
            break;
        case Type.CHAR:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C",
                    false));
            break;
        case Type.INT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false));
            break;
        case Type.FLOAT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false));
            break;
        case Type.LONG:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false));
            break;
        case Type.DOUBLE:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false));
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName()));
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalArgumentException();
        }
    }

    return ret;
}

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

License:Open Source License

/**
 * Generates instructions to load the local variables table from an object array.
 *
 * @param arrayLocalsVar variable that the object array containing local variables table is stored
 * @param tempObjectVar variable to use for temporary objects
 * @param frame execution frame at the instruction for which the local variables table is to be restored
 * @return instructions to load the local variables table from an array
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong
 * type//from w w w  .  j  a  v a  2  s. com
 */
public static InsnList loadLocalVariableTable(Variable arrayLocalsVar, Variable tempObjectVar,
        Frame<BasicValue> frame) {
    Validate.notNull(arrayLocalsVar);
    Validate.notNull(tempObjectVar);
    Validate.notNull(frame);
    Validate.isTrue(arrayLocalsVar.getType().equals(Type.getType(Object[].class)));
    Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class)));
    validateLocalIndicies(arrayLocalsVar.getIndex(), tempObjectVar.getIndex());
    InsnList ret = new InsnList();

    // Load the locals
    for (int i = 0; i < frame.getLocals(); i++) {
        BasicValue basicValue = frame.getLocal(i);
        Type type = basicValue.getType();

        // If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return ".". This means that this
        // slot contains nothing to load. So, skip this slot if we encounter it (such that it will remain uninitialized).
        if (type == null) {
            continue;
        }

        // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
        // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
        // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby
        // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is
        // not a real class and can never be a real class -- null is a reserved word in Java).
        if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) {
            ret.add(new InsnNode(Opcodes.ACONST_NULL));
            ret.add(new VarInsnNode(Opcodes.ASTORE, i));
            continue;
        }

        // Load item from locals storage array
        ret.add(new VarInsnNode(Opcodes.ALOAD, arrayLocalsVar.getIndex()));
        ret.add(new LdcInsnNode(i));
        ret.add(new InsnNode(Opcodes.AALOAD));

        // Convert the item from an object stores it in local vars table.
        switch (type.getSort()) {
        case Type.BOOLEAN:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z",
                    false));
            ret.add(new VarInsnNode(Opcodes.ISTORE, i));
            break;
        case Type.BYTE:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false));
            ret.add(new VarInsnNode(Opcodes.ISTORE, i));
            break;
        case Type.SHORT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false));
            ret.add(new VarInsnNode(Opcodes.ISTORE, i));
            break;
        case Type.CHAR:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C",
                    false));
            ret.add(new VarInsnNode(Opcodes.ISTORE, i));
            break;
        case Type.INT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false));
            ret.add(new VarInsnNode(Opcodes.ISTORE, i));
            break;
        case Type.FLOAT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false));
            ret.add(new VarInsnNode(Opcodes.FSTORE, i));
            break;
        case Type.LONG:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false));
            ret.add(new VarInsnNode(Opcodes.LSTORE, i));
            break;
        case Type.DOUBLE:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double"));
            ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false));
            ret.add(new VarInsnNode(Opcodes.DSTORE, i));
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName()));
            ret.add(new VarInsnNode(Opcodes.ASTORE, i));
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalStateException();
        }
    }

    return ret;
}

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

License:Open Source License

/**
 * Get the number of arguments required for an invocation of some method. This includes the 'this' argument for non-static methods.
 * <p>//  w  w w. ja  va2s  .  com
 * NOTE THAT THIS IS NOT THE NUMBER OF ITEMS ON THE STACK. If the method takes in doubles or longs, each double or long encountered
 * would be 2 items on the stack. This method returns the number of arguments required for the method to be invoked, not the number of
 * items required to be on the stack for the method to be invoked.
 * @param invokeNode the invocation instruction (either normal invocation or invokedynamic)
 * @return number of arguments required by this method
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if {@code invokeNode} is neither of type {@link MethodInsnNode} nor {@link InvokeDynamicInsnNode},
 * or if type of invocation ({@link MethodInsnNode}) cannot be determined
 */
public static int getArgumentCountRequiredForInvocation(AbstractInsnNode invokeNode) {
    Validate.notNull(invokeNode);

    if (invokeNode instanceof MethodInsnNode) {
        MethodInsnNode methodInsnNode = (MethodInsnNode) invokeNode;
        int extra;
        int paramCount;

        switch (methodInsnNode.getOpcode()) {
        case Opcodes.INVOKEVIRTUAL:
        case Opcodes.INVOKESPECIAL:
        case Opcodes.INVOKEINTERFACE:
            extra = 1;
            break;
        case Opcodes.INVOKESTATIC:
            extra = 0;
            break;
        default:
            throw new IllegalArgumentException(); // unknown invocation type? probably badly generated instruction node
        }
        Type methodType = Type.getType(methodInsnNode.desc);
        paramCount = methodType.getArgumentTypes().length;

        return paramCount + extra;
    } else if (invokeNode instanceof InvokeDynamicInsnNode) {
        InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) invokeNode;
        int paramCount;

        Type methodType = Type.getType(invokeDynamicInsnNode.desc);
        paramCount = methodType.getArgumentTypes().length;

        return paramCount;
    } else {
        throw new IllegalArgumentException();
    }
}

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

License:Open Source License

@Test
public void mustProperlyDetermineStackSizeForNormalMethod() {
    Type type = Type.getType(MethodUtils.getAccessibleMethod(Integer.class, "compareTo", Integer.class));
    MethodInsnNode methodInsnNode = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/Integer", "compareTo",
            type.getDescriptor(), false);
    int reqStackCount = MethodInvokeUtils.getArgumentCountRequiredForInvocation(methodInsnNode);

    assertEquals(2, reqStackCount);/*from w w w. jav  a 2s  . c  o  m*/
}

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

License:Open Source License

/**
 * Get the number of items that need to be on the stack for an invocation of some method.
 * @param invokeNode the invocation instruction (either normal invocation or invokedynamic)
 * @return number of items required on the stack for this method
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if {@code invokeNode} is neither of type {@link MethodInsnNode} nor {@link InvokeDynamicInsnNode},
 * or if type of invocation ({@link MethodInsnNode}) cannot be determined
 *//*from w  w w  . j a  va 2 s  .  c  o m*/
public static int getRequiredStackCountForInvocation(AbstractInsnNode invokeNode) {
    Validate.notNull(invokeNode);

    if (invokeNode instanceof MethodInsnNode) {
        MethodInsnNode methodInsnNode = (MethodInsnNode) invokeNode;
        int extra;
        int paramCount;

        switch (methodInsnNode.getOpcode()) {
        case Opcodes.INVOKEVIRTUAL:
        case Opcodes.INVOKESPECIAL:
        case Opcodes.INVOKEINTERFACE:
            extra = 1;
            break;
        case Opcodes.INVOKESTATIC:
            extra = 0;
            break;
        default:
            throw new IllegalArgumentException(); // unknown invocation type? probably badly generated instruction node
        }
        Type methodType = Type.getType(methodInsnNode.desc);
        paramCount = methodType.getArgumentTypes().length;

        return paramCount + extra;
    } else if (invokeNode instanceof InvokeDynamicInsnNode) {
        InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) invokeNode;
        int paramCount;

        Type methodType = Type.getType(invokeDynamicInsnNode.desc);
        paramCount = methodType.getArgumentTypes().length;

        return paramCount;
    } else {
        throw new IllegalArgumentException();
    }
}

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

License:Open Source License

@Test
public void mustProperlyDetermineStackSizeForNormalMethod() {
    Type type = Type.getType(MethodUtils.getAccessibleMethod(Integer.class, "compareTo", Integer.class));
    MethodInsnNode methodInsnNode = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/Integer", "compareTo",
            type.getDescriptor(), false);
    int reqStackCount = SearchUtils.getRequiredStackCountForInvocation(methodInsnNode);

    assertEquals(2, reqStackCount);/*from w  w w .  ja  v a  2  s.  c o  m*/
}