changeset 13103:c0b0974dd509

moved notification of Graal compilation statistics from VMToCompiler to CompilerToVM
author Doug Simon <doug.simon@oracle.com>
date Thu, 21 Nov 2013 22:08:04 +0100
parents f9f4503a4ab5
children dd941feb26cb
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalVMToCompiler.cpp src/share/vm/graal/graalVMToCompiler.hpp src/share/vm/graal/vmStructs_graal.hpp src/share/vm/runtime/timer.cpp src/share/vm/runtime/timer.hpp
diffstat 15 files changed, 83 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Thu Nov 21 22:08:04 2013 +0100
@@ -204,8 +204,9 @@
                 long processedBytes = InlinedBytecodes.getCurrentValue() - previousInlinedBytecodes;
                 long time = CompilationTime.getCurrentValue() - previousCompilationTime;
                 TimeUnit timeUnit = CompilationTime.getTimeUnit();
-                VMToCompiler vm2c = backend.getRuntime().getVMToCompiler();
-                vm2c.notifyCompilationDone(id, method, entryBCI != INVOCATION_ENTRY_BCI, (int) processedBytes, time, timeUnit, installedCode);
+                long timeUnitsPerSecond = timeUnit.convert(1, TimeUnit.SECONDS);
+                CompilerToVM c2vm = backend.getRuntime().getCompilerToVM();
+                c2vm.notifyCompilationStatistics(id, method, entryBCI != INVOCATION_ENTRY_BCI, (int) processedBytes, time, timeUnitsPerSecond, installedCode);
             }
 
             assert method.isQueuedForCompilation();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Thu Nov 21 22:08:04 2013 +0100
@@ -35,7 +35,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.logging.*;
-import com.oracle.graal.java.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.common.*;
 
