changeset 8369:610dc20a7bc8

Merge
author jwilhelm
date Mon, 11 May 2015 16:30:26 +0200
parents 08b5dfe9bcb5 a4a5ef4bc0c2
children cf90d6ff5a27 92457dfb91bd
files src/os/linux/vm/os_linux.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp
diffstat 14 files changed, 142 insertions(+), 183 deletions(-) [+]
line wrap: on
line diff
--- a/src/os/linux/vm/os_linux.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/os/linux/vm/os_linux.cpp	Mon May 11 16:30:26 2015 +0200
@@ -4799,8 +4799,8 @@
             FLAG_IS_DEFAULT(UseSHM) &&
             FLAG_IS_DEFAULT(UseHugeTLBFS)) {
           UseLargePages = false;
-        } else {
-          warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing");
+        } else if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) {
+          warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)");
           UseAdaptiveSizePolicy = false;
           UseAdaptiveNUMAChunkSizing = false;
         }
--- a/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Mon May 11 16:30:26 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
 }
 
 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
-  SuspendibleThreadSetJoiner sts;
+  SuspendibleThreadSetJoiner sts_join;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1p = g1h->g1_policy();
   if (g1p->adaptive_young_list_length()) {
@@ -89,8 +89,8 @@
 
       // we try to yield every time we visit 10 regions
       if (regions_visited == 10) {
-        if (sts.should_yield()) {
-          sts.yield();
+        if (sts_join.should_yield()) {
+          sts_join.yield();
           // we just abandon the iteration
           break;
         }
@@ -188,7 +188,7 @@
     }
 
     {
-      SuspendibleThreadSetJoiner sts;
+      SuspendibleThreadSetJoiner sts_join;
 
       do {
         int curr_buffer_num = (int)dcqs.completed_buffers_num();
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp	Mon May 11 16:30:26 2015 +0200
@@ -193,13 +193,8 @@
       _cl(cl), _suspendible(suspendible), AbstractGangTask("Parallel Clear Bitmap Task"), _hrclaimer(n_workers) {}
 
   void work(uint worker_id) {
-    if (_suspendible) {
-      SuspendibleThreadSet::join();
-    }
+    SuspendibleThreadSetJoiner sts_join(_suspendible);
     G1CollectedHeap::heap()->heap_region_par_iterate(_cl, worker_id, &_hrclaimer, true);
-    if (_suspendible) {
-      SuspendibleThreadSet::leave();
-    }
   }
 };
 
@@ -275,7 +270,6 @@
   _capacity = (jint) capacity;
   _saved_index = -1;
   _should_expand = false;
-  NOT_PRODUCT(_max_depth = 0);
   return true;
 }
 
@@ -331,54 +325,6 @@
   }
 }
 
-void CMMarkStack::par_push(oop ptr) {
-  while (true) {
-    if (isFull()) {
-      _overflow = true;
-      return;
-    }
-    // Otherwise...
-    jint index = _index;
-    jint next_index = index+1;
-    jint res = Atomic::cmpxchg(next_index, &_index, index);
-    if (res == index) {
-      _base[index] = ptr;
-      // Note that we don't maintain this atomically.  We could, but it
-      // doesn't seem necessary.
-      NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index));
-      return;
-    }
-    // Otherwise, we need to try again.
-  }
-}
-
-void CMMarkStack::par_adjoin_arr(oop* ptr_arr, int n) {
-  while (true) {
-    if (isFull()) {
-      _overflow = true;
-      return;
-    }
-    // Otherwise...
-    jint index = _index;
-    jint next_index = index + n;
-    if (next_index > _capacity) {
-      _overflow = true;
-      return;
-    }
-    jint res = Atomic::cmpxchg(next_index, &_index, index);
-    if (res == index) {
-      for (int i = 0; i < n; i++) {
-        int  ind = index + i;
-        assert(ind < _capacity, "By overflow test above.");
-        _base[ind] = ptr_arr[i];
-      }
-      NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index));
-      return;
-    }
-    // Otherwise, we need to try again.
-  }
-}
-
 void CMMarkStack::par_push_arr(oop* ptr_arr, int n) {
   MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
   jint start = _index;
@@ -394,7 +340,6 @@
     assert(ind < _capacity, "By overflow test above.");
     _base[ind] = ptr_arr[i];
   }
