Example usage for org.objectweb.asm.tree.analysis Frame getLocal

List of usage examples for org.objectweb.asm.tree.analysis Frame getLocal

Introduction

In this page you can find the example usage for org.objectweb.asm.tree.analysis Frame getLocal.

Prototype

public V getLocal(final int index) 

Source Link

Document

Returns the value of the given local variable.

Usage

From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java

License:Open Source License

private void emitStoreState(MethodVisitor mv, int idx, FrameInfo fi, int numArgsToPreserve) {
    Frame f = frames[fi.endInstruction];

    if (fi.lBefore != null)
        fi.lBefore.accept(mv);//w  ww .ja v  a 2  s. c  o m

    mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
    emitConst(mv, idx);
    emitConst(mv, fi.numSlots);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "pushMethod", "(II)V");

    // store operand stack
    for (int i = f.getStackSize(); i-- > 0;) {
        BasicValue v = (BasicValue) f.getStack(i);
        if (!isOmitted(v)) {
            if (!isNullType(v)) {
                int slotIdx = fi.stackSlotIndices[i];
                assert slotIdx >= 0 && slotIdx < fi.numSlots;
                emitStoreValue(mv, v, lvarStack, slotIdx, -1);
            } else {
                db.log(LogLevel.DEBUG, "NULL stack entry: type=%s size=%d", v.getType(), v.getSize());
                mv.visitInsn(Opcodes.POP);
            }
        }
    }

    // store local vars
    for (int i = firstLocal; i < f.getLocals(); i++) {
        BasicValue v = (BasicValue) f.getLocal(i);
        if (!isNullType(v)) {
            mv.visitVarInsn(v.getType().getOpcode(Opcodes.ILOAD), i);
            int slotIdx = fi.localSlotIndices[i];
            assert slotIdx >= 0 && slotIdx < fi.numSlots;
            emitStoreValue(mv, v, lvarStack, slotIdx, i);
        }
    }

    // restore last numArgsToPreserve operands
    for (int i = f.getStackSize() - numArgsToPreserve; i < f.getStackSize(); i++) {
        BasicValue v = (BasicValue) f.getStack(i);
        if (!isOmitted(v)) {
            if (!isNullType(v)) {
                int slotIdx = fi.stackSlotIndices[i];
                assert slotIdx >= 0 && slotIdx < fi.numSlots;
                emitRestoreValue(mv, v, lvarStack, slotIdx, -1);
            } else {
                mv.visitInsn(Opcodes.ACONST_NULL);
            }
        }
    }
}

From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java

License:Open Source License

private void emitRestoreState(MethodVisitor mv, int idx, FrameInfo fi, int numArgsPreserved) {
    Frame f = frames[fi.endInstruction];

    // restore local vars
    for (int i = firstLocal; i < f.getLocals(); i++) {
        BasicValue v = (BasicValue) f.getLocal(i);
        if (!isNullType(v)) {
            int slotIdx = fi.localSlotIndices[i];
            assert slotIdx >= 0 && slotIdx < fi.numSlots;
            emitRestoreValue(mv, v, lvarStack, slotIdx, i);
            mv.visitVarInsn(v.getType().getOpcode(Opcodes.ISTORE), i);
        } else if (v != BasicValue.UNINITIALIZED_VALUE) {
            mv.visitInsn(Opcodes.ACONST_NULL);
            mv.visitVarInsn(Opcodes.ASTORE, i);
        }/*from  w  w  w .  j a  v a  2 s  .  co m*/
    }

    // restore operand stack
    for (int i = 0; i < f.getStackSize() - numArgsPreserved; i++) {
        BasicValue v = (BasicValue) f.getStack(i);
        if (!isOmitted(v)) {
            if (!isNullType(v)) {
                int slotIdx = fi.stackSlotIndices[i];
                assert slotIdx >= 0 && slotIdx < fi.numSlots;
                emitRestoreValue(mv, v, lvarStack, slotIdx, -1);
            } else {
                mv.visitInsn(Opcodes.ACONST_NULL);
            }
        }
    }

    if (fi.lAfter != null) {
        fi.lAfter.accept(mv);
    }
}

From source file:com.dragome.callbackevictor.serverside.bytecode.transformation.asm.ContinuationMethodAdapter.java

License:Apache License

public void visitCode() {
    mv.visitCode();/*  w w w .j a v  a 2  s  .com*/

    int fsize = labels.size();
    Label[] restoreLabels = new Label[fsize];
    for (int i = 0; i < restoreLabels.length; i++) {
        restoreLabels[i] = new Label();
    }

    // verify if restoring
    Label l0 = new Label();

    // PC: StackRecorder stackRecorder = StackRecorder.get();
    mv.visitMethodInsn(INVOKESTATIC, STACK_RECORDER, "get", "()L" + STACK_RECORDER + ";", false);
    mv.visitInsn(DUP);
    mv.visitVarInsn(ASTORE, stackRecorderVar);
    mv.visitLabel(startLabel);

    // PC: if (stackRecorder != null && !stackRecorder.isRestoring) {  
    mv.visitJumpInsn(IFNULL, l0);
    mv.visitVarInsn(ALOAD, stackRecorderVar);
    mv.visitFieldInsn(GETFIELD, STACK_RECORDER, "isRestoring", "Z");
    mv.visitJumpInsn(IFEQ, l0);

    mv.visitVarInsn(ALOAD, stackRecorderVar);
    // PC:    stackRecorder.popInt();
    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Int", "()I", false);
    mv.visitTableSwitchInsn(0, fsize - 1, l0, restoreLabels);

    // switch cases
    for (int i = 0; i < fsize; i++) {
        Label frameLabel = labels.get(i);
        mv.visitLabel(restoreLabels[i]);

        MethodInsnNode mnode = nodes.get(i);
        Frame frame = analyzer.getFrames()[canalyzer.getIndex(mnode)];

        // for each local variable store the value in locals popping it from the stack!
        // locals
        int lsize = frame.getLocals();
        for (int j = lsize - 1; j >= 0; j--) {
            BasicValue value = (BasicValue) frame.getLocal(j);
            if (isNull(value)) {
                mv.visitInsn(ACONST_NULL);
                mv.visitVarInsn(ASTORE, j);
            } else if (value == BasicValue.UNINITIALIZED_VALUE) {
                // TODO ??
            } else if (value == BasicValue.RETURNADDRESS_VALUE) {
                // TODO ??
            } else {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                Type type = value.getType();
                if (value.isReference()) {
                    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object",
                            "()Ljava/lang/Object;", false);
                    Type t = value.getType();
                    String desc = t.getDescriptor();
                    if (desc.charAt(0) == '[') {
                        mv.visitTypeInsn(CHECKCAST, desc);
                    } else {
                        mv.visitTypeInsn(CHECKCAST, t.getInternalName());
                    }
                    mv.visitVarInsn(ASTORE, j);

                } else {
                    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type),
                            "()" + type.getDescriptor(), false);
                    mv.visitVarInsn(type.getOpcode(ISTORE), j);
                }
            }
        }

        if (frame instanceof MonitoringFrame) {
            int[] monitoredLocals = ((MonitoringFrame) frame).getMonitored();
            // System.out.println(System.identityHashCode(frame)+" AMonitored locals "+monitoredLocals.length);
            for (int monitoredLocal : monitoredLocals) {
                // System.out.println(System.identityHashCode(frame)+" AMonitored local "+monitoredLocals[j]);
                mv.visitVarInsn(ALOAD, monitoredLocal);
                mv.visitInsn(MONITORENTER);
            }
        }

        // stack
        int argSize = Type.getArgumentTypes(mnode.desc).length;
        int ownerSize = mnode.getOpcode() == INVOKESTATIC ? 0 : 1; // TODO
        int initSize = mnode.name.equals("<init>") ? 2 : 0;
        int ssize = frame.getStackSize();
        for (int j = 0; j < ssize - argSize - ownerSize - initSize; j++) {
            BasicValue value = (BasicValue) frame.getStack(j);
            if (isNull(value)) {
                mv.visitInsn(ACONST_NULL);
            } else if (value == BasicValue.UNINITIALIZED_VALUE) {
                // TODO ??
            } else if (value == BasicValue.RETURNADDRESS_VALUE) {
                // TODO ??
            } else if (value.isReference()) {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object", "()Ljava/lang/Object;",
                        false);
                mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName());
            } else {
                Type type = value.getType();
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type),
                        "()" + type.getDescriptor(), false);
            }
        }

        boolean hasMethodRef = false;
        if (mnode.getOpcode() != INVOKESTATIC) {
            // Load the object whose method we are calling  
            BasicValue value = ((BasicValue) frame.getStack(ssize - argSize - 1));
            if (isNull(value)) {
                // If user code causes NPE, then we keep this behavior: load null to get NPE at runtime 
                mv.visitInsn(ACONST_NULL);
            } else {
                hasMethodRef = true;

                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Reference",
                        "()Ljava/lang/Object;", false);
                mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName());

            }
        }

        // Create null types for the parameters of the method invocation
        // RS:
        if (hasMethodRef && canalyzer._continueReflection && mnode.name.contains("invoke")
                && mnode.owner.contains("java/lang/reflect/Method")) {
            ContinuationMethodAnalyzer.MyVariables vars = canalyzer._reflectMapping.get(mnode);
            mv.visitVarInsn(ALOAD, vars.objectVar());
            mv.visitVarInsn(ALOAD, vars.argsVar());
            //mv.visitVarInsn(ALOAD, 2);
            //mv.visitVarInsn(ALOAD, 4);
        }
        //RS:
        else {
            for (Type paramType : Type.getArgumentTypes(mnode.desc)) {
                pushDefault(paramType);
            }
        }

        // continue to the next method
        mv.visitJumpInsn(GOTO, frameLabel);
    }

    // PC: }
    // end of start block
    mv.visitLabel(l0);
}

