Beispiel #1
0
 public void replay(IoAdapter adapter) {
   adapter.seek(_address);
 }
  /**
   * * Visitor of the method-calling byte-code instructions called by the method
   *
   * <p>This allows us to instrument the method-calling byte-code instructions of a profiled method.
   * These methods can be divided into the ones that: - denote thread start - denote thread yield -
   * denote thread wait - trigger synchronisation points - should register I/O points
   */
  @Override
  public void visitMethodInsn(int opcode, String owner, String name, String desc) {

    if (DEBUG) {
      System.out.println(owner + " --> " + name + ": " + desc + " (" + opcode + ")");
    }
    // called at the beginning of a method
    if (removingMethodBody()) {
      return;
    }

    instrumentationStatsRecord.addInstruction();

    // Thread.yield - cannot be instrumented in java.lang.Thread, because it's a native method
    if (opcode == INVOKESTATIC
        && owner.equals("java/lang/Thread")
        && name.equals("yield")
        && desc.equals("()V")) {
      instrumentationStatsRecord.addSyncPrimitive();
      mv.visitMethodInsn(INVOKESTATIC, "virtualtime/EventNotifier", "_yield", "()V");
      return;
    }

    // Virtualizing waiting calls
    if (iparams.shouldTransformWaits()) {

      // In the limited JVMTI case we do not rely on JVMTI to trap Object.wait(), so we trap both
      // indefinite and timed-waiting events
      if (iparams.onlyLimitedJvmtiUsage()) {
        if (opcode == INVOKEVIRTUAL && owner.equals("java/lang/Object") && name.equals("wait")) {
          instrumentationStatsRecord.addSyncPrimitive();

          if (iparams.shouldRemoveMonitors()) {
            mv.visitLdcInsn(ICONST_0);
          } else {
            mv.visitLdcInsn(ICONST_1);
          }

          if (desc.equals("()V")) {
            mv.visitMethodInsn(
                INVOKESTATIC,
                "virtualtime/EventNotifier",
                "waitInVirtualTimeWithoutJvmti",
                "(Ljava/lang/Object;Z)V");

          } else if (desc.equals("(J)V")) {
            mv.visitMethodInsn(
                INVOKESTATIC,
                "virtualtime/EventNotifier",
                "waitInVirtualTimeWithoutJvmti",
                "(Ljava/lang/Object;JZ)V");

          } else {
            mv.visitMethodInsn(
                INVOKESTATIC,
                "virtualtime/EventNotifier",
                "waitInVirtualTimeWithoutJvmti",
                "(Ljava/lang/Object;J*Z)V");
          }
          return;
        }

      } else {
        // JVMTI traps Object.wait(), so we only trap timed-waiting events
        if (opcode == INVOKEVIRTUAL
            && owner.equals("java/lang/Object")
            && name.equals("wait")
            && desc.equals("(J)V")) {
          instrumentationStatsRecord.addSyncPrimitive();
          mv.visitMethodInsn(
              INVOKESTATIC,
              "virtualtime/EventNotifier",
              "waitInVirtualTime",
              "(Ljava/lang/Object;J)V");
          return;
        }

        if (opcode == INVOKEVIRTUAL
            && owner.equals("java/lang/Object")
            && name.equals("wait")
            && desc.equals("(JI)V")) {
          instrumentationStatsRecord.addSyncPrimitive();
          // Object.wait(timeout, nanos)
          mv.visitMethodInsn(
              INVOKESTATIC,
              "virtualtime/EventNotifier",
              "waitInVirtualTime",
              "(Ljava/lang/Object;JI)V");
          return;
        }
      }

      // Hack to include subclasses of Thread that override sleep - naive onLoad check does not work
      if (name.equals("sleep")
          && (desc.equals("(J)V") || desc.equals("(JI)V"))
          && (!owner.equals(className)
              || iparams
                  .isSubClassOfJavaLangThread())) { // && owner.equals("java/lang/Thread")) {	// ||
                                                    // iparams.isExtendindJavaLangThread(owner)
        instrumentationStatsRecord.addSyncPrimitive();
        //				System.out.println("changing sleep for " + owner + " "  + name + " " + desc + " " +
        // className + " " + methodName);
        mv.visitMethodInsn(INVOKESTATIC, "virtualtime/EventNotifier", "sleepInVirtualTime", desc);
        return;
      } else if (name.equals("sleep")) {
        //				System.out.println("*NOT* changing sleep for " + owner + " "  + name + " " + desc + "
        // " + className + " " + methodName);
      }
    }

    if (iparams.shouldTransformWaits()) {
      if (!iparams.shouldRemoveMonitors()) {

        // Object.notifyAll():
        if (opcode == INVOKEVIRTUAL
            && owner.equals("java/lang/Object")
            && name.equals("notifyAll")
            && desc.equals("()V")) {
          instrumentationStatsRecord.addSyncPrimitive();
          mv.visitMethodInsn(
              INVOKESTATIC,
              "virtualtime/EventNotifier",
              "beforeNotifyAll",
              "(Ljava/lang/Object;)V");
          return;
        }

        // Object.notify():
        if (opcode == INVOKEVIRTUAL
            && owner.equals("java/lang/Object")
            && name.equals("notify")
            && desc.equals("()V")) {
          instrumentationStatsRecord.addSyncPrimitive();
          mv.visitMethodInsn(
              INVOKESTATIC, "virtualtime/EventNotifier", "beforeNotify", "(Ljava/lang/Object;)V");
          return;
        }
      } else {
        // WITHOUT MONITORS
        // Object.notifyAll():
        if (opcode == INVOKEVIRTUAL
            && owner.equals("java/lang/Object")
            && name.equals("notifyAll")
            && desc.equals("()V")) {
          instrumentationStatsRecord.addSyncPrimitive();
          mv.visitMethodInsn(
              INVOKESTATIC,
              "virtualtime/EventNotifier",
              "beforeNotifyAllWithoutMonitors",
              "(Ljava/lang/Object;)V");
          return;
        }

        // Object.notify():
        if (opcode == INVOKEVIRTUAL
            && owner.equals("java/lang/Object")
            && name.equals("notify")
            && desc.equals("()V")) {
          instrumentationStatsRecord.addSyncPrimitive();
          mv.visitMethodInsn(
              INVOKESTATIC,
              "virtualtime/EventNotifier",
              "beforeNotifyWithoutMonitors",
              "(Ljava/lang/Object;)V");
          return;
        }
      }
    }

    // Any I/O method: store invocation id before every I/O call of a profiled method
    if (owner.startsWith("java/io/")
        || (owner.startsWith("java/net/") && (name.equals("write") || name.equals("read")))) {
      instrumentationStatsRecord.addIoPoint();
      mv.visitMethodInsn(INVOKESTATIC, "java/lang/Thread", "currentThread", "()Ljava/lang/Thread;");
      mv.visitIntInsn(SIPUSH, IoAdapter.getNextInvocationPointId());
      mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Thread", "setVtfIoInvocationPoint", "(I)V");
    }

    // Adapting recursive call to self
    if (iparams.isRecursiveRetransformation() && iparams.usingExternalInstrumentation()) {
      if (owner.equals(className)
          && methodName.equals(iparams.getRetransformingMethodName())
          && desc.equals(iparams.getRetransformingMethodDesc())) {
        if (DEBUG) {
          System.out.println(
              "Found recursive call " + owner + " --> " + name + ": " + desc + " (" + opcode + ")");
        }

        name = "_vtfmethod_" + name;
        //				if (!name.endsWith("init>")) {
        //					name = "_vtfmethod_"+ name;
        //				} else {
        //					if (name.equals("<init>")) {
        //						name = "_vtfmethod_constructor";
        //					} else {
        //		        		name = "_vtfmethod_class_initialization";
        //					}
        //				}
      }
    }

    if (iparams.shouldModifyTimeCalls()) {
      if ((opcode == INVOKESTATIC
              && owner.equals("java/lang/System")
              && name.equals("currentTimeMillis")
              && desc.equals("()J"))
          || (opcode == INVOKESTATIC
              && owner.equals("java/lang/System")
              && name.equals("nanoTime")
              && desc.equals("()J"))) {
        mv.visitMethodInsn(INVOKESTATIC, "virtualtime/EventNotifier", name, desc);
        return;
      }
    }
    mv.visitMethodInsn(opcode, owner, name, desc);
  }