-  NOT_PRODUCT(_max_depth = MAX2(_max_depth, next_index));
 }
 
 bool CMMarkStack::par_pop_arr(oop* ptr_arr, int max, int* n) {
@@ -1006,19 +951,17 @@
  */
 
 void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
+  bool barrier_aborted;
+
   if (verbose_low()) {
     gclog_or_tty->print_cr("[%u] entering first barrier", worker_id);
   }
 
-  if (concurrent()) {
-    SuspendibleThreadSet::leave();
+  {
+    SuspendibleThreadSetLeaver sts_leave(concurrent());
+    barrier_aborted = !_first_overflow_barrier_sync.enter();
   }
 
-  bool barrier_aborted = !_first_overflow_barrier_sync.enter();
-
-  if (concurrent()) {
-    SuspendibleThreadSet::join();
-  }
   // at this point everyone should have synced up and not be doing any
   // more work
 
@@ -1065,19 +1008,17 @@
 }
 
 void ConcurrentMark::enter_second_sync_barrier(uint worker_id) {
+  bool barrier_aborted;
+
   if (verbose_low()) {
     gclog_or_tty->print_cr("[%u] entering second barrier", worker_id);
   }
 
-  if (concurrent()) {
-    SuspendibleThreadSet::leave();
+  {
+    SuspendibleThreadSetLeaver sts_leave(concurrent());
+    barrier_aborted = !_second_overflow_barrier_sync.enter();
   }
 
-  bool barrier_aborted = !_second_overflow_barrier_sync.enter();
-
-  if (concurrent()) {
-    SuspendibleThreadSet::join();
-  }
   // at this point everything should be re-initialized and ready to go
 
   if (verbose_low()) {
@@ -1128,40 +1069,41 @@
 
     double start_vtime = os::elapsedVTime();
 
-    SuspendibleThreadSet::join();
-
-    assert(worker_id < _cm->active_tasks(), "invariant");
-    CMTask* the_task = _cm->task(worker_id);
-    the_task->record_start_time();
-    if (!_cm->has_aborted()) {
-      do {
-        double start_vtime_sec = os::elapsedVTime();
-        double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
-
-        the_task->do_marking_step(mark_step_duration_ms,
-                                  true  /* do_termination */,
-                                  false /* is_serial*/);
-
-        double end_vtime_sec = os::elapsedVTime();
-        double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
-        _cm->clear_has_overflown();
-
-        _cm->do_yield_check(worker_id);
-
-        jlong sleep_time_ms;
-        if (!_cm->has_aborted() && the_task->has_aborted()) {
-          sleep_time_ms =
-            (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
-          SuspendibleThreadSet::leave();
-          os::sleep(Thread::current(), sleep_time_ms, false);
-          SuspendibleThreadSet::join();
-        }
-      } while (!_cm->has_aborted() && the_task->has_aborted());
+    {
+      SuspendibleThreadSetJoiner sts_join;
+
+      assert(worker_id < _cm->active_tasks(), "invariant");
+      CMTask* the_task = _cm->task(worker_id);
+      the_task->record_start_time();
+      if (!_cm->has_aborted()) {
+        do {
+          double start_vtime_sec = os::elapsedVTime();
+          double mark_step_duration_ms = G1ConcMarkStepDurationMillis;
+
+          the_task->do_marking_step(mark_step_duration_ms,
+                                    true  /* do_termination */,
+                                    false /* is_serial*/);
+
+          double end_vtime_sec = os::elapsedVTime();
+          double elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
+          _cm->clear_has_overflown();
+
+          _cm->do_yield_check(worker_id);
+
+          jlong sleep_time_ms;
+          if (!_cm->has_aborted() && the_task->has_aborted()) {
+            sleep_time_ms =
+              (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
+            {
+              SuspendibleThreadSetLeaver sts_leave;
+              os::sleep(Thread::current(), sleep_time_ms, false);
+            }
+          }
+        } while (!_cm->has_aborted() && the_task->has_aborted());
+      }
+      the_task->record_end_time();
+      guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
     }
-    the_task->record_end_time();
-    guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
-
-    SuspendibleThreadSet::leave();
 
     double end_vtime = os::elapsedVTime();
     _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp	Mon May 11 16:30:26 2015 +0200
@@ -180,25 +180,12 @@
   jint _index;       // one more than last occupied index
   jint _capacity;    // max #elements
   jint _saved_index; // value of _index saved at start of GC
-  NOT_PRODUCT(jint _max_depth;)   // max depth plumbed during run
 
   bool  _overflow;
   bool  _should_expand;
   DEBUG_ONLY(bool _drain_in_progress;)
   DEBUG_ONLY(bool _drain_in_progress_yields;)
 
- public:
-  CMMarkStack(ConcurrentMark* cm);
-  ~CMMarkStack();
-
-#ifndef PRODUCT
-  jint max_depth() const {
-    return _max_depth;
-  }
-#endif
-
-  bool allocate(size_t capacity);
-
   oop pop() {
     if (!isEmpty()) {
       return _base[--_index] ;
@@ -206,27 +193,11 @@
     return NULL;
   }
 
-  // If overflow happens, don't do the push, and record the overflow.
-  // *Requires* that "ptr" is already marked.
-  void push(oop ptr) {
-    if (isFull()) {
-      // Record overflow.
-      _overflow = true;
-      return;
-    } else {
-      _base[_index++] = ptr;
-      NOT_PRODUCT(_max_depth = MAX2(_max_depth, _index));
-    }
-  }
-  // Non-block impl.  Note: concurrency is allowed only with other
-  // "par_push" operations, not with "pop" or "drain".  We would need
-  // parallel versions of them if such concurrency was desired.
-  void par_push(oop ptr);
+ public:
+  CMMarkStack(ConcurrentMark* cm);
+  ~CMMarkStack();
 
-  // Pushes the first "n" elements of "ptr_arr" on the stack.
-  // Non-block impl.  Note: concurrency is allowed only with other
-  // "par_adjoin_arr" or "push" operations, not with "pop" or "drain".
-  void par_adjoin_arr(oop* ptr_arr, int n);
+  bool allocate(size_t capacity);
 
   // Pushes the first "n" elements of "ptr_arr" on the stack.
   // Locking impl: concurrency is allowed only with
@@ -254,7 +225,6 @@
   bool drain(OopClosureClass* cl, CMBitMap* bm, bool yield_after = false);
 
   bool isEmpty()    { return _index == 0; }
-  bool isFull()     { return _index == _capacity; }
   int  maxElems()   { return _capacity; }
 
   bool overflow() { return _overflow; }
@@ -378,7 +348,6 @@
   friend class ConcurrentMarkThread;
   friend class CMTask;
   friend class CMBitMapClosure;
-  friend class CMGlobalObjectClosure;
   friend class CMRemarkTask;
   friend class CMConcurrentMarkingTask;
   friend class G1ParNoteEndTask;
@@ -473,8 +442,8 @@
   // All of these times are in ms
   NumberSeq _init_times;
   NumberSeq _remark_times;
-  NumberSeq   _remark_mark_times;
-  NumberSeq   _remark_weak_ref_times;
+  NumberSeq _remark_mark_times;
+  NumberSeq _remark_weak_ref_times;
   NumberSeq _cleanup_times;
   double    _total_counting_time;
   double    _total_rs_scrub_time;
@@ -623,19 +592,9 @@
 
 public:
   // Manipulation of the global mark stack.
-  // Notice that the first mark_stack_push is CAS-based, whereas the
-  // two below are Mutex-based. This is OK since the first one is only
-  // called during evacuation pauses and doesn't compete with the
-  // other two (which are called by the marking tasks during
-  // concurrent marking or remark).
-  bool mark_stack_push(oop p) {
-    _markStack.par_push(p);
-    if (_markStack.overflow()) {
-      set_has_overflown();
-      return false;
-    }
-    return true;
-  }
+  // The push and pop operations are used by tasks for transfers
+  // between task-local queues and the global mark stack, and use
+  // locking for concurrency safety.
   bool mark_stack_push(oop* arr, int n) {
     _markStack.par_push_arr(arr, n);
     if (_markStack.overflow()) {
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp	Mon May 11 16:30:26 2015 +0200
@@ -192,7 +192,7 @@
       } else {
         // We don't want to update the marking status if a GC pause
         // is already underway.
-        SuspendibleThreadSetJoiner sts;
+        SuspendibleThreadSetJoiner sts_join;
         g1h->set_marking_complete();
       }
 
@@ -262,7 +262,7 @@
       // not needed any more as the concurrent mark state has been
       // already reset).
       {
-        SuspendibleThreadSetJoiner sts;
+        SuspendibleThreadSetJoiner sts_join;
         if (!cm()->has_aborted()) {
           g1_policy->record_concurrent_mark_cleanup_completed();
         }
@@ -291,7 +291,7 @@
     // Java thread is waiting for a full GC to happen (e.g., it
     // called System.gc() with +ExplicitGCInvokesConcurrent).
     {
-      SuspendibleThreadSetJoiner sts;
+      SuspendibleThreadSetJoiner sts_join;
       g1h->increment_old_marking_cycles_completed(true /* concurrent */);
       g1h->register_concurrent_cycle_end();
     }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Mon May 11 16:30:26 2015 +0200
@@ -1877,13 +1877,18 @@
   // Carve out the G1 part of the heap.
 
   ReservedSpace g1_rs = heap_rs.first_part(max_byte_size);
+  size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
   G1RegionToSpaceMapper* heap_storage =
     G1RegionToSpaceMapper::create_mapper(g1_rs,
                                          g1_rs.size(),
-                                         UseLargePages ? os::large_page_size() : os::vm_page_size(),
+                                         page_size,
                                          HeapRegion::GrainBytes,
                                          1,
                                          mtJavaHeap);
+  os::trace_page_sizes("G1 Heap", collector_policy()->min_heap_byte_size(),
+                       max_byte_size, page_size,
+                       heap_rs.base(),
+                       heap_rs.size());
   heap_storage->set_mapping_changed_listener(&_listener);
 
   // Create storage for the BOT, card table, card counts table (hot card cache) and the bitmaps.
--- a/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp	Mon May 11 16:30:26 2015 +0200
@@ -74,7 +74,7 @@
 
     {
       // Include thread in safepoints
-      SuspendibleThreadSetJoiner sts;
+      SuspendibleThreadSetJoiner sts_join;
 
       stat.mark_exec();
 
@@ -88,9 +88,9 @@
         G1StringDedupTable::deduplicate(java_string, stat);
 
         // Safepoint this thread if needed
-        if (sts.should_yield()) {
+        if (sts_join.should_yield()) {
           stat.mark_block();
-          sts.yield();
+          sts_join.yield();
           stat.mark_unblock();
         }
       }
--- a/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp	Mon May 11 16:30:26 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,16 +33,20 @@
 double SuspendibleThreadSet::_suspend_all_start = 0.0;
 
 void SuspendibleThreadSet::join() {
+  assert(!Thread::current()->is_suspendible_thread(), "Thread already joined");
   MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
   while (_suspend_all) {
     ml.wait(Mutex::_no_safepoint_check_flag);
   }
   _nthreads++;
+  DEBUG_ONLY(Thread::current()->set_suspendible_thread();)
 }
 
 void SuspendibleThreadSet::leave() {
+  assert(Thread::current()->is_suspendible_thread(), "Thread not joined");
   MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
   assert(_nthreads > 0, "Invalid");
+  DEBUG_ONLY(Thread::current()->clear_suspendible_thread();)
   _nthreads--;
   if (_suspend_all) {
     ml.notify_all();
@@ -50,6 +54,7 @@
 }
 
 void SuspendibleThreadSet::yield() {
+  assert(Thread::current()->is_suspendible_thread(), "Must have joined");
   if (_suspend_all) {
     MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
     if (_suspend_all) {
--- a/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp	Mon May 11 16:30:26 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,19 +36,22 @@
 // suspending thread later calls desynchronize(), allowing the suspended
 // threads to continue.
 class SuspendibleThreadSet : public AllStatic {
+  friend class SuspendibleThreadSetJoiner;
+  friend class SuspendibleThreadSetLeaver;
+
 private:
   static uint   _nthreads;
   static uint   _nthreads_stopped;
   static bool   _suspend_all;
   static double _suspend_all_start;
 
-public:
   // Add the current thread to the set. May block if a suspension is in progress.
   static void join();
 
   // Removes the current thread from the set.
   static void leave();
 
+public:
   // Returns true if an suspension is in progress.
   static bool should_yield() { return _suspend_all; }
 
@@ -63,22 +66,52 @@
 };
 
 class SuspendibleThreadSetJoiner : public StackObj {
+private:
+  bool _active;
+
 public:
-  SuspendibleThreadSetJoiner() {
-    SuspendibleThreadSet::join();
+  SuspendibleThreadSetJoiner(bool active = true) : _active(active) {
+    if (_active) {
+      SuspendibleThreadSet::join();
+    }
   }
 
   ~SuspendibleThreadSetJoiner() {
-    SuspendibleThreadSet::leave();
+    if (_active) {
+      SuspendibleThreadSet::leave();
+    }
   }
 
   bool should_yield() {
-    return SuspendibleThreadSet::should_yield();
+    if (_active) {
+      return SuspendibleThreadSet::should_yield();
+    } else {
+      return false;
+    }
   }
 
   void yield() {
+    assert(_active, "Thread has not joined the suspendible thread set");
     SuspendibleThreadSet::yield();
   }
 };
 
+class SuspendibleThreadSetLeaver : public StackObj {
+private:
+  bool _active;
+
+public:
+  SuspendibleThreadSetLeaver(bool active = true) : _active(active) {
+    if (_active) {
+      SuspendibleThreadSet::leave();
+    }
+  }
+
+  ~SuspendibleThreadSetLeaver() {
+    if (_active) {
+      SuspendibleThreadSet::join();
+    }
+  }
+};
+
 #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
--- a/src/share/vm/runtime/task.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/runtime/task.cpp	Mon May 11 16:30:26 2015 +0200
@@ -53,7 +53,7 @@
   if (ProfilerCheckIntervals) {
     _ticks++;
     _timer.stop();
-    int ms = (int)(_timer.seconds() * 1000.0);
+    int ms = (int)_timer.milliseconds();
     _timer.reset();
     _timer.start();
     if (ms >= PeriodicTask::max_interval) ms = PeriodicTask::max_interval - 1;
--- a/src/share/vm/runtime/thread.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/runtime/thread.cpp	Mon May 11 16:30:26 2015 +0200
@@ -190,6 +190,7 @@
   set_stack_size(0);
   set_self_raw_id(0);
   set_lgrp_id(-1);
+  DEBUG_ONLY(clear_suspendible_thread();)
 
   // allocated data structures
   set_osthread(NULL);
--- a/src/share/vm/runtime/thread.hpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/runtime/thread.hpp	Mon May 11 16:30:26 2015 +0200
@@ -204,11 +204,25 @@
  private:
   int _num_nested_signal;
 
+  DEBUG_ONLY(bool _suspendible_thread;)
+
  public:
   void enter_signal_handler() { _num_nested_signal++; }
   void leave_signal_handler() { _num_nested_signal--; }
   bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
 
+#ifdef ASSERT
+  void set_suspendible_thread() {
+    _suspendible_thread = true;
+  }
+
+  void clear_suspendible_thread() {
+    _suspendible_thread = false;
+  }
+
+  bool is_suspendible_thread() { return _suspendible_thread; }
+#endif
+
  private:
   // Active_handles points to a block of handles
   JNIHandleBlock* _active_handles;
--- a/src/share/vm/runtime/timer.cpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/runtime/timer.cpp	Mon May 11 16:30:26 2015 +0200
@@ -28,9 +28,12 @@
 #include "utilities/ostream.hpp"
 
 double TimeHelper::counter_to_seconds(jlong counter) {
-  double count = (double) counter;
   double freq  = (double) os::elapsed_frequency();
-  return counter/freq;
+  return counter / freq;
+}
+
+double TimeHelper::counter_to_millis(jlong counter) {
+  return counter_to_seconds(counter) * 1000.0;
 }
 
 void elapsedTimer::add(elapsedTimer t) {
@@ -56,8 +59,7 @@
 }
 
 jlong elapsedTimer::milliseconds() const {
-  jlong ticks_per_ms = os::elapsed_frequency() / 1000;
-  return _counter / ticks_per_ms;
+  return TimeHelper::counter_to_millis(_counter);
 }
 
 jlong elapsedTimer::active_ticks() const {
@@ -86,11 +88,8 @@
 
 jlong TimeStamp::milliseconds() const {
   assert(is_updated(), "must not be clear");
-
   jlong new_count = os::elapsed_counter();
-  jlong count = new_count - _counter;
-  jlong ticks_per_ms = os::elapsed_frequency() / 1000;
-  return count / ticks_per_ms;
+  return TimeHelper::counter_to_millis(new_count - _counter);
 }
 
 jlong TimeStamp::ticks_since_update() const {
--- a/src/share/vm/runtime/timer.hpp	Fri May 08 13:25:11 2015 -0400
+++ b/src/share/vm/runtime/timer.hpp	Mon May 11 16:30:26 2015 +0200
@@ -123,6 +123,7 @@
 class TimeHelper {
  public:
   static double counter_to_seconds(jlong counter);
+  static double counter_to_millis(jlong counter);
 };
 
 #endif // SHARE_VM_RUNTIME_TIMER_HPP