Example usage for org.objectweb.asm Opcodes MONITORENTER

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

Introduction

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

Prototype

int MONITORENTER

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

Click Source Link

Usage

From source file:com.google.test.metric.asm.MethodVisitorBuilder.java

License:Apache License

public void visitInsn(final int opcode) {
    switch (opcode) {
    case Opcodes.ACONST_NULL:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Load(lineNumber, new Constant(null, JavaType.OBJECT)));
            }/*from  w  w  w  .j a  va2 s . c  om*/
        });
        break;
    case Opcodes.ICONST_M1:
    case Opcodes.ICONST_0:
    case Opcodes.ICONST_1:
    case Opcodes.ICONST_2:
    case Opcodes.ICONST_3:
    case Opcodes.ICONST_4:
    case Opcodes.ICONST_5:
        loadConstant(opcode - Opcodes.ICONST_M1 - 1, JavaType.INT);
        break;
    case Opcodes.LCONST_0:
    case Opcodes.LCONST_1:
        loadConstant(opcode - Opcodes.LCONST_0, JavaType.LONG);
        break;
    case Opcodes.FCONST_0:
    case Opcodes.FCONST_1:
    case Opcodes.FCONST_2:
        loadConstant(opcode - Opcodes.FCONST_0, JavaType.FLOAT);
        break;
    case Opcodes.DCONST_0:
    case Opcodes.DCONST_1:
        loadConstant(opcode - Opcodes.DCONST_0, JavaType.DOUBLE);
        break;
    case Opcodes.IALOAD:
        recordArrayLoad(JavaType.INT);
        break;
    case Opcodes.LALOAD:
        recordArrayLoad(JavaType.LONG);
        break;
    case Opcodes.FALOAD:
        recordArrayLoad(JavaType.FLOAT);
        break;
    case Opcodes.DALOAD:
        recordArrayLoad(JavaType.DOUBLE);
        break;
    case Opcodes.AALOAD:
        recordArrayLoad(JavaType.OBJECT);
        break;
    case Opcodes.BALOAD:
        recordArrayLoad(JavaType.BYTE);
        break;
    case Opcodes.CALOAD:
        recordArrayLoad(JavaType.CHAR);
        break;
    case Opcodes.SALOAD:
        recordArrayLoad(JavaType.SHORT);
        break;

    case Opcodes.IASTORE:
        recordArrayStore(JavaType.INT);
        break;
    case Opcodes.LASTORE:
        recordArrayStore(JavaType.LONG);
        break;
    case Opcodes.FASTORE:
        recordArrayStore(JavaType.FLOAT);
        break;
    case Opcodes.DASTORE:
        recordArrayStore(JavaType.DOUBLE);
        break;
    case Opcodes.AASTORE:
        recordArrayStore(JavaType.OBJECT);
        break;
    case Opcodes.BASTORE:
        recordArrayStore(JavaType.BYTE);
        break;
    case Opcodes.CASTORE:
        recordArrayStore(JavaType.CHAR);
        break;
    case Opcodes.SASTORE:
        recordArrayStore(JavaType.SHORT);
        break;
    case Opcodes.POP:
    case Opcodes.POP2:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Pop(lineNumber, opcode - Opcodes.POP + 1));
            }
        });
        break;
    case Opcodes.DUP:
    case Opcodes.DUP_X1:
    case Opcodes.DUP_X2:
        recorder.add(new Runnable() {
            public void run() {
                int offset = opcode - Opcodes.DUP;
                block.addOp(new Duplicate(lineNumber, offset));
            }
        });
        break;
    case Opcodes.DUP2:
    case Opcodes.DUP2_X1:
    case Opcodes.DUP2_X2:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Duplicate2(lineNumber, opcode - Opcodes.DUP2));
            }
        });
        break;
    case Opcodes.SWAP:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Swap(lineNumber));
            }
        });
        break;
    case Opcodes.IRETURN:
        _return(JavaType.INT);
        break;
    case Opcodes.FRETURN:
        _return(JavaType.FLOAT);
        break;
    case Opcodes.ARETURN:
        _return(JavaType.OBJECT);
        break;
    case Opcodes.LRETURN:
        _return(JavaType.LONG);
        break;
    case Opcodes.DRETURN:
        _return(JavaType.DOUBLE);
        break;
    case Opcodes.ATHROW:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Throw(lineNumber));
            }
        });
        break;
    case Opcodes.RETURN:
        _return(JavaType.VOID);
        break;
    case Opcodes.LCMP:
        operation("cmp", JavaType.LONG, JavaType.LONG, JavaType.INT);
        break;
    case Opcodes.FCMPL:
        operation("cmpl", JavaType.FLOAT, JavaType.FLOAT, JavaType.INT);
        break;
    case Opcodes.FCMPG:
        operation("cmpg", JavaType.FLOAT, JavaType.FLOAT, JavaType.INT);
        break;
    case Opcodes.DCMPL:
        operation("cmpl", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.INT);
        break;
    case Opcodes.DCMPG:
        operation("cmpg", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.INT);
        break;
    case Opcodes.LSHL:
        operation("shl", JavaType.LONG, JavaType.INT, JavaType.LONG);
        break;
    case Opcodes.LSHR:
        operation("shr", JavaType.LONG, JavaType.INT, JavaType.LONG);
        break;
    case Opcodes.LUSHR:
        operation("ushr", JavaType.LONG, JavaType.INT, JavaType.LONG);
        break;
    case Opcodes.LADD:
        operation("add", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LSUB:
        operation("sub", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LDIV:
        operation("div", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LREM:
        operation("rem", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LAND:
        operation("and", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LOR:
        operation("or", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LXOR:
        operation("xor", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.LMUL:
        operation("mul", JavaType.LONG, JavaType.LONG, JavaType.LONG);
        break;
    case Opcodes.FADD:
        operation("add", JavaType.FLOAT, JavaType.FLOAT, JavaType.FLOAT);
        break;
    case Opcodes.FSUB:
        operation("sub", JavaType.FLOAT, JavaType.FLOAT, JavaType.FLOAT);
        break;
    case Opcodes.FMUL:
        operation("mul", JavaType.FLOAT, JavaType.FLOAT, JavaType.FLOAT);
        break;
    case Opcodes.FREM:
        operation("rem", JavaType.FLOAT, JavaType.FLOAT, JavaType.FLOAT);
        break;
    case Opcodes.FDIV:
        operation("div", JavaType.FLOAT, JavaType.FLOAT, JavaType.FLOAT);
        break;
    case Opcodes.ISHL:
        operation("shl", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.ISHR:
        operation("shr", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IUSHR:
        operation("ushr", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IADD:
        operation("add", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.ISUB:
        operation("sub", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IMUL:
        operation("mul", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IDIV:
        operation("div", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IREM:
        operation("rem", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IAND:
        operation("and", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IOR:
        operation("or", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.IXOR:
        operation("xor", JavaType.INT, JavaType.INT, JavaType.INT);
        break;
    case Opcodes.DSUB:
        operation("sub", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.DOUBLE);
        break;
    case Opcodes.DADD:
        operation("add", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.DOUBLE);
        break;
    case Opcodes.DMUL:
        operation("mul", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.DOUBLE);
        break;
    case Opcodes.DDIV:
        operation("div", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.DOUBLE);
        break;
    case Opcodes.DREM:
        operation("rem", JavaType.DOUBLE, JavaType.DOUBLE, JavaType.DOUBLE);
        break;
    case Opcodes.L2I:
        convert(JavaType.LONG, JavaType.INT);
        break;
    case Opcodes.L2F:
        convert(JavaType.LONG, JavaType.FLOAT);
        break;
    case Opcodes.L2D:
        convert(JavaType.LONG, JavaType.DOUBLE);
        break;
    case Opcodes.LNEG:
        operation("neg", JavaType.LONG, null, JavaType.LONG);
        break;
    case Opcodes.F2I:
        convert(JavaType.FLOAT, JavaType.INT);
        break;
    case Opcodes.F2L:
        convert(JavaType.FLOAT, JavaType.LONG);
        break;
    case Opcodes.FNEG:
        operation("neg", JavaType.FLOAT, null, JavaType.FLOAT);
        break;
    case Opcodes.F2D:
        convert(JavaType.FLOAT, JavaType.DOUBLE);
        break;
    case Opcodes.D2I:
        convert(JavaType.DOUBLE, JavaType.INT);
        break;
    case Opcodes.D2L:
        convert(JavaType.DOUBLE, JavaType.LONG);
        break;
    case Opcodes.D2F:
        convert(JavaType.DOUBLE, JavaType.FLOAT);
        break;
    case Opcodes.DNEG:
        operation("neg", JavaType.DOUBLE, null, JavaType.DOUBLE);
        break;
    case Opcodes.I2L:
        convert(JavaType.INT, JavaType.LONG);
        break;
    case Opcodes.I2F:
        convert(JavaType.INT, JavaType.FLOAT);
        break;
    case Opcodes.I2D:
        convert(JavaType.INT, JavaType.DOUBLE);
        break;
    case Opcodes.I2B:
        convert(JavaType.INT, JavaType.BYTE);
        break;
    case Opcodes.I2C:
        convert(JavaType.INT, JavaType.CHAR);
        break;
    case Opcodes.I2S:
        convert(JavaType.INT, JavaType.SHORT);
        break;
    case Opcodes.INEG:
        operation("neg", JavaType.INT, null, JavaType.INT);
        break;
    case Opcodes.ARRAYLENGTH:
        operation("arraylength", JavaType.OBJECT.toArray(), null, JavaType.INT);
        break;
    case Opcodes.MONITORENTER:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new MonitorEnter(lineNumber));
            }
        });
        break;
    case Opcodes.MONITOREXIT:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new MonitorExit(lineNumber));
            }
        });
        break;
    case Opcodes.NOP:
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Transform(lineNumber, "NOP", null, null, null));
            }
        });
    }
}

From source file:com.mebigfatguy.junitflood.jvm.OperandStack.java

License:Apache License

public void performInsn(int opcode) {
    switch (opcode) {
    case Opcodes.NOP:
        break;//w  w w  .j av a2  s. c o m

    case Opcodes.ACONST_NULL: {
        Operand op = new Operand();
        op.setNull(true);
        push(op);
    }
        break;

    case Opcodes.ICONST_M1: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(-1));
        push(op);
    }
        break;

    case Opcodes.ICONST_0: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(0));
        push(op);
    }
        break;

    case Opcodes.ICONST_1: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(1));
        push(op);
    }
        break;

    case Opcodes.ICONST_2: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(2));
        push(op);
    }
        break;

    case Opcodes.ICONST_3: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(3));
        push(op);
    }
        break;

    case Opcodes.ICONST_4: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(4));
        push(op);
    }
        break;

    case Opcodes.ICONST_5: {
        Operand op = new Operand();
        op.setConstant(Integer.valueOf(5));
        push(op);
    }
        break;

    case Opcodes.LCONST_0: {
        Operand op = new Operand();
        op.setConstant(Long.valueOf(0));
        push(op);
    }
        break;

    case Opcodes.LCONST_1: {
        Operand op = new Operand();
        op.setConstant(Long.valueOf(1));
        push(op);
    }
        break;

    case Opcodes.FCONST_0: {
        Operand op = new Operand();
        op.setConstant(Float.valueOf(0));
        push(op);
    }
        break;

    case Opcodes.FCONST_1: {
        Operand op = new Operand();
        op.setConstant(Float.valueOf(1));
        push(op);
    }
        break;

    case Opcodes.FCONST_2: {
        Operand op = new Operand();
        op.setConstant(Float.valueOf(2));
        push(op);
    }
        break;

    case Opcodes.DCONST_0: {
        Operand op = new Operand();
        op.setConstant(Double.valueOf(0));
        push(op);
    }
        break;

    case Opcodes.DCONST_1: {
        Operand op = new Operand();
        op.setConstant(Double.valueOf(1));
        push(op);
    }
        break;

    case Opcodes.IALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.AALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("Ljava/lang/Object;");
        push(op);
    }
        break;

    case Opcodes.BALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("B");
        push(op);
    }
        break;

    case Opcodes.CALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("C");
        push(op);
    }
        break;

    case Opcodes.SALOAD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("S");
        push(op);
    }
        break;

    case Opcodes.IASTORE:
    case Opcodes.LASTORE:
    case Opcodes.FASTORE:
    case Opcodes.DASTORE:
    case Opcodes.AASTORE:
    case Opcodes.BASTORE:
    case Opcodes.CASTORE:
    case Opcodes.SASTORE:
        if (stack.size() < 2) {
            stack.clear();
        } else {
            Operand value = stack.remove(stack.size() - 1);
            Operand reg = stack.remove(stack.size() - 1);
            registers.put(Integer.valueOf(reg.getRegister()), value);
        }
        break;

    case Opcodes.POP:
        pop();
        break;

    case Opcodes.POP2:
        pop2();
        break;

    case Opcodes.DUP:
        if (!stack.isEmpty()) {
            Operand op = stack.get(stack.size() - 1);
            push(op);
        }
        break;

    case Opcodes.DUP_X1:
        if (stack.size() >= 2) {
            Operand op = stack.get(stack.size() - 1);
            stack.add(stack.size() - 2, op);
        }
        break;

    case Opcodes.DUP_X2:
        if (stack.size() >= 2) {
            Operand op = stack.get(stack.size() - 2);
            String sig = op.getSignature();
            op = stack.get(stack.size() - 1);
            if ("J".equals(sig) || "D".equals(sig)) {
                stack.add(stack.size() - 2, op);
            } else if (stack.size() >= 3) {
                stack.add(stack.size() - 3, op);
            }
        }
        break;

    case Opcodes.DUP2:
        if (stack.size() >= 2) {
            stack.add(stack.get(stack.size() - 2));
            stack.add(stack.get(stack.size() - 2));
        }
        break;

    case Opcodes.DUP2_X1:
        if (stack.size() >= 1) {
            Operand op = stack.get(stack.size() - 1);
            String sig = op.getSignature();
            if ("J".equals(sig) || "D".equals(sig)) {
                if (stack.size() >= 3) {
                    stack.add(stack.size() - 3, op);
                    op = stack.get(stack.size() - 2);
                    stack.add(stack.size() - 4, op);
                }
            } else {
                if (stack.size() >= 2) {
                    stack.add(stack.size() - 2, op);
                }
            }
        }
        break;

    case Opcodes.DUP2_X2:
        if (stack.size() >= 1) {
            Operand op = stack.get(stack.size() - 1);
            String sig = op.getSignature();
            if ("J".equals(sig) || "D".equals(sig)) {
                if (stack.size() >= 2) {
                    op = stack.get(stack.size() - 2);
                    sig = op.getSignature();
                    if ("J".equals(sig) || "D".equals(sig)) {
                        op = stack.get(stack.size() - 1);
                        stack.add(stack.size() - 2, op);
                    } else {
                        if (stack.size() >= 3) {
                            op = stack.get(stack.size() - 1);
                            stack.add(stack.size() - 3, op);
                        }
                    }
                }
            } else {
                if (stack.size() >= 3) {
                    op = stack.get(stack.size() - 3);
                    sig = op.getSignature();
                    if ("J".equals(sig) || "D".equals(sig)) {
                        op = stack.get(stack.size() - 2);
                        stack.add(stack.size() - 3, op);
                        op = stack.get(stack.size() - 1);
                        stack.add(stack.size() - 3, op);
                    } else {
                        if (stack.size() >= 4) {
                            op = stack.get(stack.size() - 2);
                            stack.add(stack.size() - 4, op);
                            op = stack.get(stack.size() - 1);
                            stack.add(stack.size() - 4, op);
                        }
                    }
                }
            }
        }
        break;

    case Opcodes.SWAP:
        if (stack.size() >= 2) {
            Operand op = stack.remove(stack.size() - 1);
            stack.add(stack.size() - 1, op);
        }
        break;

    case Opcodes.IADD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LADD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FADD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DADD: {
        pop2();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.ISUB: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LSUB: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FSUB: {
        pop2();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DSUB: {
        pop2();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.IMUL: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LMUL: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FMUL: {
        pop2();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DMUL: {
        pop2();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.IDIV: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LDIV: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FDIV: {
        pop2();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DDIV: {
        pop2();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.IREM: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LREM: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FREM: {
        pop2();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DREM: {
        pop2();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.INEG: {
        pop();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LNEG: {
        pop();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.FNEG: {
        pop();
        Operand op = new Operand();
        op.setSignature("F");
        push(op);
    }
        break;

    case Opcodes.DNEG: {
        pop();
        Operand op = new Operand();
        op.setSignature("D");
        push(op);
    }
        break;

    case Opcodes.ISHL: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LSHL: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.ISHR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LSHR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.IUSHR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LUSHR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.IAND: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LAND: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.IOR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LOR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.IXOR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.LXOR: {
        pop2();
        Operand op = new Operand();
        op.setSignature("J");
        push(op);
    }
        break;

    case Opcodes.I2L: {
        Operand lop = new Operand();
        lop.setSignature("J");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                lop.setConstant(Long.valueOf(((Integer) o).longValue()));
            }
        }
        push(lop);
    }
        break;

    case Opcodes.I2F: {
        Operand fop = new Operand();
        fop.setSignature("F");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                fop.setConstant(Float.valueOf(((Integer) o).floatValue()));
            }
        }
        push(fop);
    }
        break;

    case Opcodes.I2D: {
        Operand dop = new Operand();
        dop.setSignature("D");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                dop.setConstant(Double.valueOf(((Integer) o).doubleValue()));
            }
        }
        push(dop);
    }
        break;

    case Opcodes.L2I: {
        Operand iop = new Operand();
        iop.setSignature("I");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                iop.setConstant(Integer.valueOf(((Long) o).intValue()));
            }
        }
        push(iop);
    }
        break;

    case Opcodes.L2F: {
        Operand fop = new Operand();
        fop.setSignature("F");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                fop.setConstant(Float.valueOf(((Long) o).floatValue()));
            }
        }
        push(fop);
    }
        break;

    case Opcodes.L2D: {
        Operand dop = new Operand();
        dop.setSignature("D");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                dop.setConstant(Double.valueOf(((Long) o).doubleValue()));
            }
        }
        push(dop);
    }
        break;

    case Opcodes.F2I: {
        Operand iop = new Operand();
        iop.setSignature("I");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                iop.setConstant(Integer.valueOf(((Float) o).intValue()));
            }
        }
        push(iop);
    }
        break;

    case Opcodes.F2L: {
        Operand lop = new Operand();
        lop.setSignature("J");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                lop.setConstant(Long.valueOf(((Float) o).longValue()));
            }
        }
        push(lop);
    }
        break;

    case Opcodes.F2D: {
        Operand dop = new Operand();
        dop.setSignature("D");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                dop.setConstant(Double.valueOf(((Float) o).doubleValue()));
            }
        }
        push(dop);
    }
        break;

    case Opcodes.D2I: {
        Operand iop = new Operand();
        iop.setSignature("I");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                iop.setConstant(Integer.valueOf(((Double) o).intValue()));
            }
        }
        push(iop);
    }
        break;

    case Opcodes.D2L: {
        Operand lop = new Operand();
        lop.setSignature("J");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                lop.setConstant(Long.valueOf(((Double) o).longValue()));
            }
        }
        push(lop);
    }
        break;

    case Opcodes.D2F: {
        Operand fop = new Operand();
        fop.setSignature("F");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                fop.setConstant(Float.valueOf(((Double) o).floatValue()));
            }
        }
        push(fop);
    }
        break;

    case Opcodes.I2B: {
        Operand bop = new Operand();
        bop.setSignature("B");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                bop.setConstant(Byte.valueOf(((Integer) o).byteValue()));
            }
        }
        push(bop);
    }
        break;

    case Opcodes.I2C: {
        Operand cop = new Operand();
        cop.setSignature("C");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                cop.setConstant(Character.valueOf((char) ((Integer) o).intValue()));
            }
        }
        push(cop);
    }
        break;

    case Opcodes.I2S: {
        Operand sop = new Operand();
        sop.setSignature("S");
        if (!stack.isEmpty()) {
            Operand op = stack.remove(stack.size() - 1);
            Object o = op.getConstant();
            if (o != null) {
                sop.setConstant(Short.valueOf((short) ((Integer) o).intValue()));
            }
        }
        push(sop);
    }
        break;

    case Opcodes.LCMP:
    case Opcodes.FCMPL:
    case Opcodes.FCMPG:
    case Opcodes.DCMPL:
    case Opcodes.DCMPG: {
        pop2();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.IRETURN:
    case Opcodes.LRETURN:
    case Opcodes.FRETURN:
    case Opcodes.DRETURN:
    case Opcodes.ARETURN:
        pop();
        break;

    case Opcodes.RETURN:
        //nop
        break;

    case Opcodes.ARRAYLENGTH: {
        pop();
        Operand op = new Operand();
        op.setSignature("I");
        push(op);
    }
        break;

    case Opcodes.ATHROW:
    case Opcodes.MONITORENTER:
    case Opcodes.MONITOREXIT:
        pop();
        break;
    }
}

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

