public void instructionExecuted(JVM vm) {
    ThreadInfo ti = vm.getLastThreadInfo();
    Instruction insn = vm.getLastInstruction();

    if (insn instanceof VirtualInvocation) {

      if (vm.getNextInstruction() != insn) { // otherwise we didn't execute
        VirtualInvocation call = (VirtualInvocation) insn;
        int ref = call.getCalleeThis(ti);
        Record rec = getRecord(ref);

        if (rec != null) {
          MethodInfo mi = call.getInvokedMethod(ti, ref);

          if (logCall) {
            log(ti, "invoke %1$s.%2$s", rec.ei, mi.getUniqueName());
          }

          if (!checkShared(rec, ti, mi, insn)) {
            return;
          }
        }
      }

    } else if (insn instanceof PUTFIELD) {
      PUTFIELD storeInsn = (PUTFIELD) insn;
      int ref = storeInsn.getLastThis();
      Record rec = getRecord(ref);

      if (rec != null) {
        FieldInfo fi = storeInsn.getFieldInfo();

        if (logPut) {
          log(ti, "put %1$s.%2$s = <%3$d>", rec.ei, fi.getName(), storeInsn.getLastValue());
        }

        if (!checkShared(rec, ti, fi, insn)) {
          return;
        }

        if (!checkConst(rec, ti, fi, insn)) {
          return;
        }
      }
    }
  }
  public void executeInstruction(JVM vm) {
    Instruction insn = vm.getLastInstruction();
    MethodInfo mi = insn.getMethodInfo();
    ThreadInfo ti = vm.getLastThreadInfo();

    if (mi != lastMi) {
      logStack(ti);
      lastMi = mi;

    } else if (insn instanceof InvokeInstruction) {
      MethodInfo callee;

      // that's the only little gist of it - if this is a VirtualInvocation,
      // we have to dig the callee out by ourselves (it's not known
      // before execution)

      if (insn instanceof VirtualInvocation) {
        VirtualInvocation callInsn = (VirtualInvocation) insn;
        int objref = callInsn.getCalleeThis(ti);
        callee = callInsn.getInvokedMethod(ti, objref);

      } else if (insn instanceof INVOKESPECIAL) {
        INVOKESPECIAL callInsn = (INVOKESPECIAL) insn;
        callee = callInsn.getInvokedMethod(ti);

      } else {
        InvokeInstruction callInsn = (InvokeInstruction) insn;
        callee = callInsn.getInvokedMethod(ti);
      }

      if (callee != null) {
        if (callee.isMJI()) {
          logStack(ti);
        }
      } else {
        out.println("ERROR: unknown callee of: " + insn);
      }
    }
  }