Example usage for org.objectweb.asm Opcodes ASTORE

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

Introduction

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

Prototype

int ASTORE

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

Click Source Link

Usage

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//from  ww  w  .j  a v  a  2 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 ww. j  a va2s.c o m
 */
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.InstructionUtils.java

License:Open Source License

/**
 * Generates instructions to save the local variables table to 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 where the local variables table is to be saved
 * @return instructions to save the local variables table in to 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//  w  ww.  j  av a2s.com
 */
public static InsnList saveLocalVariableTable(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();

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

    // Save 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 save. So, skip this slot if we encounter it.
        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 we can avoid saving 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())) {
            continue;
        }

        // Convert the item to an object (if not already an object) and stores it in array.
        switch (type.getSort()) {
        case Type.BOOLEAN:
            ret.add(new VarInsnNode(Opcodes.ILOAD, i));
            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 VarInsnNode(Opcodes.ILOAD, i));
            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 VarInsnNode(Opcodes.ILOAD, i));
            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 VarInsnNode(Opcodes.ILOAD, i));
            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 VarInsnNode(Opcodes.ILOAD, i));
            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 VarInsnNode(Opcodes.FLOAD, i));
            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 VarInsnNode(Opcodes.LLOAD, i));
            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 VarInsnNode(Opcodes.DLOAD, i));
            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.ALOAD, i));
            ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex()));
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalStateException();
        }

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

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.LocalsStateGenerators.java

License:Open Source License

/**
 * Generates instructions to load the local variables table.
 * @param markerType debug marker type/*  w w w  .  j a  va 2s.  c  om*/
 * @param storageVars variables to load locals from
 * @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}
 */