License:Open Source License

/**
 * Clones a monitorenter/monitorexit node and returns it as an instruction list.
 * @param insnNode instruction to clone//www.j a v a 2 s. co m
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if node isn't of invoke type
 * @return instruction list with cloned instruction
 */
public static InsnList cloneMonitorNode(AbstractInsnNode insnNode) {
    Validate.notNull(insnNode);
    Validate.isTrue(insnNode instanceof InsnNode);
    Validate.isTrue(
            insnNode.getOpcode() == Opcodes.MONITORENTER || insnNode.getOpcode() == Opcodes.MONITOREXIT);

    InsnList ret = new InsnList();
    ret.add(insnNode.clone(new HashMap<>()));

    return ret;
}

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

License:Open Source License

/**
 * Generates a MONITORENTER instruction, which consumes an Object from the top of the stack.
 * @return instructions for a pop//  ww  w  . j  a v a 2 s .c  o m
 */
public static InsnList monitorEnter() {
    InsnList ret = new InsnList();
    ret.add(new InsnNode(Opcodes.MONITORENTER));

    return ret;
}

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

License:Open Source License

@Test
public void mustFindOpcodeWithinMethod() {
    MethodNode methodNode = findMethodsWithName(classNode.methods, "syncTest").get(0);

    List<AbstractInsnNode> insns = searchForOpcodes(methodNode.instructions, Opcodes.MONITORENTER,
            Opcodes.MONITOREXIT);//  w  ww  .j  av a2s.c  o m
    assertEquals(3, insns.size());
    assertEquals(Opcodes.MONITORENTER, insns.get(0).getOpcode());
    assertEquals(Opcodes.MONITOREXIT, insns.get(1).getOpcode());
    assertEquals(Opcodes.MONITOREXIT, insns.get(2).getOpcode()); // hidden trycatch block generated by compiler
}

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

