List of usage examples for org.objectweb.asm Opcodes AALOAD
int AALOAD
To view the source code for org.objectweb.asm Opcodes AALOAD.
Click Source Link
From source file:com.google.monitoring.runtime.instrumentation.adapters.AllocationMethodAdapter.java
License:Apache License
void calculateArrayLengthAndDispatch(final String typeName, final int dimCount) { // Since the dimensions of the array are not known at instrumentation // time, we take the created multi-dimensional array and peel off nesting // levels from the left. For each nesting layer we probe the array length // and accumulate a partial product which we can then feed the recording // function.// w w w . ja v a 2s .c om // below we note the partial product of dimensions 1 to X-1 as productToX // (so productTo1 == 1 == no dimensions yet). We denote by aref0 the // array reference at the current nesting level (the containing aref's [0] // element). If we hit a level whose arraylength is 0 there's no point // continuing so we shortcut out. final Label zeroDimension = new Label(); super.visitInsn(Opcodes.DUP); // -> stack: ... origaref aref0 super.visitLdcInsn(1); // -> stack: ... origaref aref0 productTo1 for (int i = 0; i < dimCount; ++i) { // pre: stack: ... origaref aref0 productToI super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref productToI aref super.visitInsn(Opcodes.DUP_X1); // -> stack: ... origaref aref0 productToI aref super.visitInsn(Opcodes.ARRAYLENGTH); // -> stack: ... origaref aref0 productToI dimI final Label nonZeroDimension = new Label(); super.visitInsn(Opcodes.DUP); // -> stack: ... origaref aref0 productToI dimI dimI super.visitJumpInsn(Opcodes.IFNE, nonZeroDimension); // -> stack: ... origaref aref0 productToI dimI super.visitInsn(Opcodes.POP); // -> stack: ... origaref aref0 productToI super.visitJumpInsn(Opcodes.GOTO, zeroDimension); super.visitLabel(nonZeroDimension); // -> stack: ... origaref aref0 productToI max(dimI,1) super.visitInsn(Opcodes.IMUL); // -> stack: ... origaref aref0 productTo{I+1} if (i < dimCount - 1) { super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref productTo{I+1} aref0 super.visitInsn(Opcodes.ICONST_0); // -> stack: ... origaref productTo{I+1} aref0 0 super.visitInsn(Opcodes.AALOAD); // -> stack: ... origaref productTo{I+1} aref0' super.visitInsn(Opcodes.SWAP); } // post: stack: ... origaref aref0 productTo{I+1} } super.visitLabel(zeroDimension); super.visitInsn(Opcodes.SWAP); // -> stack: ... origaref product aref0 super.visitInsn(Opcodes.POP); // -> stack: ... origaref product super.visitInsn(Opcodes.SWAP); // -> stack: ... product origaref invokeRecordAllocation(typeName); }
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 va 2 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;/*from w w w . j av a2 s. co 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.mogujie.instantrun.IncrementalChangeVisitor.java
License:Apache License
/** * To each class, add the dispatch method called by the original code that acts as a trampoline to * invoke the changed methods./* w w w . j a v a 2 s . c o m*/ * <p/> * Pseudo code: * <code> * Object access$dispatch(String name, object[] args) { * if (name.equals( * "firstMethod.(L$type;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;")) { * return firstMethod(($type)arg[0], (String)arg[1], arg[2]); * } * if (name.equals("secondMethod.(L$type;Ljava/lang/String;I;)V")) { * secondMethod(($type)arg[0], (String)arg[1], (int)arg[2]); * return; * } * ... * StringBuilder $local1 = new StringBuilder(); * $local1.append("Method not found "); * $local1.append(name); * $local1.append(" in " + visitedClassName + * "$dispatch implementation, restart the application"); * throw new $package/InstantReloadException($local1.toString()); * } * </code> */ private void addDispatchMethod() { int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_VARARGS; Method m = new Method("access$dispatch", "(I[Ljava/lang/Object;)Ljava/lang/Object;"); MethodVisitor visitor = super.visitMethod(access, m.getName(), m.getDescriptor(), null, null); final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor); if (TRACING_ENABLED) { mv.push("Redirecting "); mv.loadArg(0); trace(mv, 2); } List<MethodNode> allMethods = new ArrayList(); // if we are disabled, do not generate any dispatch, the method will throw an exception // if invoked which should never happen. if (!instantRunDisabled) { //noinspection unchecked allMethods.addAll(classNode.methods); allMethods.addAll(addedMethods); } final Map<String, MethodNode> methods = new HashMap(); for (MethodNode methodNode : allMethods) { if (methodNode.name.equals("<clinit>") || methodNode.name.equals("<init>")) { continue; } if (!isAccessCompatibleWithInstantRun(methodNode.access)) { continue; } methods.put(methodNode.name + "." + methodNode.desc, methodNode); } new IntSwitch() { @Override void visitString() { mv.visitVarInsn(Opcodes.ALOAD, 1); } @Override void visitInt() { mv.visitVarInsn(Opcodes.ILOAD, 1); } @Override void visitCase(String methodName) { MethodNode methodNode = methods.get(methodName); String name = methodNode.name; boolean isStatic = (methodNode.access & Opcodes.ACC_STATIC) != 0; String newDesc = computeOverrideMethodDesc(methodNode.desc, isStatic); if (TRACING_ENABLED) { trace(mv, "M: " + name + " P:" + newDesc); } Type[] args = Type.getArgumentTypes(newDesc); int argc = 0; for (Type t : args) { mv.visitVarInsn(Opcodes.ALOAD, 2); mv.push(argc); mv.visitInsn(Opcodes.AALOAD); ByteCodeUtils.unbox(mv, t); argc++; } mv.visitMethodInsn(Opcodes.INVOKESTATIC, visitedClassName + "$override", isStatic ? computeOverrideMethodName(name, methodNode.desc) : name, newDesc, false); Type ret = Type.getReturnType(methodNode.desc); if (ret.getSort() == Type.VOID) { mv.visitInsn(Opcodes.ACONST_NULL); } else { mv.box(ret); } mv.visitInsn(Opcodes.ARETURN); } @Override void visitDefault() { writeMissingMessageWithHash(mv, visitedClassName); } }.visit(mv, methods.keySet(), visitedClassName); mv.visitMaxs(0, 0); mv.visitEnd(); }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * For each element in an object array, performs an action. * @param counterVar parameter used to keep track of count in loop * @param arrayLenVar parameter used to keep track of array length * @param array object array instruction list -- must leave an array on top of the stack * @param action action to perform on each element -- element will be at top of stack and must be consumed by these instructions * @return instructions instruction list to perform some action if two ints are equal * @throws NullPointerException if any argument is {@code null} */// www. j av a2 s. co m public static InsnList forEach(Variable counterVar, Variable arrayLenVar, InsnList array, InsnList action) { Validate.notNull(counterVar); Validate.notNull(arrayLenVar); Validate.notNull(array); Validate.notNull(action); Validate.isTrue(counterVar.getType().equals(Type.INT_TYPE)); Validate.isTrue(arrayLenVar.getType().equals(Type.INT_TYPE)); InsnList ret = new InsnList(); LabelNode doneLabelNode = new LabelNode(); LabelNode loopLabelNode = new LabelNode(); // put zero in to counterVar ret.add(new LdcInsnNode(0)); // int ret.add(new VarInsnNode(Opcodes.ISTORE, counterVar.getIndex())); // // load array we'll be traversing over ret.add(array); // object[] // put array length in to arrayLenVar ret.add(new InsnNode(Opcodes.DUP)); // object[], object[] ret.add(new InsnNode(Opcodes.ARRAYLENGTH)); // object[], int ret.add(new VarInsnNode(Opcodes.ISTORE, arrayLenVar.getIndex())); // object[] // loopLabelNode: test if counterVar == arrayLenVar, if it does then jump to doneLabelNode ret.add(loopLabelNode); ret.add(new VarInsnNode(Opcodes.ILOAD, counterVar.getIndex())); // object[], int ret.add(new VarInsnNode(Opcodes.ILOAD, arrayLenVar.getIndex())); // object[], int, int ret.add(new JumpInsnNode(Opcodes.IF_ICMPEQ, doneLabelNode)); // object[] // load object from object[] ret.add(new InsnNode(Opcodes.DUP)); // object[], object[] ret.add(new VarInsnNode(Opcodes.ILOAD, counterVar.getIndex())); // object[], object[], int ret.add(new InsnNode(Opcodes.AALOAD)); // object[], object // call action ret.add(action); // object[] // increment counter var and goto loopLabelNode ret.add(new IincInsnNode(counterVar.getIndex(), 1)); // object[] ret.add(new JumpInsnNode(Opcodes.GOTO, loopLabelNode)); // object[] // doneLabelNode: pop object[] off of stack ret.add(doneLabelNode); ret.add(new InsnNode(Opcodes.POP)); // return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
private static InsnList loadOperandStack(Variable arrayStackVar, Variable tempObjectVar, Frame<BasicValue> frame, int start, int end) { Validate.notNull(arrayStackVar);/* ww w . j a v a2s .com*/ Validate.notNull(tempObjectVar); Validate.notNull(frame); Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class))); Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class))); validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex()); Validate.isTrue(start >= 0); Validate.isTrue(end >= start); // end is exclusive Validate.isTrue(end <= frame.getStackSize()); InsnList ret = new InsnList(); // Restore the stack for (int i = start; i < end; i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new InsnNode(Opcodes.AALOAD)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)); break; case Type.BYTE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false)); break; case Type.SHORT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false)); break; case Type.CHAR: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)); break; case Type.INT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)); break; case Type.FLOAT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false)); break; case Type.LONG: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false)); break; case Type.DOUBLE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false)); break; case Type.ARRAY: case Type.OBJECT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to save the operand stack to an object array. * @param arrayStackVar variable that the object array containing operand stack is stored * @param tempObjectVar variable to use for temporary objects * @param frame execution frame at the instruction where the operand stack is to be saved * @return instructions to save the operand stack in to an array and save it to the local variables table * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong * type/* www . j a v a 2 s . c o m*/ */ public static InsnList saveOperandStack(Variable arrayStackVar, Variable tempObjectVar, Frame<BasicValue> frame) { Validate.notNull(arrayStackVar); Validate.notNull(tempObjectVar); Validate.notNull(frame); Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class))); Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class))); validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex()); InsnList ret = new InsnList(); // Create stack storage array and save it in local vars table ret.add(new LdcInsnNode(frame.getStackSize())); ret.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object")); ret.add(new VarInsnNode(Opcodes.ASTORE, arrayStackVar.getIndex())); // Save the stack for (int i = frame.getStackSize() - 1; i >= 0; i--) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so we can avoid saving it (but we still need to do a POP to get rid of it). When we load it back up, we can // simply push a null in to that slot, thereby keeping the same 'Lnull;' type. if ("Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.POP)); continue; } // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;")); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.BYTE: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.SHORT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.CHAR: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.INT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.FLOAT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.LONG: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.DOUBLE: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.ARRAY: case Type.OBJECT: ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } // Store item in to stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new VarInsnNode(Opcodes.ALOAD, tempObjectVar.getIndex())); ret.add(new InsnNode(Opcodes.AASTORE)); } // Restore the stack for (int i = 0; i < frame.getStackSize(); i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new InsnNode(Opcodes.AALOAD)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)); break; case Type.BYTE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false)); break; case Type.SHORT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false)); break; case Type.CHAR: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)); break; case Type.INT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)); break; case Type.FLOAT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false)); break; case Type.LONG: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false)); break; case Type.DOUBLE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false)); break; case Type.ARRAY: case Type.OBJECT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to load the local variables table from an object array. * * @param arrayLocalsVar variable that the object array containing local variables table is stored * @param tempObjectVar variable to use for temporary objects * @param frame execution frame at the instruction for which the local variables table is to be restored * @return instructions to load the local variables table from an array * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong * type//from ww w . j a v a 2s . c om */ 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.LocalsStateGenerators.java
License:Open Source License
/** * Generates instructions to load the local variables table. * @param markerType debug marker type/* ww w. ja v a 2s . c o 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.OperandStackStateGenerators.java
License:Open Source License
/** * Generates instructions to load a certain number of items to the top of the operand stack. * @param markerType debug marker type/* w w w . j a v a 2s .co m*/ * @param storageVars variables to load operand stack from * @param frame execution frame at the instruction where the operand stack is to be loaded * @param storageStackStartIdx stack position where {@code storageVars} starts from * @param storageStackLoadIdx stack position where loading should start from * @param count number of stack items to load * @return instructions to load the operand stack from the specified storage variables * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if any numeric argument is negative, or if you're trying to load stack items that aren't available * in the storage vars (stack items before {@code storageStackStartIdx}), or if you're trying to load too many items on the stack (such * that it goes past {@code frame.getStackSize()}) */ public static InsnList loadOperandStack(MarkerType markerType, StorageVariables storageVars, Frame<BasicValue> frame, int storageStackStartIdx, // stack idx which the storage was started at int storageStackLoadIdx, // stack idx we should start loading at int count) { Validate.notNull(markerType); Validate.notNull(storageVars); Validate.notNull(frame); // no negs allowed Validate.isTrue(storageStackStartIdx >= 0); Validate.isTrue(storageStackLoadIdx >= 0); Validate.isTrue(count >= 0); Validate.isTrue(storageStackLoadIdx >= storageStackStartIdx); Validate.isTrue(storageStackStartIdx + count <= frame.getStackSize()); Validate.isTrue(storageStackStartIdx + count >= 0); // likely will never overflow unless crazy high count passedin, but just in case 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(); // Increment offsets for parts of the storage arrays we don't care about. We need to do this so when we load we're loading from the // correct offsets in the storage arrays for (int i = storageStackStartIdx; i < storageStackLoadIdx; i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { continue; // skip } switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: intsCounter++; break; case Type.FLOAT: floatsCounter++; break; case Type.LONG: longsCounter++; break; case Type.DOUBLE: doublesCounter++; break; case Type.ARRAY: case Type.OBJECT: objectsCounter++; break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } // Restore the stack ret.add(debugMarker(markerType, "Loading stack items")); for (int i = storageStackLoadIdx; i < storageStackLoadIdx + count; i++) { BasicValue basicValue = frame.getStack(i); Type type = basicValue.getType(); // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise' // the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this // point in the code so there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(debugMarker(markerType, "Loading null value at " + i)); ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(debugMarker(markerType, "Loading from container at" + i)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: ret.add(debugMarker(markerType, "Loading int at " + 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] intsCounter++; break; case Type.FLOAT: ret.add(debugMarker(markerType, "Loading float at " + 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] floatsCounter++; break; case Type.LONG: ret.add(debugMarker(markerType, "Loading long at " + 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] longsCounter++; break; case Type.DOUBLE: ret.add(debugMarker(markerType, "Loading double at " + 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] doublesCounter++; break; case Type.ARRAY: case Type.OBJECT: ret.add(debugMarker(markerType, "Loading object at " + 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] ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); objectsCounter++; break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }