コード例 #1
0
 /** * Code to be instrumented when a method is exited. */
 private void onMethodExitInstrumentation() {
   if (!iparams.usingExternalInstrumentation() || methodName.endsWith("init>")) {
     if (iparams.methodShouldBeAdapted(methodId)) {
       if (isMethodDescribedByPerformanceModel()) {
         if (!shouldMethodBodyBeRemoved()) {
           // Only the case that real code is executed under performance model time will call this
           BasicBlockAdapter.insertMethodInstrument(mv, methodId, "_exitPerfModel");
         } else {
           BasicBlockAdapter.insertMethodInstrument(mv, methodId, "_exitPerfModel");
         }
       } else {
         BasicBlockAdapter.insertMethodInstrument(
             mv, methodId, BasicBlockAdapter.vtfMethodExitCallback);
       }
     }
   }
 }
コード例 #2
0
 /** * Code to be instrumented when a method is entered. */
 private void onMethodEntryInstrumentation() {
   if (!iparams.usingExternalInstrumentation() || methodName.endsWith("init>")) {
     if (iparams.methodShouldBeAdapted(methodId)) {
       if (isMethodDescribedByPerformanceModel()) {
         if (!shouldMethodBodyBeRemoved()) {
           // The method body will be executed as normal, but the performance impact will only
           // depend on the provided model
           // This is used to simulate the behaviour, but still get the correct behaviour
           BasicBlockAdapter.insertMethodInstrument(mv, methodId, "_enterPerfModel");
         } else {
           // No method behaviour, just performance cost added by the model
           BasicBlockAdapter.insertMethodInstrument(mv, methodId, "_enterPerfModel");
         }
       } else {
         BasicBlockAdapter.insertMethodInstrument(
             mv, methodId, BasicBlockAdapter.vtfMethodEntryCallback);
       }
     }
   }
 }
コード例 #3
0
 /** * Code to be instrumented when an interaction point is encountered. */
 private void onInteractionPointEncounter() {
   if (iparams.trappingInteractionPoints()) {
     mv.visitMethodInsn(INVOKESTATIC, "virtualtime/EventNotifier", "_interactionPoint", "()V");
   }
 }
コード例 #4
0
  /**
   * * Visit any byte-code instruction
   *
   * <p>This allows us to instrument methods an the instruction level. Instructions that are
   * instrumented this way regard exiting and synchronising byte-code instructions
   */
  @Override
  public void visitInsn(int opcode) {

    instrumentationStatsRecord.addInstruction();

    // if (opcode != ATHROW) {
    if (performanceModelParameters != null) {
      if (performanceModelParameters.removingMethodBody()) {
        if ((opcode >= IRETURN && opcode <= RETURN)
            || (!instrumentExceptionHandlingCode && opcode == ATHROW)) {
          if (profile) {
            onMethodExitInstrumentation();
          }
          mv.visitInsn(opcode);
        }
        return;
      }
    }

    // These are all instructions which terminate a method
    if ((opcode >= IRETURN && opcode <= RETURN)
        || (!instrumentExceptionHandlingCode && opcode == ATHROW && tryCatchDepth == 0)) {

      if (profile) {
        onMethodExitInstrumentation();
      }

      if (iparams.onlyLimitedJvmtiUsage() && isSynchronised) {
        if (isStatic) {
          mv.visitLdcInsn(Type.getType("L" + className + ";"));
        } else {
          mv.visitVarInsn(ALOAD, 0);
        }
        //				mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I");
        mv.visitMethodInsn(
            INVOKESTATIC, "java/lang/System", "identityHashCode", "(Ljava/lang/Object;)I");
        mv.visitMethodInsn(
            INVOKESTATIC, "virtualtime/EventNotifier", "_beforeReleasingMonitor", "(I)V");
      }

      if (shouldBeWrappedWithVexOptimizerLoop) {
        mv.visitMethodInsn(
            INVOKESTATIC,
            "virtualtime/EventNotifier",
            "_exportAndProcessMainIterationResults",
            "()V");
        mv.visitJumpInsn(GOTO, startMainWrappedWithVexOptimizer);
        mv.visitLabel(endMainWrappedWithVexOptimizer);
      }
      mv.visitInsn(opcode);
      return;
    }

    // Monitor enter instrumentation - suspend thread
    if (opcode == MONITORENTER || opcode == MONITOREXIT) {
      instrumentationStatsRecord.addSyncPrimitive();

      if (iparams.onlyLimitedJvmtiUsage()) {

        if (!iparams.shouldRemoveMonitors()) {
          mv.visitInsn(DUP);
        }
        if (opcode == MONITORENTER) {
          //					mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I");
          mv.visitMethodInsn(
              INVOKESTATIC, "java/lang/System", "identityHashCode", "(Ljava/lang/Object;)I");
          onInteractionPointEncounter();
          mv.visitMethodInsn(
              INVOKESTATIC, "virtualtime/EventNotifier", "_beforeAcquiringMonitor", "(I)V");

        } else {
          onInteractionPointEncounter();
          // mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I");
          mv.visitMethodInsn(
              INVOKESTATIC, "java/lang/System", "identityHashCode", "(Ljava/lang/Object;)I");

          mv.visitMethodInsn(
              INVOKESTATIC, "virtualtime/EventNotifier", "_beforeReleasingMonitor", "(I)V");
        }

        if (iparams.shouldRemoveMonitors()) {
          return;
        }
      }
    }
    mv.visitInsn(opcode);
  }
コード例 #5
0
  /**
   * * 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);
  }
コード例 #6
0
  /**
   * * Constructor setting the parameters of the method
   *
   * @param arg0 the method visitor object to write the new code
   * @param _methodId the unique JINE id of the method
   * @param isProfiled should we add instrumentation code to profile the method
   * @param access access rules of the method
   * @param cName class name
   * @param mName method name
   * @param desc arguments description
   * @param signature signature
   * @param exceptions array of strings with the possibly thrown exception classes
   * @param _iparams instrumentation parameters as selected by the user options
   */
  public BasicBlockMethodAdapter(
      MethodVisitor arg0,
      int _methodId,
      boolean isProfiled,
      int access,
      String cName,
      String mName,
      String desc,
      String signature,
      String[] exceptions,
      InstrumentationParameters _iparams,
      MethodAdaptationInfo _methodAdaptationInfo) {

    super(arg0);

    instrumentationStatsRecord = InstrumentationRecordFactory.getRecord();

    allStartingTryCatchingBlockLabels = null;
    allEndingTryCatchingBlockLabels = null;
    tryCatchDepth = 0;

    iparams = _iparams;
    methodAdaptationInfo = _methodAdaptationInfo;

    methodId = _methodId;

    className = cName;
    methodName = mName;
    methodDesc = desc;

    isSynchronised = (access & ACC_SYNCHRONIZED) != 0;
    isStatic = (access & ACC_STATIC) != 0;

    profile =
        isProfiled
            && !(isSynchronised
                && (iparams.trappingInteractionPoints()
                    || (iparams
                        .usingExternalInstrumentation()))); // sync methods are profiled externally
                                                            // when IPs are trapped

    // Some methods
    if (iparams.exceptionHandlingEverywhere()) {
      instrumentExceptionHandlingCode = true;
    } else {
      instrumentExceptionHandlingCode = false;
    }

    // Register the methodId to the VTF
    if (profile) {
      instrumentationStatsRecord.setProfiled();

      if (!iparams.isRetransformingInstrumentation()) {
        EventNotifier.registerMethod(
            cName + " " + mName + " " + desc, methodId, _iparams.getMethod0());
      } else {
        instrumentationStatsRecord.setRetransformed();
      }

      shouldBeWrappedWithVexOptimizerLoop =
          iparams.shouldBeWrappedWithVexOptimizerLoop(mName); // wrap the first appearance of main
      if (shouldBeWrappedWithVexOptimizerLoop) {
        System.out.println("will wrap vex optimizer " + cName + " " + mName + " " + desc);
      }

      if (iparams.methodShouldBeAdapted(methodId)) {
        if (exceptions != null && exceptions.length > 0) {
          instrumentExceptionHandlingCode = true;
        }
      }
    }

    if (DEBUG) {
      System.out.println("Instrumenting  " + cName + " -> " + mName + "(" + methodId + ")" + desc);
    }

    performanceModelParameters = null;
  }