License:Open Source License

public MethodAttributes analyze(ClassNode classNode, MethodNode methodNode, InstrumentationSettings settings) {
    ///////////////////////////////////////////////////////////////////////////////////////////
    // VALIDATE INPUTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    Validate.notNull(classNode);// w w w .  ja  v a 2  s . c om
    Validate.notNull(methodNode);
    Validate.notNull(settings);

    // Sanity check to make sure class
    Validate.isTrue(classNode.methods.contains(methodNode), "Method does not belong to class");

    // Check if method is constructor -- we cannot instrument constructor
    Validate.isTrue(!"<init>".equals(methodNode.name), "Instrumentation of constructors not allowed");

    // Check for JSR blocks -- Emitted for finally blocks in older versions of the JDK. Should never happen since we already inlined
    // these blocks before coming to this point. This is a sanity check.
    Validate.isTrue(searchForOpcodes(methodNode.instructions, Opcodes.JSR).isEmpty(),
            "JSR instructions not allowed");

    ///////////////////////////////////////////////////////////////////////////////////////////
    // FIND SUSPEND / CONTINUATION INVOCATIONS + ALSO FIND SYNCHRONIZATION INSTRUCTIONS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Find invocations of continuation invocation/suspend
    List<AbstractInsnNode> suspendInvocationInsnNodes = findInvocationsOf(methodNode.instructions,
            CONTINUATION_SUSPEND_METHOD);
    List<AbstractInsnNode> contInvocationInsnNodes = findInvocationsWithParameter(methodNode.instructions,
            CONTINUATION_CLASS_TYPE);

    // If there are no continuation points, we don't need to instrument this method. It'll be like any other normal method
    // invocation because it won't have the potential to pause or call in to another method that may potentially pause.
    if (suspendInvocationInsnNodes.isEmpty() && contInvocationInsnNodes.isEmpty()) {
        return null;
    }

    // Check for continuation points that use invokedynamic instruction, which are currently only used by lambdas. See comments in
    // validateNoInvokeDynamic to see why we need to do this.
    validateNoInvokeDynamic(suspendInvocationInsnNodes);
    validateNoInvokeDynamic(contInvocationInsnNodes);

    // Find MONITORENTER/MONITOREXIT instructions
    List<AbstractInsnNode> monitorInsnNodes = searchForOpcodes(methodNode.instructions, Opcodes.MONITORENTER,
            Opcodes.MONITOREXIT);

    ///////////////////////////////////////////////////////////////////////////////////////////
    // COMPUTE FRAMES FOR INSTRUCTIONS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Compute frames for each instruction in the method
    Frame<BasicValue>[] frames;
    try {
        frames = new Analyzer<>(new SimpleVerifier(classInfoRepo)).analyze(classNode.name, methodNode);
    } catch (AnalyzerException ae) {
        throw new IllegalArgumentException("Analyzer failed to analyze method", ae);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // CREATE SUSPEND/CONTINUATION/SYNCHRONIZATION OBJECTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    List<ContinuationPoint> continuationPoints = new LinkedList<>();
    // Create SuspendContinuationPoint objects for suspend points

    for (AbstractInsnNode suspendInvocationInsnNode : suspendInvocationInsnNodes) {
        int instructionIndex = methodNode.instructions.indexOf(suspendInvocationInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        LineNumberNode lineNumberNode = findLineNumberForInstruction(methodNode.instructions,
                suspendInvocationInsnNode);
        Integer lineNumber = lineNumberNode != null ? lineNumberNode.line : null;

        SuspendContinuationPoint suspendPoint = new SuspendContinuationPoint(lineNumber,
                (MethodInsnNode) suspendInvocationInsnNode, frame);
        continuationPoints.add(suspendPoint);
    }

    // Create NormalInvokeContinuationPoint / TryCatchInvokeContinuationPoint objects for suspend points
    for (AbstractInsnNode contInvocationInsnNode : contInvocationInsnNodes) {
        int instructionIndex = methodNode.instructions.indexOf(contInvocationInsnNode);
        boolean withinTryCatch = findTryCatchBlockNodesEncompassingInstruction(methodNode.instructions,
                methodNode.tryCatchBlocks, contInvocationInsnNode).size() > 0;
        Frame<BasicValue> frame = frames[instructionIndex];

        LineNumberNode lineNumberNode = findLineNumberForInstruction(methodNode.instructions,
                contInvocationInsnNode);
        Integer lineNumber = lineNumberNode != null ? lineNumberNode.line : null;

        ContinuationPoint continuationPoint;
        if (withinTryCatch) {
            continuationPoint = new TryCatchInvokeContinuationPoint(lineNumber,
                    (MethodInsnNode) contInvocationInsnNode, frame);
        } else {
            continuationPoint = new NormalInvokeContinuationPoint(lineNumber,
                    (MethodInsnNode) contInvocationInsnNode, frame);
        }
        continuationPoints.add(continuationPoint);
    }

    // Create SynchronizationPoint objects for MONITORENTER/MONITOREXIT opcodes
    List<SynchronizationPoint> synchPoints = new LinkedList<>();
    for (AbstractInsnNode monitorInsnNode : monitorInsnNodes) {
        int instructionIndex = methodNode.instructions.indexOf(monitorInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        SynchronizationPoint synchPoint = new SynchronizationPoint((InsnNode) monitorInsnNode, frame);
        synchPoints.add(synchPoint);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE TYPES RETURNED FROM SUSPEND / CONTINUATION POINTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // For each non-suspend invocation node found, see what the return type is and figure out if it's in a try/catch block.
    //
    // The return type scanning is needed because the instrumenter needs to temporarily cache the results of the invocation. The
    // variable slots for these caches are assigned lower on in the code.
    //
    // The try/catch information is needed because the instrumenter needs to temporarily cache a throwable if the invocation throws one.
    // The variable slot for the throwable is assigned lower on in the code.
    TypeTracker invocationReturnTypes = new TypeTracker();
    boolean invocationFoundWrappedInTryCatch = false;
    for (AbstractInsnNode invokeInsnNode : contInvocationInsnNodes) {
        if (findTryCatchBlockNodesEncompassingInstruction(methodNode.instructions, methodNode.tryCatchBlocks,
                invokeInsnNode).size() > 0) {
            invocationFoundWrappedInTryCatch = true;
        }

        Type returnType = getReturnTypeOfInvocation(invokeInsnNode);
        if (returnType.getSort() != Type.VOID) {
            invocationReturnTypes.trackType(returnType);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE TYPES ON THE LOCAL VARIABLES TABE AT SUSPEND / CONTINUATION POINTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // For each invocation node found, see whats on the locals.
    //
    // We need on scan the types on the locals because the instrumenter needs to know which extra variable slots to allot to the
    // storage containers for those types. The variable slots for these storage containers are assigned lower on in the code.
    TypeTracker localsTypes = new TypeTracker();
    for (AbstractInsnNode invokeInsnNode : union(contInvocationInsnNodes, suspendInvocationInsnNodes)) {
        int instructionIndex = methodNode.instructions.indexOf(invokeInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        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. We don't store anything in this case so skip this slot if we encounter it.
            //
            // 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 (type == null || "Lnull;".equals(type.getDescriptor())) {
                continue;
            }

            localsTypes.trackType(type);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE TYPES ON THE OPERAND STACK AT SUSPEND / CONTINUATION POINTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // For each invocation node found, see whats on the operand stack.
    //
    // We need on scan the types on the operand stack because the instrumenter needs to know which extra variable slots to allot to the
    // storage containers for those types. The variable slots for these storage containers are assigned lower on in the code.
    TypeTracker operandStackTypes = new TypeTracker();
    for (AbstractInsnNode invokeInsnNode : union(contInvocationInsnNodes, suspendInvocationInsnNodes)) {
        int instructionIndex = methodNode.instructions.indexOf(invokeInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        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 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;
            }

            operandStackTypes.trackType(type);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE WHICH INDEX IN LOCAL VARIABLE TABLE CONTAINS CONTINUATION OBJECT
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Find index of continuation object
    int contArgIdx = getLocalVariableIndexOfContinuationParameter(methodNode);

    ///////////////////////////////////////////////////////////////////////////////////////////
    // CALCULATE EXTRA VARIABLES REQUIRED BY INSTRUMENTATION
    ///////////////////////////////////////////////////////////////////////////////////////////

    VariableTable varTable = new VariableTable(classNode, methodNode);

    // Create variable for the continuation object passed in as arg + variable for storing/loading method state
    Variable continuationArgVar = varTable.getArgument(contArgIdx);
    Variable methodStateVar = varTable.acquireExtra(MethodState.class);
    CoreVariables coreVars = new CoreVariables(continuationArgVar, methodStateVar);

    // Create variables for storing/loading locals -- only create ones we need
    StorageVariables localsStorageVars = allocateStorageVariableSlots(varTable, localsTypes);

    // Create variables for storing/loading operand stack -- only create ones we need
    StorageVariables stackStorageVars = allocateStorageVariableSlots(varTable, operandStackTypes);

    // Create variables to locals and operand stack storage containers -- these must exist
    StorageContainerVariables storageContainerVars = allocateStorageContainerVariableSlots(varTable);

    // Create variables to cache return values and thrown exceptions of invocations -- only create ones we need
    CacheVariables cacheVars = allocateCacheVariableSlots(varTable, invocationReturnTypes,
            invocationFoundWrappedInTryCatch);

    // Create variables to for holding on to monitors -- only create if we need them
    LockVariables lockVars = allocateLockVariableSlots(varTable, !synchPoints.isEmpty());

    ///////////////////////////////////////////////////////////////////////////////////////////
    // RETURN RESULTS OF ANALYSIS
    ///////////////////////////////////////////////////////////////////////////////////////////

    MethodSignature signature = new MethodSignature(classNode.name, methodNode.name,
            Type.getMethodType(methodNode.desc));

    return new MethodAttributes(signature, settings, continuationPoints, synchPoints, coreVars, cacheVars,
            storageContainerVars, localsStorageVars, stackStorageVars, lockVars);
}

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

License:Open Source License

public void instrument(MethodNode methodNode, MethodAttributes attrs) {
    Validate.notNull(methodNode);//  w  ww  .j a v  a  2  s .c o m
    Validate.notNull(attrs);

    // These sanity checks need to exist. The methodNode.instructions.insertBefore/remove methods don't actually check to make sure the
    // instructions they're operating on belong to the method. This is here to make sure that the properties and methodNode match.
    attrs.getContinuationPoints().stream().map(x -> x.getInvokeInstruction())
            .forEach(x -> methodNode.instructions.contains(x));
    attrs.getSynchronizationPoints().stream().map(x -> x.getMonitorInstruction())
            .forEach(x -> methodNode.instructions.contains(x));

    // Add trycatch nodes
    attrs.getContinuationPoints().stream().filter(x -> x instanceof TryCatchInvokeContinuationPoint)
            .map(x -> (TryCatchInvokeContinuationPoint) x).map(x -> x.getTryCatchBlock())
            .forEach(x -> methodNode.tryCatchBlocks.add(0, x));

    // Add loading code (this includes continuation restore points)
    InsnList entryPoint = entryPointLoader(attrs);
    methodNode.instructions.insert(entryPoint);

    // Add continuation save points
    List<ContinuationPoint> continuationPoints = attrs.getContinuationPoints();
    for (int i = 0; i < continuationPoints.size(); i++) {
        ContinuationPoint cp = continuationPoints.get(i);

        AbstractInsnNode nodeToReplace = cp.getInvokeInstruction();
        InsnList insnsToReplaceWith = saveState(attrs, i);

        methodNode.instructions.insertBefore(nodeToReplace, insnsToReplaceWith);
        methodNode.instructions.remove(nodeToReplace);
    }

    // Add synchronization save points
    List<SynchronizationPoint> synchPoints = attrs.getSynchronizationPoints();
    MarkerType markerType = attrs.getSettings().getMarkerType();
    LockVariables lockVars = attrs.getLockVariables();
    for (int i = 0; i < synchPoints.size(); i++) {
        SynchronizationPoint sp = synchPoints.get(i);

        InsnNode nodeToReplace = sp.getMonitorInstruction();
        InsnList insnsToReplaceWith;
        switch (nodeToReplace.getOpcode()) {
        case Opcodes.MONITORENTER:
            insnsToReplaceWith = enterMonitorAndStore(markerType, lockVars);
            break;
        case Opcodes.MONITOREXIT:
            insnsToReplaceWith = exitMonitorAndDelete(markerType, lockVars);
            break;
        default:
            throw new IllegalStateException(); //should never happen
        }

        methodNode.instructions.insertBefore(nodeToReplace, insnsToReplaceWith);
        methodNode.instructions.remove(nodeToReplace);
    }
}

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

License:Open Source License

MonitorInstrumentationInstructions generate() {
    // Find monitorenter/monitorexit and create replacement instructions that keep track of which objects were entered/exited.
    ////from ww  w  .  j  a v a 2 s .c  o  m
    //
    // Check for synchronized code blocks. Synchronized methods and Java 5 locks are okay to ignore, but synchronized blocks need to
    // be instrumented. For every MONITORENTER instruction that's performed on an object, there needs to be an equivalent MONITOREXIT
    // before the method exits. Otherwise, the method throws an IllegalMonitorState exception when it exits. I've confirmed by making a
    // simple java class in JASMIN assembler that did 10 MONITORENTERs in a loop and returned. That code threw
    // IllegalMonitorStateException when it tried to return. This link seems to explain it pretty well:
    // http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/2008-April/000118.html.
    //
    // So that means that if we're going to instrument the code to suspend and return in places, we need to make sure to exit all
    // monitors when we return and to re-enter those monitors when we come back in. We can't handle this via static analysis like we do
    // with inspecting the operand stack and local variables. It looks like static analysis is what Javaflow tries to do, which will
    // work in 99% of cases but won't in some edge cases like if the code was written in some JVM langauge other than Java.
    //
    // The following code creates replacements for every MONITORENTER and MONITOREXIT instruction such that those monitors get tracked
    // in a LockState object.
    List<AbstractInsnNode> monitorInsnNodes = searchForOpcodes(methodNode.instructions, Opcodes.MONITORENTER,
            Opcodes.MONITOREXIT);
    Map<AbstractInsnNode, InsnList> monitorInsnNodeReplacements = new HashMap<>();

    // IMPORTANT NOTE: The following code only generates code if monitorInsnNodes is NOT empty. That means that there has to be at least
    // one MONITORENTER or one MONITOREXIT for this method to generate instructions. Otherwise, all instruction listings will be stubbed
    // out with empty instruction lists.

    for (AbstractInsnNode monitorInsnNode : monitorInsnNodes) {
        InsnNode insnNode = (InsnNode) monitorInsnNode;
        InsnList replacementLogic;

        switch (insnNode.getOpcode()) {
        case Opcodes.MONITORENTER:
            replacementLogic = merge(saveVar(tempObjVar), // enter monitor
                    loadVar(tempObjVar), cloneMonitorNode(insnNode),
                    call(LOCKSTATE_ENTER_METHOD, loadVar(lockStateVar), loadVar(tempObjVar)) // track after entered
            );
            break;
        case Opcodes.MONITOREXIT:
            replacementLogic = merge(saveVar(tempObjVar), // exit monitor
                    loadVar(tempObjVar), cloneMonitorNode(insnNode),
                    call(LOCKSTATE_EXIT_METHOD, loadVar(lockStateVar), loadVar(tempObjVar)) // discard after exit
            );
            break;
        default:
            throw new IllegalStateException(); // should never happen
        }

        monitorInsnNodeReplacements.put(monitorInsnNode, replacementLogic);
    }

    // Create code to create a new lockstate object
    InsnList createAndStoreLockStateInsnList;
    if (monitorInsnNodeReplacements.isEmpty()) { // if we don't have any MONITORENTER/MONITOREXIT, ignore this
        createAndStoreLockStateInsnList = empty();
    } else {
        createAndStoreLockStateInsnList = merge(construct(LOCKSTATE_INIT_METHOD), saveVar(lockStateVar));
    }

    // Create code to load lockstate object from methodstate
    InsnList loadAndStoreLockStateFromMethodStateInsnList;
    if (monitorInsnNodeReplacements.isEmpty()) {
        loadAndStoreLockStateFromMethodStateInsnList = empty();
    } else {
        loadAndStoreLockStateFromMethodStateInsnList = merge(
                call(METHODSTATE_GETLOCKSTATE_METHOD, loadVar(methodStateVar)), saveVar(lockStateVar));
    }

    // Create code to load lockstate object to the stack
    InsnList loadLockStateToStackInsnList;
    if (monitorInsnNodeReplacements.isEmpty()) {
        loadLockStateToStackInsnList = loadNull();
    } else {
        loadLockStateToStackInsnList = loadVar(lockStateVar);
    }

    // Create code to enter all monitors in lockstate object
    InsnList enterMonitorsInLockStateInsnList;
    if (monitorInsnNodeReplacements.isEmpty()) {
        enterMonitorsInLockStateInsnList = empty();
    } else {
        enterMonitorsInLockStateInsnList = forEach(counterVar, arrayLenVar,
                call(LOCKSTATE_TOARRAY_METHOD, loadVar(lockStateVar)), merge(monitorEnter() // temp monitor enter
                ));
    }

    // Create code to exit all monitors in lockstate object
    InsnList exitMonitorsInLockStateInsnList;
    if (monitorInsnNodeReplacements.isEmpty()) {
        exitMonitorsInLockStateInsnList = empty();
    } else {
        exitMonitorsInLockStateInsnList = forEach(counterVar, arrayLenVar,
                call(LOCKSTATE_TOARRAY_METHOD, loadVar(lockStateVar)), merge(monitorExit() // temp monitor exit
                ));
    }

    return new MonitorInstrumentationInstructions(monitorInsnNodeReplacements, createAndStoreLockStateInsnList,
            loadAndStoreLockStateFromMethodStateInsnList, loadLockStateToStackInsnList,
            enterMonitorsInLockStateInsnList, exitMonitorsInLockStateInsnList);
}

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

License:Open Source License

/**
 * Generates instruction to enter all monitors in the {@link LockState} object sitting in the lockstate variable.
 * @param markerType debug marker type//from  w w  w.  j av  a2 s.  co m
 * @param lockVars variables for lock/synchpoint functionality
 * @return instructions to enter all monitors in the {@link LockState} object
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if lock variables aren't set (the method doesn't contain any monitorenter/monitorexit instructions)
 */
public static InsnList enterStoredMonitors(MarkerType markerType, LockVariables lockVars) {
    Validate.notNull(markerType);
    Validate.notNull(lockVars);

    Variable lockStateVar = lockVars.getLockStateVar();
    Variable counterVar = lockVars.getCounterVar();
    Variable arrayLenVar = lockVars.getArrayLenVar();
    Validate.isTrue(lockStateVar != null);
    Validate.isTrue(counterVar != null);
    Validate.isTrue(arrayLenVar != null);

    return forEach(counterVar, arrayLenVar,
            merge(debugMarker(markerType, "Loading monitors to enter"),
                    call(LOCKSTATE_TOARRAY_METHOD, loadVar(lockStateVar))),
            merge(debugMarker(markerType, "Entering monitor"), new InsnNode(Opcodes.MONITORENTER)));
}

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

License:Open Source License

/**
 * Generates instruction to enter a monitor (top item on the stack) and store it in the {@link LockState} object sitting in the
 * lockstate variable.//  w w  w . ja  v  a  2s . c  o m
 * @param markerType debug marker type
 * @param lockVars variables for lock/synchpoint functionality
 * @return instructions to enter a monitor and store it in the {@link LockState} object
 * @throws NullPointerException if any argument is {@code null}
 * @throws IllegalArgumentException if lock variables aren't set (the method doesn't contain any monitorenter/monitorexit instructions)
 */
public static InsnList enterMonitorAndStore(MarkerType markerType, LockVariables lockVars) {
    Validate.notNull(markerType);
    Validate.notNull(lockVars);

    Variable lockStateVar = lockVars.getLockStateVar();
    Validate.isTrue(lockStateVar != null);

    Type clsType = Type.getType(LOCKSTATE_ENTER_METHOD.getDeclaringClass());
    Type methodType = Type.getType(LOCKSTATE_ENTER_METHOD);
    String clsInternalName = clsType.getInternalName();
    String methodDesc = methodType.getDescriptor();
    String methodName = LOCKSTATE_ENTER_METHOD.getName();

    // NOTE: This adds to the lock state AFTER locking.
    return merge(debugMarker(markerType, "Entering monitor and storing"),
            // [obj]
            new InsnNode(Opcodes.DUP), // [obj, obj]
            new InsnNode(Opcodes.MONITORENTER), // [obj]
            new VarInsnNode(Opcodes.ALOAD, lockStateVar.getIndex()), // [obj, lockState]
            new InsnNode(Opcodes.SWAP), // [lockState, obj]
            new MethodInsnNode(Opcodes.INVOKEVIRTUAL, // []
                    clsInternalName, methodName, methodDesc, false));
}