@@ -224,7 +223,6 @@
      */
     public static void finalizeOptions(boolean ciTime) {
         if (ciTime) {
-            unconditionallyEnableTimerOrMetric(GraphBuilderPhase.class, "BytecodesParsed");
             unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes");
             unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime");
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Nov 21 22:08:04 2013 +0100
@@ -738,16 +738,6 @@
 
     @HotSpotVMConstant(name = "GRAAL_COUNTERS_SIZE", optional = true) @Stable public int graalCountersSize;
 
-    @HotSpotVMField(name = "CompilerStatistics::_standard", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsStandardOffset;
-    @HotSpotVMField(name = "CompilerStatistics::_osr", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsOsrOffset;
-    @HotSpotVMField(name = "CompilerStatistics::_nmethods_size", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsNmethodsSizeOffset;
-    @HotSpotVMField(name = "CompilerStatistics::_nmethods_code_size", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsNmethodsCodeSizeOffset;
-    @HotSpotVMField(name = "CompilerStatistics::Data::_bytes", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsDataBytesOffset;
-    @HotSpotVMField(name = "CompilerStatistics::Data::_time", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsDataTimeOffset;
-    @HotSpotVMField(name = "CompilerStatistics::Data::_count", get = HotSpotVMField.Type.OFFSET) @Stable public long compilerStatisticsDataCountOffset;
-    @HotSpotVMField(name = "elapsedTimer::_counter", get = HotSpotVMField.Type.OFFSET) @Stable public long elapsedTimerCounterOffset;
-    @Stable public long elapsedTimerFrequency;
-
     /**
      * This field is used to pass exception objects into and out of the runtime system during
      * exception handling for compiled code.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Thu Nov 21 22:08:04 2013 +0100
@@ -146,6 +146,22 @@
      */
     CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog cache);
 
+    /**
+     * Notifies the VM of statistics for a completed compilation.
+     * 
+     * @param id the identifier of the compilation
+     * @param method the method compiled
+     * @param osr specifies if the compilation was for on-stack-replacement
+     * @param processedBytecodes the number of bytecodes processed during the compilation, including
+     *            the bytecodes of all inlined methods
+     * @param time the amount time spent compiling {@code method}
+     * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
+     * @param installedCode the nmethod installed as a result of the compilation
+     */
+    void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, HotSpotInstalledCode installedCode);
+
+    void resetCompilationStatistics();
+
     void initializeConfiguration(HotSpotVMConfig config);
 
     JavaMethod resolveMethod(HotSpotResolvedObjectType klass, String name, String signature);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Nov 21 22:08:04 2013 +0100
@@ -176,6 +176,11 @@
         return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode);
     }
 
+    public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
+                    HotSpotInstalledCode installedCode);
+
+    public native void resetCompilationStatistics();
+
     /**
      * Direct call to the given nmethod with three object arguments and an object return value. This
      * method does not have an implementation on the C++ side, but its entry points (from
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Thu Nov 21 22:08:04 2013 +0100
@@ -24,7 +24,6 @@
 package com.oracle.graal.hotspot.bridge;
 
 import java.io.*;
-import java.util.concurrent.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.debug.*;
@@ -41,23 +40,9 @@
      */
     void compileMethod(long metaspaceMethod, HotSpotResolvedObjectType holder, int entryBCI, boolean blocking);
 
-    /**
-     * Notifies this object of statistics for a completed compilation.
-     * 
-     * @param id the identifier of the compilation
-     * @param method the method compiled
-     * @param osr specifies if the compilation was for on-stack-replacement
-     * @param processedBytecodes the number of bytecodes processed during the compilation, including
-     *            the bytecodes of all inlined methods
-     * @param time the amount time spent compiling {@code method}
-     * @param timeUnit the units of {@code time}
-     * @param installedCode the nmethod installed as a result of the compilation
-     */
-    void notifyCompilationDone(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, TimeUnit timeUnit, HotSpotInstalledCode installedCode);
-
     void shutdownCompiler() throws Exception;
 
-    void startCompiler(boolean bootstrapEnabled, long statsAddress) throws Throwable;
+    void startCompiler(boolean bootstrapEnabled) throws Throwable;
 
     void bootstrap() throws Throwable;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Nov 21 15:04:54 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Thu Nov 21 22:08:04 2013 +0100
@@ -26,7 +26,6 @@
 import static com.oracle.graal.compiler.GraalDebugConfig.*;
 import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static java.util.concurrent.TimeUnit.*;
 
 import java.io.*;
 import java.lang.reflect.*;
@@ -101,8 +100,6 @@
 
     private long compilerStartTime;
 
-    private long compilerStatistics;
-
     public VMToCompilerImpl(HotSpotGraalRuntime runtime) {
         this.runtime = runtime;
 
@@ -123,7 +120,7 @@
         assert unsafe.getObject(mirror, offset) == type;
     }
 
-    public void startCompiler(boolean bootstrapEnabled, long compilerStatisticsAddress) throws Throwable {
+    public void startCompiler(boolean bootstrapEnabled) throws Throwable {
 
         FastNodeClassRegistry.initialize();
 
@@ -150,7 +147,7 @@
             }
         }
 
-        compilerStatistics = compilerStatisticsAddress;
+        runtime.getCompilerToVM();
 
         TTY.initialize(log);
 
@@ -318,7 +315,7 @@
 
         if (ResetDebugValuesAfterBootstrap.getValue()) {
             printDebugValues("bootstrap", true);
-            resetCompilerStatistics();
+            runtime.getCompilerToVM().resetCompilationStatistics();
         }
         phaseTransition("bootstrap");
 
@@ -600,64 +597,6 @@
         }
     }
 
-    private TimeUnit elapsedTimerTimeUnit;
-
-    private TimeUnit getElapsedTimerTimeUnit() {
-        if (elapsedTimerTimeUnit == null) {
-            long freq = runtime.getConfig().elapsedTimerFrequency;
-            for (TimeUnit tu : TimeUnit.values()) {
-                if (tu.toSeconds(freq) == 1) {
-                    elapsedTimerTimeUnit = tu;
-                    break;
-                }
-            }
-            assert elapsedTimerTimeUnit != null;
-        }
-        return elapsedTimerTimeUnit;
-    }
-
-    public synchronized void notifyCompilationDone(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, TimeUnit timeUnit, HotSpotInstalledCode installedCode) {
-        HotSpotVMConfig config = runtime.getConfig();
-        long dataAddress = compilerStatistics + (osr ? config.compilerStatisticsOsrOffset : config.compilerStatisticsStandardOffset);
-
-        long timeAddress = dataAddress + config.compilerStatisticsDataTimeOffset + config.elapsedTimerCounterOffset;
-        long previousElapsedTime = unsafe.getLong(timeAddress);
-        long elapsedTime = getElapsedTimerTimeUnit().convert(time, timeUnit);
-        unsafe.putLong(timeAddress, previousElapsedTime + elapsedTime);
-
-        long bytesAddress = dataAddress + config.compilerStatisticsDataBytesOffset;
-        int currentBytes = unsafe.getInt(bytesAddress);
-        unsafe.putInt(bytesAddress, currentBytes + processedBytecodes);
-
-        long countAddress = dataAddress + config.compilerStatisticsDataCountOffset;
-        int currentCount = unsafe.getInt(countAddress);
-        unsafe.putInt(countAddress, currentCount + 1);
-
-        long nmethodsSizeAddress = compilerStatistics + config.compilerStatisticsNmethodsSizeOffset;
-        int currentSize = unsafe.getInt(nmethodsSizeAddress);
-        unsafe.putInt(nmethodsSizeAddress, currentSize + installedCode.getSize());
-
-        long nmethodsCodeSizeAddress = compilerStatistics + config.compilerStatisticsNmethodsCodeSizeOffset;
-        int currentCodeSize = unsafe.getInt(nmethodsCodeSizeAddress);
-        unsafe.putInt(nmethodsCodeSizeAddress, currentCodeSize + (int) installedCode.getCodeSize());
-
-        if (config.ciTimeEach) {
-            TTY.println(String.format("%-6d {%s: %d ms, %d bytes}", id, osr ? "osr" : "standard", MILLISECONDS.convert(time, timeUnit), processedBytecodes));
-        }
-    }
-
-    private static void resetCompilerStatisticsData(HotSpotVMConfig config, long dataAddress) {
-        unsafe.putInt(dataAddress + config.compilerStatisticsDataBytesOffset, 0);
-        unsafe.putInt(dataAddress + config.compilerStatisticsDataCountOffset, 0);
-        unsafe.putLong(dataAddress + config.compilerStatisticsDataTimeOffset + config.elapsedTimerCounterOffset, 0L);
-    }
-
-    private void resetCompilerStatistics() {
-        HotSpotVMConfig config = runtime.getConfig();
-        resetCompilerStatisticsData(config, compilerStatistics + config.compilerStatisticsStandardOffset);
-        resetCompilerStatisticsData(config, compilerStatistics + config.compilerStatisticsOsrOffset);
-    }
-
     @Override
     public JavaMethod createUnresolvedJavaMethod(String name, String signature, JavaType holder) {
         return new HotSpotMethodUnresolved(name, signature, holder);
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Nov 21 22:08:04 2013 +0100
@@ -574,7 +574,6 @@
   template(char_array_void_signature,                 "([C)V")                                                    \
   template(int_int_void_signature,                    "(II)V")                                                    \
   template(long_long_void_signature,                  "(JJ)V")                                                    \
-  template(boolean_long_void_signature,               "(ZJ)V")                                                    \
   template(void_classloader_signature,                "()Ljava/lang/ClassLoader;")                                \
   template(void_object_signature,                     "()Ljava/lang/Object;")                                     \
   template(void_class_signature,                      "()Ljava/lang/Class;")                                      \
@@ -919,7 +918,7 @@
    do_signature(copyMemory_signature,         "(Ljava/lang/Object;JLjava/lang/Object;JJ)V")                             \
   do_intrinsic(_park,                     sun_misc_Unsafe,        park_name, park_signature,                     F_RN)  \
    do_name(     park_name,                                       "park")                                                \
-   do_alias(park_signature,                                       boolean_long_void_signature)                          \
+   do_signature(park_signature,                                  "(ZJ)V")                                               \
   do_intrinsic(_unpark,                   sun_misc_Unsafe,        unpark_name, unpark_signature,                 F_RN)  \
    do_name(     unpark_name,                                     "unpark")                                              \
    do_alias(    unpark_signature,                               /*(LObject;)V*/ object_void_signature)                  \
--- a/src/share/vm/graal/graalCompiler.cpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Thu Nov 21 22:08:04 2013 +0100
@@ -102,8 +102,7 @@
 
     if (UseCompiler) {
       bool bootstrap = GRAALVM_ONLY(BootstrapGraal) NOT_GRAALVM(false);
-      jlong compilerStatisticsAddress = (jlong) ((address) (stats()));
-      VMToCompiler::startCompiler(bootstrap, compilerStatisticsAddress);
+      VMToCompiler::startCompiler(bootstrap);
       _initialized = true;
       CompilationPolicy::completed_vm_startup();
       if (bootstrap) {
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Nov 21 22:08:04 2013 +0100
@@ -732,8 +732,6 @@
 
   set_int("instanceKlassVtableStartOffset", InstanceKlass::vtable_start_offset() * HeapWordSize);
 
-  set_long("elapsedTimerFrequency", os::elapsed_frequency());
-
   //------------------------------------------------------------------------------------------------
 
   set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
@@ -827,6 +825,37 @@
   return result;
 C2V_END
 
+C2V_VMENTRY(void, notifyCompilationStatistics, (JNIEnv *jniEnv, jobject, jint id, jobject hotspot_method, jboolean osr, jint processedBytecodes, jlong time, jlong timeUnitsPerSecond, jobject installed_code))
+  CompilerStatistics* stats = GraalCompiler::instance()->stats();
+
+  elapsedTimer timer = elapsedTimer(time, timeUnitsPerSecond);
+  if (osr) {
+    stats->_osr.update(timer, processedBytecodes);
+  } else {
+    stats->_standard.update(timer, processedBytecodes);
+  }
+  Handle installed_code_handle = JNIHandles::resolve(installed_code);
+  stats->_nmethods_size += HotSpotInstalledCode::size(installed_code_handle);
+  stats->_nmethods_code_size += HotSpotInstalledCode::codeSize(installed_code_handle);
+
+  if (CITimeEach) {
+    methodHandle method = asMethod(HotSpotResolvedJavaMethod::metaspaceMethod(hotspot_method));
+    float bytes_per_sec = 1.0 * processedBytecodes / timer.seconds();
+    tty->print_cr("%3d   seconds: %f bytes/sec: %f (bytes %d)",
+                  id, timer.seconds(), bytes_per_sec, processedBytecodes);
+  }
+C2V_END
+
+C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
+  CompilerStatistics* stats = GraalCompiler::instance()->stats();
+  stats->_standard._time.reset();
+  stats->_standard._bytes = 0;
+  stats->_standard._count = 0;
+  stats->_osr._time.reset();
+  stats->_osr._bytes = 0;
+  stats->_osr._count = 0;
+C2V_END
+
 C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob))
   ResourceMark rm;
   HandleMark hm;
@@ -1098,6 +1127,8 @@
   {CC"getJavaField",                  CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD,                           FN_PTR(getJavaField)},
   {CC"initializeConfiguration",       CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
   {CC"installCode0",                  CC"("HS_COMPILED_CODE HS_INSTALLED_CODE"[Z)I",                    FN_PTR(installCode0)},
+  {CC"notifyCompilationStatistics",   CC"(I"HS_RESOLVED_METHOD"ZIJJ"HS_INSTALLED_CODE")V",              FN_PTR(notifyCompilationStatistics)},
+  {CC"resetCompilationStatistics",    CC"()V",                                                          FN_PTR(resetCompilationStatistics)},
   {CC"disassembleCodeBlob",           CC"(J)"STRING,                                                    FN_PTR(disassembleCodeBlob)},
   {CC"executeCompiledMethodVarargs",  CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT,                          FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
--- a/src/share/vm/graal/graalVMToCompiler.cpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/graal/graalVMToCompiler.cpp	Thu Nov 21 22:08:04 2013 +0100
@@ -146,14 +146,13 @@
   }
 }
 
-void VMToCompiler::startCompiler(jboolean bootstrap_enabled, jlong compilerStatisticsAddress) {
+void VMToCompiler::startCompiler(jboolean bootstrap_enabled) {
   JavaThread* THREAD = JavaThread::current();
   JavaValue result(T_VOID);
   JavaCallArguments args;
   args.push_oop(instance());
   args.push_int(bootstrap_enabled);
-  args.push_long(compilerStatisticsAddress);
-  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), vmSymbols::boolean_long_void_signature(), &args, THREAD);
+  JavaCalls::call_interface(&result, vmToCompilerKlass(), vmSymbols::startCompiler_name(), vmSymbols::bool_void_signature(), &args, THREAD);
   check_pending_exception("Error while calling startCompiler");
 }
 
--- a/src/share/vm/graal/graalVMToCompiler.hpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/graal/graalVMToCompiler.hpp	Thu Nov 21 22:08:04 2013 +0100
@@ -67,7 +67,7 @@
   static void shutdownCompiler();
   
   // public abstract void startCompiler(boolean bootstrapEnabled);
-  static void startCompiler(jboolean bootstrap_enabled, jlong compilerStatisticsAddress);
+  static void startCompiler(jboolean bootstrap_enabled);
   
   // public abstract void bootstrap();
   static void bootstrap();
--- a/src/share/vm/graal/vmStructs_graal.hpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/graal/vmStructs_graal.hpp	Thu Nov 21 22:08:04 2013 +0100
@@ -31,19 +31,9 @@
                                                                               \
   static_field(java_lang_Class, _graal_mirror_offset, int)                    \
                                                                               \
-  nonstatic_field(CompilerStatistics, _standard,           CompilerStatistics::Data) \
-  nonstatic_field(CompilerStatistics, _osr,                CompilerStatistics::Data) \
-  nonstatic_field(CompilerStatistics, _nmethods_size,      int)                      \
-  nonstatic_field(CompilerStatistics, _nmethods_code_size, int)                      \
-  nonstatic_field(CompilerStatistics::Data, _bytes,        int)                      \
-  nonstatic_field(CompilerStatistics::Data, _count,        int)                      \
-  nonstatic_field(CompilerStatistics::Data, _time,         elapsedTimer)             \
-
 
 #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type)                   \
                                                                               \
-  declare_toplevel_type(CompilerStatistics)                                   \
-  declare_toplevel_type(CompilerStatistics::Data)                             \
 
 
 #endif // SHARE_VM_GRAAL_VMSTRUCTS_GRAAL_HPP
--- a/src/share/vm/runtime/timer.cpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/runtime/timer.cpp	Thu Nov 21 22:08:04 2013 +0100
@@ -45,6 +45,22 @@
   return counter/freq;
 }
 