From source file:com.googlecode.dex2jar.test.TestUtils.java

License:Apache License

static void printAnalyzerResult(MethodNode method, Analyzer a, final PrintWriter pw)
        throws IllegalArgumentException, IllegalAccessException {
    Frame[] frames = a.getFrames();
    Textifier t = new Textifier();
    TraceMethodVisitor mv = new TraceMethodVisitor(t);
    String format = "%05d %-" + (method.maxStack + method.maxLocals + 6) + "s|%s";
    for (int j = 0; j < method.instructions.size(); ++j) {
        method.instructions.get(j).accept(mv);

        StringBuffer s = new StringBuffer();
        Frame f = frames[j];
        if (f == null) {
            s.append('?');
        } else {// www  .  j av  a2 s .  co  m
            for (int k = 0; k < f.getLocals(); ++k) {
                s.append(getShortName(f.getLocal(k).toString()));
            }
            s.append(" : ");
            for (int k = 0; k < f.getStackSize(); ++k) {
                s.append(getShortName(f.getStack(k).toString()));
            }
        }
        pw.printf(format, j, s, buf.get(t)); // mv.text.get(j));
    }
    for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
        ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv);
        pw.print(" " + buf.get(t));
    }
    pw.println();
    pw.flush();
}

From source file:com.googlecode.dex2jar.tools.AsmVerify.java

License:Apache License

static void printAnalyzerResult(MethodNode method, Analyzer a, final PrintWriter pw)
        throws IllegalArgumentException {
    Frame[] frames = a.getFrames();
    Textifier t = new Textifier();
    TraceMethodVisitor mv = new TraceMethodVisitor(t);
    String format = "%05d %-" + (method.maxStack + method.maxLocals + 6) + "s|%s";
    for (int j = 0; j < method.instructions.size(); ++j) {
        method.instructions.get(j).accept(mv);

        StringBuffer s = new StringBuffer();
        Frame f = frames[j];
        if (f == null) {
            s.append('?');
        } else {/*  w w w  . java  2s .  com*/
            for (int k = 0; k < f.getLocals(); ++k) {
                s.append(getShortName(f.getLocal(k).toString()));
            }
            s.append(" : ");
            for (int k = 0; k < f.getStackSize(); ++k) {
                s.append(getShortName(f.getStack(k).toString()));
            }
        }
        try {
            pw.printf(format, j, s, buf.get(t)); // mv.text.get(j));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    for (TryCatchBlockNode tryCatchBlockNode : method.tryCatchBlocks) {
        tryCatchBlockNode.accept(mv);
        try {
            pw.print(" " + buf.get(t));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    pw.println();
    pw.flush();
}

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. ja  va 2s . co  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 w w. ja v  a2  s . c  o  m
 */
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/*from w w  w .  j a va2s  .  co  m*/
 * @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/*  w  w  w.  ja 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.LocalsStateGenerators.java

License:Open Source License

/**
 * Compute sizes required for the storage arrays that will contain the local variables table at this frame.
 * @param frame frame to compute for//from   ww w .ja  va  2  s. c  o  m
 * @return size required by each storage array
 * @throws NullPointerException if any argument is {@code null}
 */
public static StorageSizes computeSizes(Frame<BasicValue> frame) {
    Validate.notNull(frame);

    // Count size required for each storage array
    int intsSize = 0;
    int longsSize = 0;
    int floatsSize = 0;
    int doublesSize = 0;
    int objectsSize = 0;
    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;
        }

        switch (type.getSort()) {
        case Type.BOOLEAN:
        case Type.BYTE:
        case Type.SHORT:
        case Type.CHAR:
        case Type.INT:
            intsSize++;
            break;
        case Type.FLOAT:
            floatsSize++;
            break;
        case Type.LONG:
            longsSize++;
            break;
        case Type.DOUBLE:
            doublesSize++;
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            objectsSize++;
            break;
        case Type.METHOD:
        case Type.VOID:
        default:
            throw new IllegalStateException();
        }
    }

    return new StorageSizes(intsSize, longsSize, floatsSize, doublesSize, objectsSize);
}