public static InsnList loadLocals(MarkerType markerType, StorageVariables storageVars,
        Frame<BasicValue> frame) {
    Validate.notNull(markerType);
    Validate.notNull(storageVars);
    Validate.notNull(frame);

    Variable intsVar = storageVars.getIntStorageVar();
    Variable floatsVar = storageVars.getFloatStorageVar();
    Variable longsVar = storageVars.getLongStorageVar();
    Variable doublesVar = storageVars.getDoubleStorageVar();
    Variable objectsVar = storageVars.getObjectStorageVar();

    int intsCounter = 0;
    int floatsCounter = 0;
    int longsCounter = 0;
    int doublesCounter = 0;
    int objectsCounter = 0;

    InsnList ret = new InsnList();

    // Load the locals
    ret.add(debugMarker(markerType, "Loading 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) {
            ret.add(debugMarker(markerType, "Skipping uninitialized value at " + i));
            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(debugMarker(markerType, "Putting null value at " + i));
            ret.add(new InsnNode(Opcodes.ACONST_NULL));
            ret.add(new VarInsnNode(Opcodes.ASTORE, i));
            continue;
        }

        // Load the locals
        switch (type.getSort()) {
        case Type.BOOLEAN:
        case Type.BYTE:
        case Type.SHORT:
        case Type.CHAR:
        case Type.INT:
            ret.add(debugMarker(markerType,
                    "Loading int to LVT index " + i + " from storage index " + intsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [int[]]
            ret.add(new LdcInsnNode(intsCounter)); // [int[], idx]
            ret.add(new InsnNode(Opcodes.IALOAD)); // [val]
            ret.add(new VarInsnNode(Opcodes.ISTORE, i)); // []
            intsCounter++;
            break;
        case Type.FLOAT:
            ret.add(debugMarker(markerType,
                    "Loading float to LVT index " + i + " from storage index " + floatsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [float[]]
            ret.add(new LdcInsnNode(floatsCounter)); // [float[], idx]
            ret.add(new InsnNode(Opcodes.FALOAD)); // [val]
            ret.add(new VarInsnNode(Opcodes.FSTORE, i)); // []
            floatsCounter++;
            break;
        case Type.LONG:
            ret.add(debugMarker(markerType,
                    "Loading long to LVT index " + i + " from storage index " + longsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [long[]]
            ret.add(new LdcInsnNode(longsCounter)); // [long[], idx]
            ret.add(new InsnNode(Opcodes.LALOAD)); // [val_PART1, val_PART2]
            ret.add(new VarInsnNode(Opcodes.LSTORE, i)); // []
            longsCounter++;
            break;
        case Type.DOUBLE:
            ret.add(debugMarker(markerType,
                    "Loading double to LVT index " + i + " from storage index " + doublesCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [double[]]
            ret.add(new LdcInsnNode(doublesCounter)); // [double[], idx]
            ret.add(new InsnNode(Opcodes.DALOAD)); // [val_PART1, val_PART2]
            ret.add(new VarInsnNode(Opcodes.DSTORE, i)); // []
            doublesCounter++;
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(debugMarker(markerType,
                    "Loading object to LVT index " + i + " from storage index " + objectsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [Object[]]
            ret.add(new LdcInsnNode(objectsCounter)); // [Object[], idx]
            ret.add(new InsnNode(Opcodes.AALOAD)); // [val]
            // must cast, otherwise the jvm won't know the type that's in the localvariable slot and it'll fail when the code tries
            // to access a method/field on it
            ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName()));
            ret.add(new VarInsnNode(Opcodes.ASTORE, i)); // []
            objectsCounter++;
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalStateException();
        }
    }

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.LocalsStateGenerators.java

License:Open Source License

/**
 * Generates instructions to save the local variables table.
 * @param markerType debug marker type/*from   w w  w .  j  a v a  2 s  .c  o m*/
 * @param storageVars variables to store locals in to
 * @param frame execution frame at the instruction where the local variables table is to be saved
 * @return instructions to save the local variables table in to an array
 * @throws NullPointerException if any argument is {@code null}
 */
public static InsnList saveLocals(MarkerType markerType, StorageVariables storageVars,
        Frame<BasicValue> frame) {
    Validate.notNull(markerType);
    Validate.notNull(storageVars);
    Validate.notNull(frame);

    Variable intsVar = storageVars.getIntStorageVar();
    Variable floatsVar = storageVars.getFloatStorageVar();
    Variable longsVar = storageVars.getLongStorageVar();
    Variable doublesVar = storageVars.getDoubleStorageVar();
    Variable objectsVar = storageVars.getObjectStorageVar();

    int intsCounter = 0;
    int floatsCounter = 0;
    int longsCounter = 0;
    int doublesCounter = 0;
    int objectsCounter = 0;

    StorageSizes storageSizes = computeSizes(frame);

    InsnList ret = new InsnList();

    // Create storage arrays and save them in respective storage vars
    ret.add(merge(debugMarker(markerType, "Saving locals"), mergeIf(intsVar != null, () -> new Object[] {
            debugMarker(markerType, "Generating ints container (" + storageSizes.getIntsSize() + ")"),
            new LdcInsnNode(storageSizes.getIntsSize()), new IntInsnNode(Opcodes.NEWARRAY,
                    Opcodes.T_INT),
            new VarInsnNode(Opcodes.ASTORE, intsVar.getIndex()) }),
            mergeIf(floatsVar != null,
                    () -> new Object[] {
                            debugMarker(markerType,
                                    "Generating floats container (" + storageSizes.getFloatsSize() + ")"),
                            new LdcInsnNode(storageSizes.getFloatsSize()),
                            new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_FLOAT),
                            new VarInsnNode(Opcodes.ASTORE, floatsVar.getIndex()) }),
            mergeIf(longsVar != null, () -> new Object[] {
                    debugMarker(markerType, "Generating longs container (" + storageSizes.getLongsSize() + ")"),
                    new LdcInsnNode(storageSizes.getLongsSize()),
                    new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_LONG),
                    new VarInsnNode(Opcodes.ASTORE, longsVar.getIndex()) }),
            mergeIf(doublesVar != null, () -> new Object[] {
                    debugMarker(markerType,
                            "Generating doubles container (" + storageSizes.getDoublesSize() + ")"),
                    new LdcInsnNode(storageSizes.getDoublesSize()),
                    new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_DOUBLE),
                    new VarInsnNode(Opcodes.ASTORE, doublesVar.getIndex()) }),
            mergeIf(objectsVar != null,
                    () -> new Object[] {
                            debugMarker(markerType,
                                    "Generating objects container (" + storageSizes.getObjectsSize() + ")"),
                            new LdcInsnNode(storageSizes.getObjectsSize()),
                            new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"),
                            new VarInsnNode(Opcodes.ASTORE, objectsVar.getIndex()) })));

    // Save 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 save. So, skip this slot if we encounter it.
        if (type == null) {
            ret.add(debugMarker(markerType, "Skipping uninitialized value at " + i));
            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 we can avoid saving 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(debugMarker(markerType, "Skipping null value at " + i));
            continue;
        }

        // Place item in to appropriate storage array
        switch (type.getSort()) {
        case Type.BOOLEAN:
        case Type.BYTE:
        case Type.SHORT:
        case Type.CHAR:
        case Type.INT:
            ret.add(debugMarker(markerType,
                    "Inserting int at LVT index " + i + " to storage index " + intsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [int[]]
            ret.add(new LdcInsnNode(intsCounter)); // [int[], idx]
            ret.add(new VarInsnNode(Opcodes.ILOAD, i)); // [int[], idx, val]
            ret.add(new InsnNode(Opcodes.IASTORE)); // []
            intsCounter++;
            break;
        case Type.FLOAT:
            ret.add(debugMarker(markerType,
                    "Inserting float at LVT index " + i + " to storage index " + floatsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [float[]]
            ret.add(new LdcInsnNode(floatsCounter)); // [float[], idx]
            ret.add(new VarInsnNode(Opcodes.FLOAD, i)); // [float[], idx, val]
            ret.add(new InsnNode(Opcodes.FASTORE)); // []
            floatsCounter++;
            break;
        case Type.LONG:
            ret.add(debugMarker(markerType,
                    "Inserting long at LVT index " + i + " to storage index " + longsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [long[]]
            ret.add(new LdcInsnNode(longsCounter)); // [long[], idx]
            ret.add(new VarInsnNode(Opcodes.LLOAD, i)); // [long[], idx, val]
            ret.add(new InsnNode(Opcodes.LASTORE)); // []
            longsCounter++;
            break;
        case Type.DOUBLE:
            ret.add(debugMarker(markerType,
                    "Inserting double at LVT index " + i + " to storage index " + doublesCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [double[]]
            ret.add(new LdcInsnNode(doublesCounter)); // [double[], idx]
            ret.add(new VarInsnNode(Opcodes.DLOAD, i)); // [double[], idx, val]
            ret.add(new InsnNode(Opcodes.DASTORE)); // []
            doublesCounter++;
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(debugMarker(markerType,
                    "Inserting object at LVT index " + i + " to storage index " + objectsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [Object[]]
            ret.add(new LdcInsnNode(objectsCounter)); // [Object[], idx]
            ret.add(new VarInsnNode(Opcodes.ALOAD, i)); // [Object[], idx, val]
            ret.add(new InsnNode(Opcodes.AASTORE)); // []
            objectsCounter++;
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalStateException();
        }
    }

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.OperandStackStateGenerators.java

License:Open Source License

/**
 * Generates instructions to save a certain number of items from the top of the operand stack.
 * <p>/*from  ww w .j av  a2  s.  c  om*/
 * The instructions generated here expect the operand stack to be fully loaded. The stack items specified by {@code frame} must actually
 * all be on the operand stack.
 * <p>
 * REMEMBER: The items aren't returned to the operand stack after they've been saved (they have been popped off the stack). If you want
 * them back on the operand stack, reload using
 * {@code loadOperandStack(markerType, storageVars, frame, frame.getStackSize() - count, frame.getStackSize() - count, count)}.
 * @param markerType debug marker type
 * @param storageVars variables to store operand stack in to
 * @param frame execution frame at the instruction where the operand stack is to be saved
 * @param count number of items to store from the stack
 * @return instructions to save the operand stack to the storage variables
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if {@code size} is larger than the number of items in the stack at {@code frame} (or is negative),
 * or if {@code count} is larger than {@code top} (or is negative)
 */
public static InsnList saveOperandStack(MarkerType markerType, StorageVariables storageVars,
        Frame<BasicValue> frame, int count) {
    Validate.notNull(markerType);
    Validate.notNull(storageVars);
    Validate.notNull(frame);
    Validate.isTrue(count >= 0);
    Validate.isTrue(count <= frame.getStackSize());

    Variable intsVar = storageVars.getIntStorageVar();
    Variable floatsVar = storageVars.getFloatStorageVar();
    Variable longsVar = storageVars.getLongStorageVar();
    Variable doublesVar = storageVars.getDoubleStorageVar();
    Variable objectsVar = storageVars.getObjectStorageVar();

    StorageSizes storageSizes = computeSizes(frame, frame.getStackSize() - count, count);

    int intsCounter = storageSizes.getIntsSize() - 1;
    int floatsCounter = storageSizes.getFloatsSize() - 1;
    int longsCounter = storageSizes.getLongsSize() - 1;
    int doublesCounter = storageSizes.getDoublesSize() - 1;
    int objectsCounter = storageSizes.getObjectsSize() - 1;

    InsnList ret = new InsnList();

    // Create stack storage arrays and save them
    ret.add(merge(debugMarker(markerType, "Saving operand stack (" + count + " items)"),
            mergeIf(storageSizes.getIntsSize() > 0, () -> new Object[] {
                    debugMarker(markerType, "Generating ints container (" + storageSizes.getIntsSize() + ")"),
                    new LdcInsnNode(storageSizes.getIntsSize()),
                    new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_INT),
                    new VarInsnNode(Opcodes.ASTORE, intsVar.getIndex()) }),
            mergeIf(storageSizes.getFloatsSize() > 0,
                    () -> new Object[] {
                            debugMarker(markerType,
                                    "Generating floats container (" + storageSizes.getFloatsSize() + ")"),
                            new LdcInsnNode(storageSizes.getFloatsSize()),
                            new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_FLOAT),
                            new VarInsnNode(Opcodes.ASTORE, floatsVar.getIndex()) }),
            mergeIf(storageSizes.getLongsSize() > 0, () -> new Object[] {
                    debugMarker(markerType, "Generating longs container (" + storageSizes.getLongsSize() + ")"),
                    new LdcInsnNode(storageSizes.getLongsSize()),
                    new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_LONG),
                    new VarInsnNode(Opcodes.ASTORE, longsVar.getIndex()) }),
            mergeIf(storageSizes.getDoublesSize() > 0, () -> new Object[] {
                    debugMarker(markerType,
                            "Generating doubles container (" + storageSizes.getDoublesSize() + ")"),
                    new LdcInsnNode(storageSizes.getDoublesSize()),
                    new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_DOUBLE),
                    new VarInsnNode(Opcodes.ASTORE, doublesVar.getIndex()) }),
            mergeIf(storageSizes.getObjectsSize() > 0,
                    () -> new Object[] {
                            debugMarker(markerType,
                                    "Generating objects container (" + storageSizes.getObjectsSize() + ")"),
                            new LdcInsnNode(storageSizes.getObjectsSize()),
                            new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"),
                            new VarInsnNode(Opcodes.ASTORE, objectsVar.getIndex()) })));

    // Save the stack
    int start = frame.getStackSize() - 1;
    int end = frame.getStackSize() - count;
    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 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(debugMarker(markerType, "Skipping null value at " + i));
            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:
        case Type.BYTE:
        case Type.SHORT:
        case Type.CHAR:
        case Type.INT:
            ret.add(debugMarker(markerType,
                    "Popping/storing int at " + i + " to storage index " + intsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [val, int[]]
            ret.add(new InsnNode(Opcodes.SWAP)); // [int[], val]
            ret.add(new LdcInsnNode(intsCounter)); // [int[], val, idx]
            ret.add(new InsnNode(Opcodes.SWAP)); // [int[], idx, val]
            ret.add(new InsnNode(Opcodes.IASTORE)); // []
            intsCounter--;
            break;
        case Type.FLOAT:
            ret.add(debugMarker(markerType,
                    "Popping/storing float at " + i + " to storage index " + floatsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [val, float[]]
            ret.add(new InsnNode(Opcodes.SWAP)); // [float[], val]
            ret.add(new LdcInsnNode(floatsCounter)); // [float[], val, idx]
            ret.add(new InsnNode(Opcodes.SWAP)); // [float[], idx, val]
            ret.add(new InsnNode(Opcodes.FASTORE)); // []
            floatsCounter--;
            break;
        case Type.LONG:
            ret.add(debugMarker(markerType,
                    "Popping/storing long at " + i + " to storage index " + longsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [val_PART1, val_PART2, long[]]
            ret.add(new LdcInsnNode(longsCounter)); // [val_PART1, val_PART2, long[], idx]
            ret.add(new InsnNode(Opcodes.DUP2_X2)); // [long[], idx, val_PART1, val_PART2, long[], idx]
            ret.add(new InsnNode(Opcodes.POP2)); // [long[], idx, val_PART1, val_PART2]
            ret.add(new InsnNode(Opcodes.LASTORE)); // []
            longsCounter--;
            break;
        case Type.DOUBLE:
            ret.add(debugMarker(markerType,
                    "Popping/storing double at " + i + " to storage index " + doublesCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [val_PART1, val_PART2, double[]]
            ret.add(new LdcInsnNode(doublesCounter)); // [val_PART1, val_PART2, double[], idx]
            ret.add(new InsnNode(Opcodes.DUP2_X2)); // [double[], idx, val_PART1, val_PART2, double[], idx]
            ret.add(new InsnNode(Opcodes.POP2)); // [double[], idx, val_PART1, val_PART2]
            ret.add(new InsnNode(Opcodes.DASTORE)); // []
            doublesCounter--;
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(debugMarker(markerType,
                    "Popping/storing object at " + i + " to storage index " + objectsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [val, object[]]
            ret.add(new InsnNode(Opcodes.SWAP)); // [object[], val]
            ret.add(new LdcInsnNode(objectsCounter)); // [object[], val, idx]
            ret.add(new InsnNode(Opcodes.SWAP)); // [object[], idx, val]
            ret.add(new InsnNode(Opcodes.AASTORE)); // []
            objectsCounter--;
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalArgumentException();
        }
    }

    // At this point, the storage array will contain the saved operand stack AND THE STACK WILL HAVE count ITEMS POPPED OFF OF IT.
    // 
    // Reload using...
    // ---------------
    // ret.add(debugMarker(markerType, "Reloading stack items"));
    // InsnList reloadInsnList = loadOperandStack(markerType, storageVars, frame,
    //         frame.getStackSize() - count,
    //         frame.getStackSize() - count,
    //         count);
    // ret.add(reloadInsnList);

    return ret;
}

From source file:com.offbynull.coroutines.instrumenter.PackStateGenerators.java

License:Open Source License

public static InsnList packStorageArrays(MarkerType markerType, Frame<BasicValue> frame, Variable containerVar,
        StorageVariables localsStorageVars, StorageVariables operandStackStorageVars) {
    Validate.notNull(markerType);/*  w w w . j  a  va  2 s.  c  o  m*/
    Validate.notNull(frame);
    Validate.notNull(containerVar);
    Validate.notNull(localsStorageVars);
    Validate.notNull(operandStackStorageVars);

    Variable localsIntsVar = localsStorageVars.getIntStorageVar();
    Variable localsFloatsVar = localsStorageVars.getFloatStorageVar();
    Variable localsLongsVar = localsStorageVars.getLongStorageVar();
    Variable localsDoublesVar = localsStorageVars.getDoubleStorageVar();
    Variable localsObjectsVar = localsStorageVars.getObjectStorageVar();
    Variable stackIntsVar = operandStackStorageVars.getIntStorageVar();
    Variable stackFloatsVar = operandStackStorageVars.getFloatStorageVar();
    Variable stackLongsVar = operandStackStorageVars.getLongStorageVar();
    Variable stackDoublesVar = operandStackStorageVars.getDoubleStorageVar();
    Variable stackObjectsVar = operandStackStorageVars.getObjectStorageVar();

    StorageSizes stackSizes = OperandStackStateGenerators.computeSizes(frame, 0, frame.getStackSize());
    StorageSizes localsSizes = LocalsStateGenerators.computeSizes(frame);

    // Why are we using size > 0 vs checking to see if var != null?
    //
    // REMEMBER THAT the analyzer will determine the variable slots to create for storage array based on its scan of EVERY
    // continuation/suspend point in the method. Imagine the method that we're instrumenting is this...
    //
    // public void example(Continuation c, String arg1) {
    //     String var1 = "hi";
    //     c.suspend();     
    //
    //     System.out.println(var1);
    //     int var2 = 5;
    //     c.suspend();
    //
    //     System.out.println(var1 + var2);
    // }
    //
    // There are two continuation/suspend points. The analyzer determines that method will need to assign variable slots for
    // localsObjectsVar+localsIntsVar. All the other locals vars will be null.
    //
    // If we ended up using var != null instead of size > 0, things would mess up on the first suspend(). The only variable initialized
    // at the first suspend is var1. As such, LocalStateGenerator ONLY CREATES AN ARRAY FOR localsObjectsVar. It doesn't touch
    // localsIntsVar because, at the first suspend(), var2 is UNINITALIZED. Nothing has been set to that variable slot.
    //
    //
    // The same thing applies to the operand stack. It doesn't make sense to create arrays for operand stack types that don't exist yet
    // at a continuation point, even though they may exist at other continuation points furhter down

    // Storage arrays in to locals container
    return merge(
            debugMarker(markerType, "Packing storage arrays for locals and operand stack in to an Object[]"),
            new LdcInsnNode(10), new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"),
            new VarInsnNode(Opcodes.ASTORE, containerVar.getIndex()),
            mergeIf(localsSizes.getIntsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals ints in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(0), // [Object[], 0]
                            new VarInsnNode(Opcodes.ALOAD, localsIntsVar.getIndex()), // [Object[], 0, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getFloatsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals floats in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(1), // [Object[], 1]
                            new VarInsnNode(Opcodes.ALOAD, localsFloatsVar.getIndex()), // [Object[], 1, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getLongsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals longs in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(2), // [Object[], 2]
                            new VarInsnNode(Opcodes.ALOAD, localsLongsVar.getIndex()), // [Object[], 2, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getDoublesSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals doubles in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(3), // [Object[], 3]
                            new VarInsnNode(Opcodes.ALOAD, localsDoublesVar.getIndex()), // [Object[], 3, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getObjectsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals objects in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(4), // [Object[], 4]
                            new VarInsnNode(Opcodes.ALOAD, localsObjectsVar.getIndex()), // [Object[], 4, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getIntsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack ints in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(5), // [Object[], 5]
                            new VarInsnNode(Opcodes.ALOAD, stackIntsVar.getIndex()), // [Object[], 5, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getFloatsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack floats in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(6), // [Object[], 6]
                            new VarInsnNode(Opcodes.ALOAD, stackFloatsVar.getIndex()), // [Object[], 6, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getLongsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack longs in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(7), // [Object[], 7]
                            new VarInsnNode(Opcodes.ALOAD, stackLongsVar.getIndex()), // [Object[], 7, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getDoublesSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack doubles in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(8), // [Object[], 8]
                            new VarInsnNode(Opcodes.ALOAD, stackDoublesVar.getIndex()), // [Object[], 8, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getObjectsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack objects in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(9), // [Object[], 9]
                            new VarInsnNode(Opcodes.ALOAD, stackObjectsVar.getIndex()), // [Object[], 9, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }));
}

From source file:com.offbynull.coroutines.instrumenter.PackStateGenerators.java

License:Open Source License

public static InsnList unpackLocalsStorageArrays(MarkerType markerType, Frame<BasicValue> frame,
        Variable containerVar, StorageVariables localsStorageVars) {
    Validate.notNull(markerType);/*  w  w w.  ja v a  2  s . co m*/
    Validate.notNull(containerVar);
    Validate.notNull(localsStorageVars);

    Variable localsIntsVar = localsStorageVars.getIntStorageVar();
    Variable localsFloatsVar = localsStorageVars.getFloatStorageVar();
    Variable localsLongsVar = localsStorageVars.getLongStorageVar();
    Variable localsDoublesVar = localsStorageVars.getDoubleStorageVar();
    Variable localsObjectsVar = localsStorageVars.getObjectStorageVar();

    StorageSizes localsSizes = LocalsStateGenerators.computeSizes(frame);

    // Why are we using size > 0 vs checking to see if var != null?
    //
    // REMEMBER THAT the analyzer will determine the variable slots to create for storage array based on its scan of EVERY
    // continuation/suspend point in the method. Imagine the method that we're instrumenting is this...
    //
    // public void example(Continuation c, String arg1) {
    //     String var1 = "hi";
    //     c.suspend();     
    //
    //     System.out.println(var1);
    //     int var2 = 5;
    //     c.suspend();
    //
    //     System.out.println(var1 + var2);
    // }
    //
    // There are two continuation/suspend points. The analyzer determines that method will need to assign variable slots for
    // localsObjectsVar+localsIntsVar. All the other locals vars will be null.
    //
    // If we ended up using var != null instead of size > 0, things would mess up on the first suspend(). The only variable initialized
    // at the first suspend is var1. As such, LocalStateGenerator ONLY CREATES AN ARRAY FOR localsObjectsVar. It doesn't touch
    // localsIntsVar because, at the first suspend(), var2 is UNINITALIZED. Nothing has been set to that variable slot.
    //
    //
    // The same thing applies to the operand stack. It doesn't make sense to create arrays for operand stack types that don't exist yet
    // at a continuation point, even though they may exist at other continuation points furhter down

    // Storage arrays from locals container
    return merge(
            debugMarker(markerType, "Unpacking storage arrays for locals and operand stack from an Object[]"),
            mergeIf(localsSizes.getIntsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting locals ints from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(0), // [Object[], 0]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, localsIntsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, localsIntsVar.getIndex()), // []
                    }),
            mergeIf(localsSizes.getFloatsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting locals floats from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(1), // [Object[], 1]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, localsFloatsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, localsFloatsVar.getIndex()), // []
                    }),
            mergeIf(localsSizes.getLongsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting locals longs from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(2), // [Object[], 2]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, localsLongsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, localsLongsVar.getIndex()), // []
                    }),
            mergeIf(localsSizes.getDoublesSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting locals doubles from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(3), // [Object[], 3]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, localsDoublesVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, localsDoublesVar.getIndex()), // []
                    }),
            mergeIf(localsSizes.getObjectsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting locals objects from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(4), // [Object[], 4]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, localsObjectsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, localsObjectsVar.getIndex()), // []
                    }));
}

From source file:com.offbynull.coroutines.instrumenter.PackStateGenerators.java

License:Open Source License

public static InsnList unpackOperandStackStorageArrays(MarkerType markerType, Frame<BasicValue> frame,
        Variable containerVar, StorageVariables operandStackStorageVars) {
    Validate.notNull(markerType);/*w  ww  .  j  a v a  2  s .c  o  m*/
    Validate.notNull(containerVar);
    Validate.notNull(operandStackStorageVars);

    Variable stackIntsVar = operandStackStorageVars.getIntStorageVar();
    Variable stackFloatsVar = operandStackStorageVars.getFloatStorageVar();
    Variable stackLongsVar = operandStackStorageVars.getLongStorageVar();
    Variable stackDoublesVar = operandStackStorageVars.getDoubleStorageVar();
    Variable stackObjectsVar = operandStackStorageVars.getObjectStorageVar();

    StorageSizes stackSizes = OperandStackStateGenerators.computeSizes(frame, 0, frame.getStackSize());

    // Why are we using size > 0 vs checking to see if var != null?
    //
    // REMEMBER THAT the analyzer will determine the variable slots to create for storage array based on its scan of EVERY
    // continuation/suspend point in the method. Imagine the method that we're instrumenting is this...
    //
    // public void example(Continuation c, String arg1) {
    //     String var1 = "hi";
    //     c.suspend();     
    //
    //     System.out.println(var1);
    //     int var2 = 5;
    //     c.suspend();
    //
    //     System.out.println(var1 + var2);
    // }
    //
    // There are two continuation/suspend points. The analyzer determines that method will need to assign variable slots for
    // localsObjectsVar+localsIntsVar. All the other locals vars will be null.
    //
    // If we ended up using var != null instead of size > 0, things would mess up on the first suspend(). The only variable initialized
    // at the first suspend is var1. As such, LocalStateGenerator ONLY CREATES AN ARRAY FOR localsObjectsVar. It doesn't touch
    // localsIntsVar because, at the first suspend(), var2 is UNINITALIZED. Nothing has been set to that variable slot.
    //
    //
    // The same thing applies to the operand stack. It doesn't make sense to create arrays for operand stack types that don't exist yet
    // at a continuation point, even though they may exist at other continuation points furhter down

    // Storage arrays from locals container
    return merge(debugMarker(markerType, "Unpacking storage arrays for operand stack from an Object[]"),
            mergeIf(stackSizes.getIntsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting stack ints from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(5), // [Object[], 5]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, stackIntsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, stackIntsVar.getIndex()), // []
                    }),
            mergeIf(stackSizes.getFloatsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting stack floats from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(6), // [Object[], 6]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, stackFloatsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, stackFloatsVar.getIndex()), // []
                    }),
            mergeIf(stackSizes.getLongsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting stack longs from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(7), // [Object[], 7]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, stackLongsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, stackLongsVar.getIndex()), // []
                    }),
            mergeIf(stackSizes.getDoublesSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting stack doubles from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(8), // [Object[], 8]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, stackDoublesVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, stackDoublesVar.getIndex()), // []
                    }),
            mergeIf(stackSizes.getObjectsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Getting stack objects from to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(9), // [Object[], 9]
                            new InsnNode(Opcodes.AALOAD), // [val]
                            new TypeInsnNode(Opcodes.CHECKCAST, stackObjectsVar.getType().getInternalName()), // [val] REQ BY JVM SO TYPE IS KNOWN
                            new VarInsnNode(Opcodes.ASTORE, stackObjectsVar.getIndex()), // []
                    }));
}

From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.DefUseChains.java

License:Open Source License

private static void removeUnboxedValueInsns(AbstractInterpretationValue val, ByteCodeMethodVisitor bcmv) {
    for (Insn i : val.getDefs())
        removeInsn(bcmv, i, val, "RemovingBoxedValueDefinition");

    for (Insn i : val.getUses()) {
        if (i.isBoxingMethod()) {
            removeInsn(bcmv, i, val, "RemoveBoxingMethod");
        } else if (i.isUnBoxingMethod()) {
            removeInsn(bcmv, i, val, "UnboxingMethod");
        } else if (i.isCheckCast()) {
            removeInsn(bcmv, i, val, "CheckCast"); // FIXME CHF
        } else if (i instanceof VarInsn) {
            VarInsn vi = (VarInsn) i;//w  ww .  j  a  v  a  2  s . co m
            if (vi.opcode == Opcodes.ASTORE) {
                int j = bcmv.insns.indexOf(i);
                removeInsn(bcmv, i, val, "astoreconversion" + val.getType());
                if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FZZ32;"))
                    bcmv.insns.add(j, new VarInsn("ISTORE", Opcodes.ISTORE, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FZZ64;"))
                    bcmv.insns.add(j, new VarInsn("LSTORE", Opcodes.LSTORE, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FRR32;"))
                    bcmv.insns.add(j, new VarInsn("FSTORE", Opcodes.FSTORE, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FRR64;"))
                    bcmv.insns.add(j, new VarInsn("DSTORE", Opcodes.DSTORE, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FBoolean;"))
                    bcmv.insns.add(j, new VarInsn("ISTORE", Opcodes.ISTORE, val.getValueNumber(), vi.index));
                else
                    bcmv.insns.add(j, new VarInsn("ASTORE", Opcodes.ASTORE, val.getValueNumber(), vi.index));
            } else if (vi.opcode == Opcodes.ALOAD) {
                int j = bcmv.insns.indexOf(i);
                removeInsn(bcmv, i, val, "Aloadconversion" + val.getType());
                if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FZZ32;"))
                    bcmv.insns.add(j, new VarInsn("ILOAD", Opcodes.ILOAD, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FZZ64;"))
                    bcmv.insns.add(j, new VarInsn("LLOAD", Opcodes.LLOAD, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FRR32;"))
                    bcmv.insns.add(j, new VarInsn("FLOAD", Opcodes.FLOAD, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FRR64;"))
                    bcmv.insns.add(j, new VarInsn("DLOAD", Opcodes.DLOAD, val.getValueNumber(), vi.index));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FBoolean;"))
                    bcmv.insns.add(j, new VarInsn("ILOAD", Opcodes.ILOAD, val.getValueNumber(), vi.index));
                else
                    bcmv.insns.add(j, new VarInsn("ALOAD", Opcodes.ALOAD, val.getValueNumber(), vi.index));
            }
        } else if (i instanceof SingleInsn) {
            SingleInsn si = (SingleInsn) i;
            if (si.opcode == Opcodes.ARETURN) {
                int j = bcmv.insns.indexOf(i);
                if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FZZ32;"))
                    bcmv.insns.add(j, new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                            "com/sun/fortress/compiler/runtimeValues/FZZ32", "make",
                            "(I)Lcom/sun/fortress/compiler/runtimeValues/FZZ32;", "ReboxingReturnValue"));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FZZ64;"))
                    bcmv.insns.add(j, new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                            "com/sun/fortress/compiler/runtimeValues/FZZ64", "make",
                            "(J)Lcom/sun/fortress/compiler/runtimeValues/FZZ64;", "ReboxingReturnValue"));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FRR32;"))
                    bcmv.insns.add(j, new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                            "com/sun/fortress/compiler/runtimeValues/FRR32", "make",
                            "(F)Lcom/sun/fortress/compiler/runtimeValues/FRR32;", "ReboxingReturnValue"));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FRR64;"))
                    bcmv.insns.add(j, new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                            "com/sun/fortress/compiler/runtimeValues/FRR64", "make",
                            "(D)Lcom/sun/fortress/compiler/runtimeValues/FRR64;", "ReboxingReturnValue"));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FVoid;"))
                    bcmv.insns.add(j, new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                            "com/sun/fortress/compiler/runtimeValues/FVoid", "make",
                            "()Lcom/sun/fortress/compiler/runtimeValues/FVoid;", "ReboxingReturnValue"));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FBoolean;"))
                    bcmv.insns.add(j, new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                            "com/sun/fortress/compiler/runtimeValues/FBoolean", "make",
                            "(Z)Lcom/sun/fortress/compiler/runtimeValues/FBoolean;", "ReboxingReturnValue"));
                else if (val.getType().equals("Lcom/sun/fortress/compiler/runtimeValues/FJavaString;"))
                    bcmv.insns.add(j,
                            new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC,
                                    "com/sun/fortress/compiler/runtimeValues/FJavaString", "make",
                                    "(java.lang.String)Lcom/sun/fortress/compiler/runtimeValues/FJavaString;",
                                    "ReboxingReturnValue"));
                else
                    throw new RuntimeException("Don't recognize var type " + val.getType());
            }
        }
    }
}