--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/runtime/task.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/runtime/thread.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/runtime/thread.hpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/runtime/timer.cpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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/hotspot/src/share/vm/runtime/timer.hpp Fri May 08 13:25:11 2015 -0400
+++ b/hotspot/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