+elapsedTimer::elapsedTimer(jlong time, jlong timeUnitsPerSecond) {
+  _active = false;
+  jlong osTimeUnitsPerSecond = os::elapsed_frequency();
+  assert(osTimeUnitsPerSecond % 1000 == 0, "must be");
+  assert(timeUnitsPerSecond % 1000 == 0, "must be");
+  while (osTimeUnitsPerSecond < timeUnitsPerSecond) {
+    timeUnitsPerSecond /= 1000;
+    time *= 1000;
+  }
+  while (osTimeUnitsPerSecond > timeUnitsPerSecond) {
+    timeUnitsPerSecond *= 1000;
+    time /= 1000;
+  }
+  _counter = time;
+}
+
 void elapsedTimer::add(elapsedTimer t) {
   _counter += t._counter;
 }
--- a/src/share/vm/runtime/timer.hpp	Thu Nov 21 15:04:54 2013 +0100
+++ b/src/share/vm/runtime/timer.hpp	Thu Nov 21 22:08:04 2013 +0100
@@ -37,6 +37,7 @@
   bool  _active;
  public:
   elapsedTimer()             { _active = false; reset(); }
+  elapsedTimer(jlong time, jlong timeUnitsPerSecond);
   void add(elapsedTimer t);
   void start();
   void stop();