# HG changeset patch # User allwin # Date 1397214299 -7200 # Node ID dc33274a62488b12ee505c1578d845dcea122eca # Parent 536c66fc43d334b80394d7e0b8a8ce3b34f37332# Parent 1ab42446f14b0fafda72cee7e7ffb7b318d4555c Merge diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -958,7 +958,7 @@ // reset handle block __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), G3_scratch); - __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); + __ st(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); // handle exceptions (exception handling will handle unlocking!) diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -2687,7 +2687,7 @@ if (!is_critical_native) { // reset handle block __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), L5); - __ st_ptr(G0, L5, JNIHandleBlock::top_offset_in_bytes()); + __ st(G0, L5, JNIHandleBlock::top_offset_in_bytes()); __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), G3_scratch); check_forward_pending_exception(masm, G3_scratch); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1147,7 +1147,7 @@ // reset handle block __ ld_ptr(G2_thread, JavaThread::active_handles_offset(), G3_scratch); - __ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); + __ st(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes()); // If we have an oop result store it where it will be safe for any further gc // until we return now that we've released the handle it might be protected by diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1358,7 +1358,7 @@ // reset handle block __ movptr(t, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); // If result was an oop then unbox and save it in the frame { Label L; diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -162,7 +162,7 @@ "Number of milliseconds to wait before start calculating aborts " \ "for RTM locking") \ \ - experimental(bool, UseRTMXendForLockBusy, false, \ + experimental(bool, UseRTMXendForLockBusy, true, \ "Use RTM Xend instead of Xabort when lock busy") \ \ /* assembler */ \ diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1488,11 +1488,10 @@ movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort bind(L_rtm_retry); } - if (!UseRTMXendForLockBusy) { - movptr(tmpReg, Address(objReg, 0)); - testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased - jcc(Assembler::notZero, IsInflated); - } + movptr(tmpReg, Address(objReg, 0)); + testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased + jcc(Assembler::notZero, IsInflated); + if (PrintPreciseRTMLockingStatistics || profile_rtm) { Label L_noincrement; if (RTMTotalCountIncrRate > 1) { @@ -1512,10 +1511,7 @@ Register abort_status_Reg = tmpReg; // status of abort is stored in RAX if (UseRTMXendForLockBusy) { xend(); - movptr(tmpReg, Address(objReg, 0)); - testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased - jcc(Assembler::notZero, IsInflated); - movptr(abort_status_Reg, 0x1); // Set the abort status to 1 (as xabort does) + movptr(abort_status_Reg, 0x2); // Set the abort status to 2 (so we can retry) jmp(L_decrement_retry); } else { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -2266,7 +2266,7 @@ if (!is_critical_native) { // reset handle block __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + __ movl(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // Any exception pending? __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -2509,7 +2509,7 @@ if (!is_critical_native) { // reset handle block __ movptr(rcx, Address(r15_thread, JavaThread::active_handles_offset())); - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movl(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); } // pop our frame diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1287,7 +1287,7 @@ // reset handle block __ movptr(t, Address(thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // If result was an oop then unbox and save it in the frame { Label L; diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1259,7 +1259,7 @@ // reset handle block __ movptr(t, Address(r15_thread, JavaThread::active_handles_offset())); - __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + __ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); // If result is an oop unbox and store it in frame where gc will see it // and result handler will pick it up diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/classfile/symbolTable.cpp --- a/hotspot/src/share/vm/classfile/symbolTable.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -810,11 +810,11 @@ const int limit = the_table()->table_size(); assert(0 <= start_idx && start_idx <= limit, - err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx)); + err_msg("start_idx (%d) is out of bounds", start_idx)); assert(0 <= end_idx && end_idx <= limit, - err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx)); + err_msg("end_idx (%d) is out of bounds", end_idx)); assert(start_idx <= end_idx, - err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, + err_msg("Index ordering: start_idx=%d, end_idx=%d", start_idx, end_idx)); for (int i = start_idx; i < end_idx; i += 1) { @@ -833,11 +833,11 @@ const int limit = the_table()->table_size(); assert(0 <= start_idx && start_idx <= limit, - err_msg("start_idx (" INT32_FORMAT ") is out of bounds", start_idx)); + err_msg("start_idx (%d) is out of bounds", start_idx)); assert(0 <= end_idx && end_idx <= limit, - err_msg("end_idx (" INT32_FORMAT ") is out of bounds", end_idx)); + err_msg("end_idx (%d) is out of bounds", end_idx)); assert(start_idx <= end_idx, - err_msg("Index ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT, + err_msg("Index ordering: start_idx=%d, end_idx=%d", start_idx, end_idx)); for (int i = start_idx; i < end_idx; ++i) { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -57,10 +57,10 @@ _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC); - int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids(); + uint worker_id_offset = DirtyCardQueueSet::num_par_ids(); ConcurrentG1RefineThread *next = NULL; - for (int i = _n_threads - 1; i >= 0; i--) { + for (uint i = _n_threads - 1; i != UINT_MAX; i--) { ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i); assert(t != NULL, "Conc refine should have been created"); if (t->osthread() == NULL) { @@ -87,7 +87,7 @@ void ConcurrentG1Refine::stop() { if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { _threads[i]->stop(); } } @@ -96,7 +96,7 @@ void ConcurrentG1Refine::reinitialize_threads() { reset_threshold_step(); if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { _threads[i]->initialize(); } } @@ -104,7 +104,7 @@ ConcurrentG1Refine::~ConcurrentG1Refine() { if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { delete _threads[i]; } FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads, mtGC); @@ -113,7 +113,7 @@ void ConcurrentG1Refine::threads_do(ThreadClosure *tc) { if (_threads != NULL) { - for (int i = 0; i < _n_threads; i++) { + for (uint i = 0; i < _n_threads; i++) { tc->do_thread(_threads[i]); } } @@ -121,20 +121,20 @@ void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) { if (_threads != NULL) { - for (int i = 0; i < worker_thread_num(); i++) { + for (uint i = 0; i < worker_thread_num(); i++) { tc->do_thread(_threads[i]); } } } -int ConcurrentG1Refine::thread_num() { - int n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads +uint ConcurrentG1Refine::thread_num() { + uint n_threads = (G1ConcRefinementThreads > 0) ? G1ConcRefinementThreads : ParallelGCThreads; - return MAX2(n_threads, 1); + return MAX2(n_threads, 1); } void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { - for (int i = 0; i < _n_threads; ++i) { + for (uint i = 0; i < _n_threads; ++i) { _threads[i]->print_on(st); st->cr(); } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -39,8 +39,8 @@ class ConcurrentG1Refine: public CHeapObj { ConcurrentG1RefineThread** _threads; - int _n_threads; - int _n_worker_threads; + uint _n_threads; + uint _n_worker_threads; /* * The value of the update buffer queue length falls into one of 3 zones: * green, yellow, red. If the value is in [0, green) nothing is @@ -88,7 +88,7 @@ // The RS sampling thread ConcurrentG1RefineThread * sampling_thread() const; - static int thread_num(); + static uint thread_num(); void print_worker_threads_on(outputStream* st) const; @@ -100,8 +100,8 @@ int yellow_zone() const { return _yellow_zone; } int red_zone() const { return _red_zone; } - int total_thread_num() const { return _n_threads; } - int worker_thread_num() const { return _n_worker_threads; } + uint total_thread_num() const { return _n_threads; } + uint worker_thread_num() const { return _n_worker_threads; } int thread_threshold_step() const { return _thread_threshold_step; } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -33,7 +33,7 @@ ConcurrentG1RefineThread:: ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, - int worker_id_offset, int worker_id) : + uint worker_id_offset, uint worker_id) : ConcurrentGCThread(), _worker_id_offset(worker_id_offset), _worker_id(worker_id), diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -38,8 +38,8 @@ double _vtime_start; // Initial virtual time. double _vtime_accum; // Initial virtual time. - int _worker_id; - int _worker_id_offset; + uint _worker_id; + uint _worker_id_offset; // The refinement threads collection is linked list. A predecessor can activate a successor // when the number of the rset update buffer crosses a certain threshold. A successor @@ -71,7 +71,7 @@ virtual void run(); // Constructor ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, - int worker_id_offset, int worker_id); + uint worker_id_offset, uint worker_id); void initialize(); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -567,8 +567,8 @@ _root_regions.init(_g1h, this); if (ConcGCThreads > ParallelGCThreads) { - warning("Can't have more ConcGCThreads (" UINT32_FORMAT ") " - "than ParallelGCThreads (" UINT32_FORMAT ").", + warning("Can't have more ConcGCThreads (" UINTX_FORMAT ") " + "than ParallelGCThreads (" UINTX_FORMAT ").", ConcGCThreads, ParallelGCThreads); return; } @@ -1804,7 +1804,6 @@ class G1NoteEndOfConcMarkClosure : public HeapRegionClosure { G1CollectedHeap* _g1; - int _worker_num; size_t _max_live_bytes; uint _regions_claimed; size_t _freed_bytes; @@ -1817,10 +1816,9 @@ public: G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1, - int worker_num, FreeRegionList* local_cleanup_list, HRRSCleanupTask* hrrs_cleanup_task) : - _g1(g1), _worker_num(worker_num), + _g1(g1), _max_live_bytes(0), _regions_claimed(0), _freed_bytes(0), _claimed_region_time(0.0), _max_region_time(0.0), @@ -1893,7 +1891,7 @@ double start = os::elapsedTime(); FreeRegionList local_cleanup_list("Local Cleanup List"); HRRSCleanupTask hrrs_cleanup_task; - G1NoteEndOfConcMarkClosure g1_note_end(_g1h, worker_id, &local_cleanup_list, + G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list, &hrrs_cleanup_task); if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, @@ -2145,7 +2143,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); - _cleanup_list.verify_list(); + _cleanup_list.verify_optional(); FreeRegionList tmp_free_list("Tmp Free List"); if (G1ConcRegionFreeingVerbose) { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -34,12 +34,12 @@ bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, bool consume, - size_t worker_i) { + uint worker_i) { bool res = true; if (_buf != NULL) { res = apply_closure_to_buffer(cl, _buf, _index, _sz, consume, - (int) worker_i); + worker_i); if (res && consume) _index = _sz; } return res; @@ -49,7 +49,7 @@ void** buf, size_t index, size_t sz, bool consume, - int worker_i) { + uint worker_i) { if (cl == NULL) return true; for (size_t i = index; i < sz; i += oopSize) { int ind = byte_index_to_index((int)i); @@ -79,8 +79,8 @@ } // Determines how many mutator threads can process the buffers in parallel. -size_t DirtyCardQueueSet::num_par_ids() { - return os::processor_count(); +uint DirtyCardQueueSet::num_par_ids() { + return (uint)os::processor_count(); } void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, @@ -103,7 +103,7 @@ } void DirtyCardQueueSet::iterate_closure_all_threads(bool consume, - size_t worker_i) { + uint worker_i) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); for(JavaThread* t = Threads::first(); t; t = t->next()) { bool b = t->dirty_card_queue().apply_closure(_closure, consume); @@ -126,11 +126,11 @@ // We get the the number of any par_id that this thread // might have already claimed. - int worker_i = thread->get_claimed_par_id(); + uint worker_i = thread->get_claimed_par_id(); - // If worker_i is not -1 then the thread has already claimed + // If worker_i is not UINT_MAX then the thread has already claimed // a par_id. We make note of it using the already_claimed value - if (worker_i != -1) { + if (worker_i != UINT_MAX) { already_claimed = true; } else { @@ -142,7 +142,7 @@ } bool b = false; - if (worker_i != -1) { + if (worker_i != UINT_MAX) { b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0, _sz, true, worker_i); if (b) Atomic::inc(&_processed_buffers_mut); @@ -154,8 +154,8 @@ // we release the id _free_ids->release_par_id(worker_i); - // and set the claimed_id in the thread to -1 - thread->set_claimed_par_id(-1); + // and set the claimed_id in the thread to UINT_MAX + thread->set_claimed_par_id(UINT_MAX); } } return b; @@ -186,7 +186,7 @@ bool DirtyCardQueueSet:: apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - int worker_i, + uint worker_i, BufferNode* nd) { if (nd != NULL) { void **buf = BufferNode::make_buffer_from_node(nd); @@ -208,7 +208,7 @@ } bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - int worker_i, + uint worker_i, int stop_at, bool during_pause) { assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); @@ -218,7 +218,7 @@ return res; } -bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, +bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i, int stop_at, bool during_pause) { return apply_closure_to_completed_buffer(_closure, worker_i, diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -36,7 +36,7 @@ public: // Process the card whose card table entry is "card_ptr". If returns // "false", terminate the iteration early. - virtual bool do_card_ptr(jbyte* card_ptr, int worker_i = 0) = 0; + virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i = 0) = 0; }; // A ptrQueue whose elements are "oops", pointers to object heads. @@ -53,7 +53,7 @@ // deletes processed entries from logs. bool apply_closure(CardTableEntryClosure* cl, bool consume = true, - size_t worker_i = 0); + uint worker_i = 0); // Apply the closure to all elements of "buf", down to "index" // (inclusive.) If returns "false", then a closure application returned @@ -63,7 +63,7 @@ static bool apply_closure_to_buffer(CardTableEntryClosure* cl, void** buf, size_t index, size_t sz, bool consume = true, - int worker_i = 0); + uint worker_i = 0); void **get_buf() { return _buf;} void set_buf(void **buf) {_buf = buf;} size_t get_index() { return _index;} @@ -98,7 +98,7 @@ // The number of parallel ids that can be claimed to allow collector or // mutator threads to do card-processing work. - static size_t num_par_ids(); + static uint num_par_ids(); static void handle_zero_index_for_thread(JavaThread* t); @@ -115,7 +115,7 @@ // change in the future.) If "consume" is true, processed entries are // discarded. void iterate_closure_all_threads(bool consume = true, - size_t worker_i = 0); + uint worker_i = 0); // If there exists some completed buffer, pop it, then apply the // registered closure to all its elements, nulling out those elements @@ -124,7 +124,7 @@ // but is only partially completed before a "yield" happens, the // partially completed buffer (with its processed elements set to NULL) // is returned to the completed buffer set, and this call returns false. - bool apply_closure_to_completed_buffer(int worker_i = 0, + bool apply_closure_to_completed_buffer(uint worker_i = 0, int stop_at = 0, bool during_pause = false); @@ -136,13 +136,13 @@ // partially completed buffer (with its processed elements set to NULL) // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - int worker_i = 0, + uint worker_i = 0, int stop_at = 0, bool during_pause = false); // Helper routine for the above. bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - int worker_i, + uint worker_i, BufferNode* nd); BufferNode* get_completed_buffer(int stop_at); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -304,26 +304,26 @@ if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) { guarantee(entry > N_words, err_msg("Should be in logarithmic region - " - "entry: " UINT32_FORMAT ", " - "_array->offset_array(c): " UINT32_FORMAT ", " - "N_words: " UINT32_FORMAT, - entry, _array->offset_array(c), N_words)); + "entry: %u, " + "_array->offset_array(c): %u, " + "N_words: %u", + (uint)entry, (uint)_array->offset_array(c), (uint)N_words)); } size_t backskip = BlockOffsetArray::entry_to_cards_back(entry); size_t landing_card = c - backskip; guarantee(landing_card >= (start_card - 1), "Inv"); if (landing_card >= start_card) { guarantee(_array->offset_array(landing_card) <= entry, - err_msg("Monotonicity - landing_card offset: " UINT32_FORMAT ", " - "entry: " UINT32_FORMAT, - _array->offset_array(landing_card), entry)); + err_msg("Monotonicity - landing_card offset: %u, " + "entry: %u", + (uint)_array->offset_array(landing_card), (uint)entry)); } else { guarantee(landing_card == start_card - 1, "Tautology"); // Note that N_words is the maximum offset value guarantee(_array->offset_array(landing_card) <= N_words, - err_msg("landing card offset: " UINT32_FORMAT ", " - "N_words: " UINT32_FORMAT, - _array->offset_array(landing_card), N_words)); + err_msg("landing card offset: %u, " + "N_words: %u", + (uint)_array->offset_array(landing_card), (uint)N_words)); } } } @@ -554,21 +554,20 @@ (_array->offset_array(orig_index) > 0 && _array->offset_array(orig_index) <= N_words), err_msg("offset array should have been set - " - "orig_index offset: " UINT32_FORMAT ", " + "orig_index offset: %u, " "blk_start: " PTR_FORMAT ", " "boundary: " PTR_FORMAT, - _array->offset_array(orig_index), + (uint)_array->offset_array(orig_index), blk_start, boundary)); for (size_t j = orig_index + 1; j <= end_index; j++) { assert(_array->offset_array(j) > 0 && _array->offset_array(j) <= (u_char) (N_words+BlockOffsetArray::N_powers-1), err_msg("offset array should have been set - " - UINT32_FORMAT " not > 0 OR " - UINT32_FORMAT " not <= " UINT32_FORMAT, - _array->offset_array(j), - _array->offset_array(j), - (u_char) (N_words+BlockOffsetArray::N_powers-1))); + "%u not > 0 OR %u not <= %u", + (uint) _array->offset_array(j), + (uint) _array->offset_array(j), + (uint) (N_words+BlockOffsetArray::N_powers-1))); } #endif } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -146,8 +146,8 @@ void check_offset(size_t offset, const char* msg) const { assert(offset <= N_words, err_msg("%s - " - "offset: " UINT32_FORMAT", N_words: " UINT32_FORMAT, - msg, offset, N_words)); + "offset: " SIZE_FORMAT", N_words: %u", + msg, offset, (uint)N_words)); } // Bounds checking accessors: diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -102,7 +102,7 @@ ConcurrentG1Refine* cg1r) : _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) {} - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); // This path is executed by the concurrent refine or mutator threads, // concurrently, and so we do not care if card_ptr contains references @@ -131,7 +131,7 @@ { for (int i = 0; i < 256; i++) _histo[i] = 0; } - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { _calls++; unsigned char* ujb = (unsigned char*)card_ptr; @@ -160,7 +160,7 @@ RedirtyLoggedCardTableEntryClosure() : _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {} - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { _calls++; *card_ptr = 0; @@ -1288,7 +1288,7 @@ print_heap_before_gc(); trace_heap_before_gc(gc_tracer); - size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + size_t metadata_prev_used = MetaspaceAux::used_bytes(); verify_region_sets_optional(); @@ -2314,7 +2314,7 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, DirtyCardQueue* into_cset_dcq, bool concurrent, - int worker_i) { + uint worker_i) { // Clean cards in the hot card cache G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache(); hot_card_cache->drain(worker_i, g1_rem_set(), into_cset_dcq); @@ -2843,7 +2843,7 @@ // Given the id of a worker, obtain or calculate a suitable // starting region for iterating over the current collection set. -HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) { +HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) { assert(get_gc_time_stamp() > 0, "should have been updated by now"); HeapRegion* result = NULL; @@ -5103,7 +5103,7 @@ OopClosure* scan_non_heap_roots, OopsInHeapRegionClosure* scan_rs, G1KlassScanClosure* scan_klasses, - int worker_i) { + uint worker_i) { // First scan the strong roots double ext_roots_start = os::elapsedTime(); @@ -5207,10 +5207,10 @@ ~G1StringSymbolTableUnlinkTask() { guarantee(!_process_strings || !_do_in_parallel || StringTable::parallel_claimed_index() >= _initial_string_table_size, - err_msg("claim value "INT32_FORMAT" after unlink less than initial string table size "INT32_FORMAT, + err_msg("claim value %d after unlink less than initial string table size %d", StringTable::parallel_claimed_index(), _initial_string_table_size)); guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, - err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT, + err_msg("claim value %d after unlink less than initial symbol table size %d", SymbolTable::parallel_claimed_index(), _initial_symbol_table_size)); } @@ -5275,7 +5275,7 @@ class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure { public: - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { *card_ptr = CardTableModRefBS::dirty_card_val(); return true; } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -845,7 +845,7 @@ OopClosure* scan_non_heap_roots, OopsInHeapRegionClosure* scan_rs, G1KlassScanClosure* scan_klasses, - int worker_i); + uint worker_i); // Notifies all the necessary spaces that the committed space has // been updated (either expanded or shrunk). It should be called @@ -1139,7 +1139,7 @@ void iterate_dirty_card_closure(CardTableEntryClosure* cl, DirtyCardQueue* into_cset_dcq, - bool concurrent, int worker_i); + bool concurrent, uint worker_i); // The shared block offset table array. G1BlockOffsetSharedArray* bot_shared() const { return _bot_shared; } @@ -1370,7 +1370,7 @@ // Given the id of a worker, obtain or calculate a suitable // starting region for iterating over the current collection set. - HeapRegion* start_cset_region_for_worker(int worker_i); + HeapRegion* start_cset_region_for_worker(uint worker_i); // This is a convenience method that is used by the // HeapRegionIterator classes to calculate the starting region for diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1204,7 +1204,7 @@ (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc; if (full) { - _metaspace_used_bytes_before_gc = MetaspaceAux::allocated_used_bytes(); + _metaspace_used_bytes_before_gc = MetaspaceAux::used_bytes(); } } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -147,7 +147,7 @@ void WorkerDataArray::verify() { for (uint i = 0; i < _length; i++) { assert(_data[i] != _uninitialized, - err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf", + err_msg("Invalid data for worker %u, data: %lf, uninitialized: %lf", i, (double)_data[i], (double)_uninitialized)); } } @@ -246,8 +246,8 @@ LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); } -void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) { - LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); +void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) { + LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %u]", str, value, workers); } double G1GCPhaseTimes::accounted_time_ms() { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -161,7 +161,7 @@ // Helper methods for detailed logging void print_stats(int level, const char* str, double value); - void print_stats(int level, const char* str, double value, int workers); + void print_stats(int level, const char* str, double value, uint workers); public: G1GCPhaseTimes(uint max_gc_threads); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -44,9 +44,9 @@ _hot_cache_idx = 0; // For refining the cards in the hot cache in parallel - int n_workers = (ParallelGCThreads > 0 ? + uint n_workers = (ParallelGCThreads > 0 ? _g1h->workers()->total_workers() : 1); - _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / n_workers); + _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers); _hot_cache_par_claimed_idx = 0; _card_counts.initialize(); @@ -89,7 +89,7 @@ return res; } -void G1HotCardCache::drain(int worker_i, +void G1HotCardCache::drain(uint worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq) { if (!default_use_cache()) { @@ -122,8 +122,8 @@ // RSet updating while within an evacuation pause. // In this case worker_i should be the id of a GC worker thread assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint"); - assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), - err_msg("incorrect worker id: "INT32_FORMAT, worker_i)); + assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), + err_msg("incorrect worker id: %u", worker_i)); into_cset_dcq->enqueue(card_ptr); } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -99,7 +99,7 @@ // Refine the cards that have delayed as a result of // being in the cache. - void drain(int worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq); + void drain(uint worker_i, G1RemSet* g1rs, DirtyCardQueue* into_cset_dcq); // Set up for parallel processing of the cards in the hot cache void reset_hot_cache_claimed_index() { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -234,14 +234,14 @@ HeapRegion* _from; OopsInHeapRegionClosure* _push_ref_cl; bool _record_refs_into_cset; - int _worker_i; + uint _worker_i; public: G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, G1RemSet* rs, OopsInHeapRegionClosure* push_ref_cl, bool record_refs_into_cset, - int worker_i = 0); + uint worker_i = 0); void set_from(HeapRegion* from) { assert(from != NULL, "from region must be non-NULL"); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -113,14 +113,14 @@ G1SATBCardTableModRefBS *_ct_bs; double _strong_code_root_scan_time_sec; - int _worker_i; + uint _worker_i; int _block_size; bool _try_claimed; public: ScanRSClosure(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i) : + uint worker_i) : _oc(oc), _code_root_cl(code_root_cl), _strong_code_root_scan_time_sec(0.0), @@ -162,7 +162,7 @@ void printCard(HeapRegion* card_region, size_t card_index, HeapWord* card_start) { - gclog_or_tty->print_cr("T %d Region [" PTR_FORMAT ", " PTR_FORMAT ") " + gclog_or_tty->print_cr("T %u Region [" PTR_FORMAT ", " PTR_FORMAT ") " "RS names card %p: " "[" PTR_FORMAT ", " PTR_FORMAT ")", _worker_i, @@ -241,7 +241,7 @@ void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i) { + uint worker_i) { double rs_time_start = os::elapsedTime(); HeapRegion *startRegion = _g1->start_cset_region_for_worker(worker_i); @@ -274,13 +274,13 @@ DirtyCardQueue* into_cset_dcq) : _g1rs(g1h->g1_rem_set()), _into_cset_dcq(into_cset_dcq) {} - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { // The only time we care about recording cards that // contain references that point into the collection set // is during RSet updating within an evacuation pause. // In this case worker_i should be the id of a GC worker thread. assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); + assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); if (_g1rs->refine_card(card_ptr, worker_i, true)) { // 'card_ptr' contains references that point into the collection @@ -295,7 +295,7 @@ } }; -void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) { +void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) { double start = os::elapsedTime(); // Apply the given closure to all remaining log entries. RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); @@ -320,14 +320,14 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i) { + uint worker_i) { #if CARD_REPEAT_HISTO ct_freq_update_histo_and_reset(); #endif // We cache the value of 'oc' closure into the appropriate slot in the // _cset_rs_update_cl for this worker - assert(worker_i < (int)n_workers(), "sanity"); + assert(worker_i < n_workers(), "sanity"); _cset_rs_update_cl[worker_i] = oc; // A DirtyCardQueue that is used to hold cards containing references @@ -399,7 +399,7 @@ _g1(g1), _ct_bs(bs) { } - bool do_card_ptr(jbyte* card_ptr, int worker_i) { + bool do_card_ptr(jbyte* card_ptr, uint worker_i) { // Construct the region representing the card. HeapWord* start = _ct_bs->addr_for(card_ptr); // And find the region containing it. @@ -543,7 +543,7 @@ G1RemSet* rs, OopsInHeapRegionClosure* push_ref_cl, bool record_refs_into_cset, - int worker_i) : + uint worker_i) : _g1(g1h), _g1_rem_set(rs), _from(NULL), _record_refs_into_cset(record_refs_into_cset), _push_ref_cl(push_ref_cl), _worker_i(worker_i) { } @@ -552,7 +552,7 @@ // into the collection set, if we're checking for such references; // false otherwise. -bool G1RemSet::refine_card(jbyte* card_ptr, int worker_i, +bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i, bool check_for_refs_into_cset) { // If the card is no longer dirty, nothing to do. diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -97,7 +97,7 @@ // In the sequential case this param will be ignored. void oops_into_collection_set_do(OopsInHeapRegionClosure* blk, CodeBlobToOopClosure* code_root_cl, - int worker_i); + uint worker_i); // Prepare for and cleanup after an oops_into_collection_set_do // call. Must call each of these once before and after (in sequential @@ -109,9 +109,9 @@ void scanRS(OopsInHeapRegionClosure* oc, CodeBlobToOopClosure* code_root_cl, - int worker_i); + uint worker_i); - void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i); + void updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i); CardTableModRefBS* ct_bs() { return _ct_bs; } size_t cardsScanned() { return _total_cards_scanned; } @@ -138,7 +138,7 @@ // if the given card contains oops that have references into the // current collection set. virtual bool refine_card(jbyte* card_ptr, - int worker_i, + uint worker_i, bool check_for_refs_into_cset); // Print accumulated summary info from the start of the VM. @@ -171,12 +171,12 @@ class UpdateRSOopClosure: public ExtendedOopClosure { HeapRegion* _from; G1RemSet* _rs; - int _worker_i; + uint _worker_i; template void do_oop_work(T* p); public: - UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) : + UpdateRSOopClosure(G1RemSet* rs, uint worker_i = 0) : _from(NULL), _rs(rs), _worker_i(worker_i) {} diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -390,7 +390,7 @@ void FromCardCache::print(outputStream* out) { for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) { for (uint j = 0; j < _max_regions; j++) { - out->print_cr("_from_card_cache["UINT32_FORMAT"]["UINT32_FORMAT"] = "INT32_FORMAT".", + out->print_cr("_from_card_cache[%u][%u] = %d.", i, j, at(i, j)); } } @@ -430,7 +430,7 @@ int from_card = (int)(uintptr_t(from) >> CardTableModRefBS::card_shift); if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = "INT32_FORMAT")", + gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)", hr()->bottom(), from_card, FromCardCache::at((uint)tid, cur_hrs_ind)); } @@ -853,13 +853,13 @@ // This can be done by either mutator threads together with the // concurrent refinement threads or GC threads. uint HeapRegionRemSet::num_par_rem_sets() { - return (uint)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); + return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), (uint)ParallelGCThreads); } HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr) : _bosa(bosa), - _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #"UINT32_FORMAT, hr->hrs_index()), true), + _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrs_index()), true), _code_roots(), _other_regions(hr, &_m) { reset_for_par_iteration(); } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -30,7 +30,7 @@ inline void HeapRegionSetBase::add(HeapRegion* hr) { check_mt_safety(); assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u")); - assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); + assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked")); _count.increment(1u, hr->capacity()); hr->set_containing_set(this); @@ -40,7 +40,7 @@ inline void HeapRegionSetBase::remove(HeapRegion* hr) { check_mt_safety(); verify_region(hr); - assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked")); + assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked")); hr->set_containing_set(NULL); assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition")); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -290,7 +290,7 @@ shared_satb_queue()->apply_closure_and_empty(_closure); } -void SATBMarkQueueSet::par_iterate_closure_all_threads(int worker) { +void SATBMarkQueueSet::par_iterate_closure_all_threads(uint worker) { SharedHeap* sh = SharedHeap::heap(); int parity = sh->strong_roots_parity(); @@ -315,7 +315,7 @@ } bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par, - int worker) { + uint worker) { BufferNode* nd = NULL; { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -84,7 +84,7 @@ // Utility function to support sequential and parallel versions. If // "par" is true, then "worker" is the par thread id; if "false", worker // is ignored. - bool apply_closure_to_completed_buffer_work(bool par, int worker); + bool apply_closure_to_completed_buffer_work(bool par, uint worker); #ifdef ASSERT void dump_active_states(bool expected_active); @@ -124,7 +124,7 @@ // be called serially and at a safepoint. void iterate_closure_all_threads(); // Parallel version of the above. - void par_iterate_closure_all_threads(int worker); + void par_iterate_closure_all_threads(uint worker); // If there exists some completed buffer, pop it, then apply the // registered closure to all its elements, and return true. If no @@ -133,7 +133,7 @@ return apply_closure_to_completed_buffer_work(false, 0); } // Parallel version of the above. - bool par_apply_closure_to_completed_buffer(int worker) { + bool par_apply_closure_to_completed_buffer(uint worker) { return apply_closure_to_completed_buffer_work(true, worker); } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -184,7 +184,7 @@ size_t prev_used = heap->used(); // Capture metadata size before collection for sizing. - size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + size_t metadata_prev_used = MetaspaceAux::used_bytes(); // For PrintGCDetails size_t old_gen_prev_used = old_gen->used_in_bytes(); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -928,7 +928,7 @@ _heap_used = heap->used(); _young_gen_used = heap->young_gen()->used_in_bytes(); _old_gen_used = heap->old_gen()->used_in_bytes(); - _metadata_used = MetaspaceAux::allocated_used_bytes(); + _metadata_used = MetaspaceAux::used_bytes(); }; size_t heap_used() const { return _heap_used; } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -62,16 +62,16 @@ }; class MetaspaceSizes : public StackObj { - size_t _capacity; + size_t _committed; size_t _used; size_t _reserved; public: - MetaspaceSizes() : _capacity(0), _used(0), _reserved(0) {} - MetaspaceSizes(size_t capacity, size_t used, size_t reserved) : - _capacity(capacity), _used(used), _reserved(reserved) {} + MetaspaceSizes() : _committed(0), _used(0), _reserved(0) {} + MetaspaceSizes(size_t committed, size_t used, size_t reserved) : + _committed(committed), _used(used), _reserved(reserved) {} - size_t capacity() const { return _capacity; } + size_t committed() const { return _committed; } size_t used() const { return _used; } size_t reserved() const { return _reserved; } }; diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -258,7 +258,7 @@ static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) { TraceStructMetaspaceSizes meta_sizes; - meta_sizes.set_capacity(sizes.capacity()); + meta_sizes.set_committed(sizes.committed()); meta_sizes.set_used(sizes.used()); meta_sizes.set_reserved(sizes.reserved()); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/gc_interface/collectedHeap.cpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -85,16 +85,16 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { const MetaspaceSizes meta_space( - MetaspaceAux::allocated_capacity_bytes(), - MetaspaceAux::allocated_used_bytes(), + MetaspaceAux::committed_bytes(), + MetaspaceAux::used_bytes(), MetaspaceAux::reserved_bytes()); const MetaspaceSizes data_space( - MetaspaceAux::allocated_capacity_bytes(Metaspace::NonClassType), - MetaspaceAux::allocated_used_bytes(Metaspace::NonClassType), + MetaspaceAux::committed_bytes(Metaspace::NonClassType), + MetaspaceAux::used_bytes(Metaspace::NonClassType), MetaspaceAux::reserved_bytes(Metaspace::NonClassType)); const MetaspaceSizes class_space( - MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType), - MetaspaceAux::allocated_used_bytes(Metaspace::ClassType), + MetaspaceAux::committed_bytes(Metaspace::ClassType), + MetaspaceAux::used_bytes(Metaspace::ClassType), MetaspaceAux::reserved_bytes(Metaspace::ClassType)); const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary = diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/memory/collectorPolicy.cpp --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -257,6 +257,12 @@ assert(_min_gen0_size % _gen_alignment == 0, "_min_gen0_size alignment"); assert(_initial_gen0_size % _gen_alignment == 0, "_initial_gen0_size alignment"); assert(_max_gen0_size % _gen_alignment == 0, "_max_gen0_size alignment"); + assert(_min_gen0_size <= bound_minus_alignment(_min_gen0_size, _min_heap_byte_size), + "Ergonomics made minimum young generation larger than minimum heap"); + assert(_initial_gen0_size <= bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size), + "Ergonomics made initial young generation larger than initial heap"); + assert(_max_gen0_size <= bound_minus_alignment(_max_gen0_size, _max_heap_byte_size), + "Ergonomics made maximum young generation lager than maximum heap"); } void TwoGenerationCollectorPolicy::assert_size_info() { @@ -267,6 +273,9 @@ assert(_max_gen1_size % _gen_alignment == 0, "_max_gen1_size alignment"); assert(_initial_gen1_size % _gen_alignment == 0, "_initial_gen1_size alignment"); assert(_max_heap_byte_size <= (_max_gen0_size + _max_gen1_size), "Total maximum heap sizes must be sum of generation maximum sizes"); + assert(_min_gen0_size + _min_gen1_size <= _min_heap_byte_size, "Minimum generation sizes exceed minimum heap size"); + assert(_initial_gen0_size + _initial_gen1_size == _initial_heap_byte_size, "Initial generation sizes should match initial heap size"); + assert(_max_gen0_size + _max_gen1_size == _max_heap_byte_size, "Maximum generation sizes should match maximum heap size"); } #endif // ASSERT @@ -303,20 +312,26 @@ } } + // Make sure NewSize allows an old generation to fit even if set on the command line + if (FLAG_IS_CMDLINE(NewSize) && NewSize >= _initial_heap_byte_size) { + warning("NewSize was set larger than initial heap size, will use initial heap size."); + NewSize = bound_minus_alignment(NewSize, _initial_heap_byte_size); + } + // Now take the actual NewSize into account. We will silently increase NewSize // if the user specified a smaller or unaligned value. - smallest_new_size = MAX2(smallest_new_size, (uintx)align_size_down(NewSize, _gen_alignment)); - if (smallest_new_size != NewSize) { + uintx bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize); + bounded_new_size = MAX2(smallest_new_size, (uintx)align_size_down(bounded_new_size, _gen_alignment)); + if (bounded_new_size != NewSize) { // Do not use FLAG_SET_ERGO to update NewSize here, since this will override // if NewSize was set on the command line or not. This information is needed // later when setting the initial and minimum young generation size. - NewSize = smallest_new_size; + NewSize = bounded_new_size; } + _min_gen0_size = smallest_new_size; _initial_gen0_size = NewSize; if (!FLAG_IS_DEFAULT(MaxNewSize)) { - uintx min_new_size = MAX2(_gen_alignment, _min_gen0_size); - if (MaxNewSize >= MaxHeapSize) { // Make sure there is room for an old generation uintx smaller_max_new_size = MaxHeapSize - _gen_alignment; @@ -330,8 +345,8 @@ FLAG_SET_ERGO(uintx, NewSize, MaxNewSize); _initial_gen0_size = NewSize; } - } else if (MaxNewSize < min_new_size) { - FLAG_SET_ERGO(uintx, MaxNewSize, min_new_size); + } else if (MaxNewSize < _initial_gen0_size) { + FLAG_SET_ERGO(uintx, MaxNewSize, _initial_gen0_size); } else if (!is_size_aligned(MaxNewSize, _gen_alignment)) { FLAG_SET_ERGO(uintx, MaxNewSize, align_size_down(MaxNewSize, _gen_alignment)); } @@ -361,7 +376,9 @@ GenCollectorPolicy::initialize_flags(); if (!is_size_aligned(OldSize, _gen_alignment)) { - FLAG_SET_ERGO(uintx, OldSize, align_size_down(OldSize, _gen_alignment)); + // Setting OldSize directly to preserve information about the possible + // setting of OldSize on the command line. + OldSize = align_size_down(OldSize, _gen_alignment); } if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(MaxHeapSize)) { @@ -400,6 +417,20 @@ } } + // Update NewSize, if possible, to avoid sizing gen0 to small when only + // OldSize is set on the command line. + if (FLAG_IS_CMDLINE(OldSize) && !FLAG_IS_CMDLINE(NewSize)) { + if (OldSize < _initial_heap_byte_size) { + size_t new_size = _initial_heap_byte_size - OldSize; + // Need to compare against the flag value for max since _max_gen0_size + // might not have been set yet. + if (new_size >= _min_gen0_size && new_size <= MaxNewSize) { + FLAG_SET_ERGO(uintx, NewSize, new_size); + _initial_gen0_size = NewSize; + } + } + } + always_do_update_barrier = UseConcMarkSweepGC; DEBUG_ONLY(TwoGenerationCollectorPolicy::assert_flags();) @@ -441,57 +472,37 @@ // Given the maximum gen0 size, determine the initial and // minimum gen0 sizes. - if (_max_heap_byte_size == _min_heap_byte_size) { - // The maximum and minimum heap sizes are the same so the generations - // minimum and initial must be the same as its maximum. - _min_gen0_size = max_new_size; - _initial_gen0_size = max_new_size; - _max_gen0_size = max_new_size; + if (_max_heap_byte_size == _initial_heap_byte_size) { + // The maxium and initial heap sizes are the same so the generation's + // initial size must be the same as it maximum size. Use NewSize as the + // size if set on command line. + size_t fixed_young_size = FLAG_IS_CMDLINE(NewSize) ? NewSize : max_new_size; + + _initial_gen0_size = fixed_young_size; + _max_gen0_size = fixed_young_size; + + // Also update the minimum size if min == initial == max. + if (_max_heap_byte_size == _min_heap_byte_size) { + _min_gen0_size = fixed_young_size; + } } else { size_t desired_new_size = 0; if (FLAG_IS_CMDLINE(NewSize)) { - // If NewSize is set on the command line, we must use it as - // the initial size and it also makes sense to use it as the - // lower limit. - _min_gen0_size = NewSize; - desired_new_size = NewSize; - max_new_size = MAX2(max_new_size, NewSize); - } else if (FLAG_IS_ERGO(NewSize)) { - // If NewSize is set ergonomically, we should use it as a lower - // limit, but use NewRatio to calculate the initial size. - _min_gen0_size = NewSize; + // If NewSize is set on the command line, we should use it as + // the initial size, but make sure it is within the heap bounds. desired_new_size = - MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); - max_new_size = MAX2(max_new_size, NewSize); + MIN2(max_new_size, bound_minus_alignment(NewSize, _initial_heap_byte_size)); + _min_gen0_size = bound_minus_alignment(desired_new_size, _min_heap_byte_size); } else { - // For the case where NewSize is the default, use NewRatio - // to size the minimum and initial generation sizes. - // Use the default NewSize as the floor for these values. If - // NewRatio is overly large, the resulting sizes can be too small. - _min_gen0_size = MAX2(scale_by_NewRatio_aligned(_min_heap_byte_size), NewSize); + // For the case where NewSize is not set on the command line, use + // NewRatio to size the initial generation size. Use the current + // NewSize as the floor, because if NewRatio is overly large, the resulting + // size can be too small. desired_new_size = - MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize); + MIN2(max_new_size, MAX2(scale_by_NewRatio_aligned(_initial_heap_byte_size), NewSize)); } - - assert(_min_gen0_size > 0, "Sanity check"); _initial_gen0_size = desired_new_size; _max_gen0_size = max_new_size; - - // At this point the desirable initial and minimum sizes have been - // determined without regard to the maximum sizes. - - // Bound the sizes by the corresponding overall heap sizes. - _min_gen0_size = bound_minus_alignment(_min_gen0_size, _min_heap_byte_size); - _initial_gen0_size = bound_minus_alignment(_initial_gen0_size, _initial_heap_byte_size); - _max_gen0_size = bound_minus_alignment(_max_gen0_size, _max_heap_byte_size); - - // At this point all three sizes have been checked against the - // maximum sizes but have not been checked for consistency among the three. - - // Final check min <= initial <= max - _min_gen0_size = MIN2(_min_gen0_size, _max_gen0_size); - _initial_gen0_size = MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size); - _min_gen0_size = MIN2(_min_gen0_size, _initial_gen0_size); } // Write back to flags if necessary. @@ -512,33 +523,6 @@ DEBUG_ONLY(GenCollectorPolicy::assert_size_info();) } -// Call this method during the sizing of the gen1 to make -// adjustments to gen0 because of gen1 sizing policy. gen0 initially has -// the most freedom in sizing because it is done before the -// policy for gen1 is applied. Once gen1 policies have been applied, -// there may be conflicts in the shape of the heap and this method -// is used to make the needed adjustments. The application of the -// policies could be more sophisticated (iterative for example) but -// keeping it simple also seems a worthwhile goal. -bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, - size_t* gen1_size_ptr, - const size_t heap_size) { - bool result = false; - - if ((*gen0_size_ptr + *gen1_size_ptr) > heap_size) { - uintx smallest_new_size = young_gen_size_lower_bound(); - if ((heap_size < (*gen0_size_ptr + _min_gen1_size)) && - (heap_size >= _min_gen1_size + smallest_new_size)) { - // Adjust gen0 down to accommodate _min_gen1_size - *gen0_size_ptr = align_size_down_bounded(heap_size - _min_gen1_size, _gen_alignment); - result = true; - } else { - *gen1_size_ptr = align_size_down_bounded(heap_size - *gen0_size_ptr, _gen_alignment); - } - } - return result; -} - // Minimum sizes of the generations may be different than // the initial sizes. An inconsistency is permitted here // in the total size that can be specified explicitly by @@ -564,57 +548,64 @@ // with the overall heap size). In either case make // the minimum, maximum and initial sizes consistent // with the gen0 sizes and the overall heap sizes. - _min_gen1_size = MAX2(_min_heap_byte_size - _min_gen0_size, _gen_alignment); - _initial_gen1_size = MAX2(_initial_heap_byte_size - _initial_gen0_size, _gen_alignment); + _min_gen1_size = _gen_alignment; + _initial_gen1_size = MIN2(_max_gen1_size, MAX2(_initial_heap_byte_size - _initial_gen0_size, _min_gen1_size)); // _max_gen1_size has already been made consistent above FLAG_SET_ERGO(uintx, OldSize, _initial_gen1_size); } else { - // OldSize has been explicitly set on the command line. Use the - // OldSize and then determine the consequences. - _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size); - _initial_gen1_size = OldSize; - + // OldSize has been explicitly set on the command line. Use it + // for the initial size but make sure the minimum allow a young + // generation to fit as well. // If the user has explicitly set an OldSize that is inconsistent // with other command line flags, issue a warning. // The generation minimums and the overall heap minimum should // be within one generation alignment. - if ((_min_gen1_size + _min_gen0_size + _gen_alignment) < _min_heap_byte_size) { - warning("Inconsistency between minimum heap size and minimum " - "generation sizes: using minimum heap = " SIZE_FORMAT, - _min_heap_byte_size); - } if (OldSize > _max_gen1_size) { warning("Inconsistency between maximum heap size and maximum " - "generation sizes: using maximum heap = " SIZE_FORMAT - " -XX:OldSize flag is being ignored", - _max_heap_byte_size); + "generation sizes: using maximum heap = " SIZE_FORMAT + " -XX:OldSize flag is being ignored", + _max_heap_byte_size); + FLAG_SET_ERGO(uintx, OldSize, _max_gen1_size); } - // If there is an inconsistency between the OldSize and the minimum and/or - // initial size of gen0, since OldSize was explicitly set, OldSize wins. - if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, _min_heap_byte_size)) { - if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " - SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, - _min_gen0_size, _initial_gen0_size, _max_gen0_size); - } + + _min_gen1_size = MIN2(OldSize, _min_heap_byte_size - _min_gen0_size); + _initial_gen1_size = OldSize; + } + + // The initial generation sizes should match the initial heap size, + // if not issue a warning and resize the generations. This behavior + // differs from JDK8 where the generation sizes have higher priority + // than the initial heap size. + if ((_initial_gen1_size + _initial_gen0_size) != _initial_heap_byte_size) { + warning("Inconsistency between generation sizes and heap size, resizing " + "the generations to fit the heap."); + + size_t desired_gen0_size = _initial_heap_byte_size - _initial_gen1_size; + if (_initial_heap_byte_size < _initial_gen1_size) { + // Old want all memory, use minimum for young and rest for old + _initial_gen0_size = _min_gen0_size; + _initial_gen1_size = _initial_heap_byte_size - _min_gen0_size; + } else if (desired_gen0_size > _max_gen0_size) { + // Need to increase both young and old generation + _initial_gen0_size = _max_gen0_size; + _initial_gen1_size = _initial_heap_byte_size - _max_gen0_size; + } else if (desired_gen0_size < _min_gen0_size) { + // Need to decrease both young and old generation + _initial_gen0_size = _min_gen0_size; + _initial_gen1_size = _initial_heap_byte_size - _min_gen0_size; + } else { + // The young generation boundaries allow us to only update the + // young generation. + _initial_gen0_size = desired_gen0_size; } - // The same as above for the old gen initial size. - if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size, - _initial_heap_byte_size)) { - if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 " - SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, - _min_gen0_size, _initial_gen0_size, _max_gen0_size); - } + + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " + SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, + _min_gen0_size, _initial_gen0_size, _max_gen0_size); } } - _min_gen1_size = MIN2(_min_gen1_size, _max_gen1_size); - - // Make sure that min gen1 <= initial gen1 <= max gen1. - _initial_gen1_size = MAX2(_initial_gen1_size, _min_gen1_size); - _initial_gen1_size = MIN2(_initial_gen1_size, _max_gen1_size); - // Write back to flags if necessary if (NewSize != _initial_gen0_size) { FLAG_SET_ERGO(uintx, NewSize, _initial_gen0_size); @@ -994,56 +985,88 @@ // verify that there are some basic rules for NewSize honored by the policies. class TestGenCollectorPolicy { public: - static void test() { + static void test_new_size() { size_t flag_value; save_flags(); - // Set some limits that makes the math simple. - FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M); - FLAG_SET_ERGO(uintx, InitialHeapSize, 120 * M); - Arguments::set_min_heap_size(40 * M); - // If NewSize is set on the command line, it should be used // for both min and initial young size if less than min heap. flag_value = 20 * M; + set_basic_flag_values(); FLAG_SET_CMDLINE(uintx, NewSize, flag_value); - verify_min(flag_value); - verify_initial(flag_value); + verify_gen0_min(flag_value); + + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, NewSize, flag_value); + verify_gen0_initial(flag_value); // If NewSize is set on command line, but is larger than the min // heap size, it should only be used for initial young size. flag_value = 80 * M; + set_basic_flag_values(); FLAG_SET_CMDLINE(uintx, NewSize, flag_value); - verify_initial(flag_value); + verify_gen0_initial(flag_value); // If NewSize has been ergonomically set, the collector policy // should use it for min but calculate the initial young size // using NewRatio. flag_value = 20 * M; + set_basic_flag_values(); FLAG_SET_ERGO(uintx, NewSize, flag_value); - verify_min(flag_value); - verify_scaled_initial(InitialHeapSize); + verify_gen0_min(flag_value); + + set_basic_flag_values(); + FLAG_SET_ERGO(uintx, NewSize, flag_value); + verify_scaled_gen0_initial(InitialHeapSize); restore_flags(); + } + + static void test_old_size() { + size_t flag_value; + + save_flags(); + + // If OldSize is set on the command line, it should be used + // for both min and initial old size if less than min heap. + flag_value = 20 * M; + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, OldSize, flag_value); + verify_gen1_min(flag_value); + + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, OldSize, flag_value); + verify_gen1_initial(flag_value); + + // If MaxNewSize is large, the maximum OldSize will be less than + // what's requested on the command line and it should be reset + // ergonomically. + flag_value = 30 * M; + set_basic_flag_values(); + FLAG_SET_CMDLINE(uintx, OldSize, flag_value); + FLAG_SET_CMDLINE(uintx, MaxNewSize, 170*M); + // Calculate what we expect the flag to be. + flag_value = MaxHeapSize - MaxNewSize; + verify_gen1_initial(flag_value); } - static void verify_min(size_t expected) { + static void verify_gen0_min(size_t expected) { MarkSweepPolicy msp; msp.initialize_all(); assert(msp.min_gen0_size() <= expected, err_msg("%zu > %zu", msp.min_gen0_size(), expected)); } - static void verify_initial(size_t expected) { + static void verify_gen0_initial(size_t expected) { MarkSweepPolicy msp; msp.initialize_all(); assert(msp.initial_gen0_size() == expected, err_msg("%zu != %zu", msp.initial_gen0_size(), expected)); } - static void verify_scaled_initial(size_t initial_heap_size) { + static void verify_scaled_gen0_initial(size_t initial_heap_size) { MarkSweepPolicy msp; msp.initialize_all(); @@ -1053,6 +1076,21 @@ err_msg("NewSize should have been set ergonomically to %zu, but was %zu", expected, NewSize)); } + static void verify_gen1_min(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.min_gen1_size() <= expected, err_msg("%zu > %zu", msp.min_gen1_size(), expected)); + } + + static void verify_gen1_initial(size_t expected) { + MarkSweepPolicy msp; + msp.initialize_all(); + + assert(msp.initial_gen1_size() == expected, err_msg("%zu != %zu", msp.initial_gen1_size(), expected)); + } + + private: static size_t original_InitialHeapSize; static size_t original_MaxHeapSize; @@ -1061,6 +1099,15 @@ static size_t original_NewSize; static size_t original_OldSize; + static void set_basic_flag_values() { + FLAG_SET_ERGO(uintx, MaxHeapSize, 180 * M); + FLAG_SET_ERGO(uintx, InitialHeapSize, 100 * M); + FLAG_SET_ERGO(uintx, OldSize, 4 * M); + FLAG_SET_ERGO(uintx, NewSize, 1 * M); + FLAG_SET_ERGO(uintx, MaxNewSize, 80 * M); + Arguments::set_min_heap_size(40 * M); + } + static void save_flags() { original_InitialHeapSize = InitialHeapSize; original_MaxHeapSize = MaxHeapSize; @@ -1088,7 +1135,11 @@ size_t TestGenCollectorPolicy::original_OldSize = 0; void TestNewSize_test() { - TestGenCollectorPolicy::test(); + TestGenCollectorPolicy::test_new_size(); +} + +void TestOldSize_test() { + TestGenCollectorPolicy::test_old_size(); } #endif diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/memory/collectorPolicy.hpp --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -248,13 +248,13 @@ // Compute max heap alignment. size_t compute_max_alignment(); - // Scale the base_size by NewRatio according to - // result = base_size / (NewRatio + 1) - // and align by min_alignment() - size_t scale_by_NewRatio_aligned(size_t base_size); + // Scale the base_size by NewRatio according to + // result = base_size / (NewRatio + 1) + // and align by min_alignment() + size_t scale_by_NewRatio_aligned(size_t base_size); - // Bound the value by the given maximum minus the min_alignment. - size_t bound_minus_alignment(size_t desired_size, size_t maximum_size); + // Bound the value by the given maximum minus the min_alignment. + size_t bound_minus_alignment(size_t desired_size, size_t maximum_size); public: GenCollectorPolicy(); @@ -335,10 +335,6 @@ virtual CollectorPolicy::Name kind() { return CollectorPolicy::TwoGenerationCollectorPolicyKind; } - - // Returns true if gen0 sizes were adjusted - bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - const size_t heap_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/memory/genCollectedHeap.cpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -374,7 +374,7 @@ ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); - const size_t metadata_prev_used = MetaspaceAux::allocated_used_bytes(); + const size_t metadata_prev_used = MetaspaceAux::used_bytes(); print_heap_before_gc(); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/memory/metaspace.cpp --- a/hotspot/src/share/vm/memory/metaspace.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/memory/metaspace.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1447,7 +1447,7 @@ uint current_shrink_factor = _shrink_factor; _shrink_factor = 0; - const size_t used_after_gc = MetaspaceAux::allocated_capacity_bytes(); + const size_t used_after_gc = MetaspaceAux::capacity_bytes(); const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC(); const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0; @@ -2538,8 +2538,8 @@ // MetaspaceAux -size_t MetaspaceAux::_allocated_capacity_words[] = {0, 0}; -size_t MetaspaceAux::_allocated_used_words[] = {0, 0}; +size_t MetaspaceAux::_capacity_words[] = {0, 0}; +size_t MetaspaceAux::_used_words[] = {0, 0}; size_t MetaspaceAux::free_bytes(Metaspace::MetadataType mdtype) { VirtualSpaceList* list = Metaspace::get_space_list(mdtype); @@ -2552,38 +2552,38 @@ void MetaspaceAux::dec_capacity(Metaspace::MetadataType mdtype, size_t words) { assert_lock_strong(SpaceManager::expand_lock()); - assert(words <= allocated_capacity_words(mdtype), + assert(words <= capacity_words(mdtype), err_msg("About to decrement below 0: words " SIZE_FORMAT - " is greater than _allocated_capacity_words[%u] " SIZE_FORMAT, - words, mdtype, allocated_capacity_words(mdtype))); - _allocated_capacity_words[mdtype] -= words; + " is greater than _capacity_words[%u] " SIZE_FORMAT, + words, mdtype, capacity_words(mdtype))); + _capacity_words[mdtype] -= words; } void MetaspaceAux::inc_capacity(Metaspace::MetadataType mdtype, size_t words) { assert_lock_strong(SpaceManager::expand_lock()); // Needs to be atomic - _allocated_capacity_words[mdtype] += words; + _capacity_words[mdtype] += words; } void MetaspaceAux::dec_used(Metaspace::MetadataType mdtype, size_t words) { - assert(words <= allocated_used_words(mdtype), + assert(words <= used_words(mdtype), err_msg("About to decrement below 0: words " SIZE_FORMAT - " is greater than _allocated_used_words[%u] " SIZE_FORMAT, - words, mdtype, allocated_used_words(mdtype))); + " is greater than _used_words[%u] " SIZE_FORMAT, + words, mdtype, used_words(mdtype))); // For CMS deallocation of the Metaspaces occurs during the // sweep which is a concurrent phase. Protection by the expand_lock() // is not enough since allocation is on a per Metaspace basis // and protected by the Metaspace lock. jlong minus_words = (jlong) - (jlong) words; - Atomic::add_ptr(minus_words, &_allocated_used_words[mdtype]); + Atomic::add_ptr(minus_words, &_used_words[mdtype]); } void MetaspaceAux::inc_used(Metaspace::MetadataType mdtype, size_t words) { - // _allocated_used_words tracks allocations for + // _used_words tracks allocations for // each piece of metadata. Those allocations are // generally done concurrently by different application // threads so must be done atomically. - Atomic::add_ptr(words, &_allocated_used_words[mdtype]); + Atomic::add_ptr(words, &_used_words[mdtype]); } size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) { @@ -2630,16 +2630,16 @@ size_t MetaspaceAux::capacity_bytes_slow() { #ifdef PRODUCT - // Use allocated_capacity_bytes() in PRODUCT instead of this function. + // Use capacity_bytes() in PRODUCT instead of this function. guarantee(false, "Should not call capacity_bytes_slow() in the PRODUCT"); #endif size_t class_capacity = capacity_bytes_slow(Metaspace::ClassType); size_t non_class_capacity = capacity_bytes_slow(Metaspace::NonClassType); - assert(allocated_capacity_bytes() == class_capacity + non_class_capacity, - err_msg("bad accounting: allocated_capacity_bytes() " SIZE_FORMAT + assert(capacity_bytes() == class_capacity + non_class_capacity, + err_msg("bad accounting: capacity_bytes() " SIZE_FORMAT " class_capacity + non_class_capacity " SIZE_FORMAT " class_capacity " SIZE_FORMAT " non_class_capacity " SIZE_FORMAT, - allocated_capacity_bytes(), class_capacity + non_class_capacity, + capacity_bytes(), class_capacity + non_class_capacity, class_capacity, non_class_capacity)); return class_capacity + non_class_capacity; @@ -2699,14 +2699,14 @@ "->" SIZE_FORMAT "(" SIZE_FORMAT ")", prev_metadata_used, - allocated_used_bytes(), + used_bytes(), reserved_bytes()); } else { gclog_or_tty->print(" " SIZE_FORMAT "K" "->" SIZE_FORMAT "K" "(" SIZE_FORMAT "K)", prev_metadata_used/K, - allocated_used_bytes()/K, + used_bytes()/K, reserved_bytes()/K); } @@ -2722,8 +2722,8 @@ "capacity " SIZE_FORMAT "K, " "committed " SIZE_FORMAT "K, " "reserved " SIZE_FORMAT "K", - allocated_used_bytes()/K, - allocated_capacity_bytes()/K, + used_bytes()/K, + capacity_bytes()/K, committed_bytes()/K, reserved_bytes()/K); @@ -2734,8 +2734,8 @@ "capacity " SIZE_FORMAT "K, " "committed " SIZE_FORMAT "K, " "reserved " SIZE_FORMAT "K", - allocated_used_bytes(ct)/K, - allocated_capacity_bytes(ct)/K, + used_bytes(ct)/K, + capacity_bytes(ct)/K, committed_bytes(ct)/K, reserved_bytes(ct)/K); } @@ -2837,42 +2837,42 @@ void MetaspaceAux::verify_capacity() { #ifdef ASSERT - size_t running_sum_capacity_bytes = allocated_capacity_bytes(); + size_t running_sum_capacity_bytes = capacity_bytes(); // For purposes of the running sum of capacity, verify against capacity size_t capacity_in_use_bytes = capacity_bytes_slow(); assert(running_sum_capacity_bytes == capacity_in_use_bytes, - err_msg("allocated_capacity_words() * BytesPerWord " SIZE_FORMAT + err_msg("capacity_words() * BytesPerWord " SIZE_FORMAT " capacity_bytes_slow()" SIZE_FORMAT, running_sum_capacity_bytes, capacity_in_use_bytes)); for (Metaspace::MetadataType i = Metaspace::ClassType; i < Metaspace:: MetadataTypeCount; i = (Metaspace::MetadataType)(i + 1)) { size_t capacity_in_use_bytes = capacity_bytes_slow(i); - assert(allocated_capacity_bytes(i) == capacity_in_use_bytes, - err_msg("allocated_capacity_bytes(%u) " SIZE_FORMAT + assert(capacity_bytes(i) == capacity_in_use_bytes, + err_msg("capacity_bytes(%u) " SIZE_FORMAT " capacity_bytes_slow(%u)" SIZE_FORMAT, - i, allocated_capacity_bytes(i), i, capacity_in_use_bytes)); + i, capacity_bytes(i), i, capacity_in_use_bytes)); } #endif } void MetaspaceAux::verify_used() { #ifdef ASSERT - size_t running_sum_used_bytes = allocated_used_bytes(); + size_t running_sum_used_bytes = used_bytes(); // For purposes of the running sum of used, verify against used size_t used_in_use_bytes = used_bytes_slow(); - assert(allocated_used_bytes() == used_in_use_bytes, - err_msg("allocated_used_bytes() " SIZE_FORMAT + assert(used_bytes() == used_in_use_bytes, + err_msg("used_bytes() " SIZE_FORMAT " used_bytes_slow()" SIZE_FORMAT, - allocated_used_bytes(), used_in_use_bytes)); + used_bytes(), used_in_use_bytes)); for (Metaspace::MetadataType i = Metaspace::ClassType; i < Metaspace:: MetadataTypeCount; i = (Metaspace::MetadataType)(i + 1)) { size_t used_in_use_bytes = used_bytes_slow(i); - assert(allocated_used_bytes(i) == used_in_use_bytes, - err_msg("allocated_used_bytes(%u) " SIZE_FORMAT + assert(used_bytes(i) == used_in_use_bytes, + err_msg("used_bytes(%u) " SIZE_FORMAT " used_bytes_slow(%u)" SIZE_FORMAT, - i, allocated_used_bytes(i), i, used_in_use_bytes)); + i, used_bytes(i), i, used_in_use_bytes)); } #endif } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/memory/metaspace.hpp --- a/hotspot/src/share/vm/memory/metaspace.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/memory/metaspace.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -280,11 +280,11 @@ // allocated to a Metaspace. This is used instead of // iterating over all the classloaders. One for each // type of Metadata - static size_t _allocated_capacity_words[Metaspace:: MetadataTypeCount]; - // Running sum of space in all Metachunks that have + static size_t _capacity_words[Metaspace:: MetadataTypeCount]; + // Running sum of space in all Metachunks that // are being used for metadata. One for each // type of Metadata. - static size_t _allocated_used_words[Metaspace:: MetadataTypeCount]; + static size_t _used_words[Metaspace:: MetadataTypeCount]; public: // Decrement and increment _allocated_capacity_words @@ -308,32 +308,32 @@ static size_t free_chunks_total_bytes(); static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype); - static size_t allocated_capacity_words(Metaspace::MetadataType mdtype) { - return _allocated_capacity_words[mdtype]; + static size_t capacity_words(Metaspace::MetadataType mdtype) { + return _capacity_words[mdtype]; } - static size_t allocated_capacity_words() { - return allocated_capacity_words(Metaspace::NonClassType) + - allocated_capacity_words(Metaspace::ClassType); + static size_t capacity_words() { + return capacity_words(Metaspace::NonClassType) + + capacity_words(Metaspace::ClassType); } - static size_t allocated_capacity_bytes(Metaspace::MetadataType mdtype) { - return allocated_capacity_words(mdtype) * BytesPerWord; + static size_t capacity_bytes(Metaspace::MetadataType mdtype) { + return capacity_words(mdtype) * BytesPerWord; } - static size_t allocated_capacity_bytes() { - return allocated_capacity_words() * BytesPerWord; + static size_t capacity_bytes() { + return capacity_words() * BytesPerWord; } - static size_t allocated_used_words(Metaspace::MetadataType mdtype) { - return _allocated_used_words[mdtype]; + static size_t used_words(Metaspace::MetadataType mdtype) { + return _used_words[mdtype]; } - static size_t allocated_used_words() { - return allocated_used_words(Metaspace::NonClassType) + - allocated_used_words(Metaspace::ClassType); + static size_t used_words() { + return used_words(Metaspace::NonClassType) + + used_words(Metaspace::ClassType); } - static size_t allocated_used_bytes(Metaspace::MetadataType mdtype) { - return allocated_used_words(mdtype) * BytesPerWord; + static size_t used_bytes(Metaspace::MetadataType mdtype) { + return used_words(mdtype) * BytesPerWord; } - static size_t allocated_used_bytes() { - return allocated_used_words() * BytesPerWord; + static size_t used_bytes() { + return used_words() * BytesPerWord; } static size_t free_bytes(); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/memory/metaspaceCounters.cpp --- a/hotspot/src/share/vm/memory/metaspaceCounters.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/memory/metaspaceCounters.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -66,7 +66,7 @@ MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL; size_t MetaspaceCounters::used() { - return MetaspaceAux::allocated_used_bytes(); + return MetaspaceAux::used_bytes(); } size_t MetaspaceCounters::capacity() { @@ -98,7 +98,7 @@ MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL; size_t CompressedClassSpaceCounters::used() { - return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); + return MetaspaceAux::used_bytes(Metaspace::ClassType); } size_t CompressedClassSpaceCounters::capacity() { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -3408,6 +3408,10 @@ ("purge: %s(%s): prev method @%d in version @%d is alive", method->name()->as_C_string(), method->signature()->as_C_string(), j, i)); + if (method->method_data() != NULL) { + // Clean out any weak method links + method->method_data()->clean_weak_method_links(); + } } } } @@ -3417,6 +3421,14 @@ ("purge: previous version stats: live=%d, deleted=%d", live_count, deleted_count)); } + + Array* methods = ik->methods(); + int num_methods = methods->length(); + for (int index2 = 0; index2 < num_methods; ++index2) { + if (methods->at(index2)->method_data() != NULL) { + methods->at(index2)->method_data()->clean_weak_method_links(); + } + } } // External interface for use during class unloading. diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/oops/methodData.cpp --- a/hotspot/src/share/vm/oops/methodData.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/oops/methodData.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1531,9 +1531,35 @@ } } -// Remove SpeculativeTrapData entries that reference an unloaded -// method -void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { +class CleanExtraDataClosure : public StackObj { +public: + virtual bool is_live(Method* m) = 0; +}; + +// Check for entries that reference an unloaded method +class CleanExtraDataKlassClosure : public CleanExtraDataClosure { +private: + BoolObjectClosure* _is_alive; +public: + CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {} + bool is_live(Method* m) { + return m->method_holder()->is_loader_alive(_is_alive); + } +}; + +// Check for entries that reference a redefined method +class CleanExtraDataMethodClosure : public CleanExtraDataClosure { +public: + CleanExtraDataMethodClosure() {} + bool is_live(Method* m) { + return m->on_stack(); + } +}; + + +// Remove SpeculativeTrapData entries that reference an unloaded or +// redefined method +void MethodData::clean_extra_data(CleanExtraDataClosure* cl) { DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); @@ -1544,7 +1570,7 @@ SpeculativeTrapData* data = new SpeculativeTrapData(dp); Method* m = data->method(); assert(m != NULL, "should have a method"); - if (!m->method_holder()->is_loader_alive(is_alive)) { + if (!cl->is_live(m)) { // "shift" accumulates the number of cells for dead // SpeculativeTrapData entries that have been seen so // far. Following entries must be shifted left by that many @@ -1575,9 +1601,9 @@ } } -// Verify there's no unloaded method referenced by a +// Verify there's no unloaded or redefined method referenced by a // SpeculativeTrapData entry -void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { +void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { #ifdef ASSERT DataLayout* dp = extra_data_base(); DataLayout* end = extra_data_limit(); @@ -1587,7 +1613,7 @@ case DataLayout::speculative_trap_data_tag: { SpeculativeTrapData* data = new SpeculativeTrapData(dp); Method* m = data->method(); - assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); + assert(m != NULL && cl->is_live(m), "Method should exist"); break; } case DataLayout::bit_data_tag: @@ -1613,6 +1639,19 @@ parameters->clean_weak_klass_links(is_alive); } - clean_extra_data(is_alive); - verify_extra_data_clean(is_alive); + CleanExtraDataKlassClosure cl(is_alive); + clean_extra_data(&cl); + verify_extra_data_clean(&cl); } + +void MethodData::clean_weak_method_links() { + for (ProfileData* data = first_data(); + is_valid(data); + data = next_data(data)) { + data->clean_weak_method_links(); + } + + CleanExtraDataMethodClosure cl; + clean_extra_data(&cl); + verify_extra_data_clean(&cl); +} diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/oops/methodData.hpp --- a/hotspot/src/share/vm/oops/methodData.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/oops/methodData.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -251,6 +251,9 @@ // GC support void clean_weak_klass_links(BoolObjectClosure* cl); + + // Redefinition support + void clean_weak_method_links(); }; @@ -506,6 +509,9 @@ // GC support virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {} + // Redefinition support + virtual void clean_weak_method_links() {} + // CI translation: ProfileData can represent both MethodDataOop data // as well as CIMethodData data. This function is provided for translating // an oop in a ProfileData to the ci equivalent. Generally speaking, @@ -1989,6 +1995,7 @@ // CC_INTERP_ONLY(class BytecodeInterpreter;) +class CleanExtraDataClosure; class MethodData : public Metadata { friend class VMStructs; @@ -2146,9 +2153,9 @@ static bool profile_parameters_jsr292_only(); static bool profile_all_parameters(); - void clean_extra_data(BoolObjectClosure* is_alive); + void clean_extra_data(CleanExtraDataClosure* cl); void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); - void verify_extra_data_clean(BoolObjectClosure* is_alive); + void verify_extra_data_clean(CleanExtraDataClosure* cl); public: static int header_size() { @@ -2440,6 +2447,8 @@ static bool profile_return_jsr292_only(); void clean_method_data(BoolObjectClosure* is_alive); + + void clean_weak_method_links(); }; #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -70,6 +70,7 @@ JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) { Compile* C = Compile::current(); + C->print_inlining_update(this); if (is_osr()) { // The JVMS for a OSR has a single argument (see its TypeFunc). @@ -126,6 +127,7 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { GraphKit kit(jvms); + kit.C->print_inlining_update(this); bool is_static = method()->is_static(); address target = is_static ? SharedRuntime::get_resolve_static_call_stub() : SharedRuntime::get_resolve_opt_virtual_call_stub(); @@ -178,6 +180,8 @@ GraphKit kit(jvms); Node* receiver = kit.argument(0); + kit.C->print_inlining_update(this); + if (kit.C->log() != NULL) { kit.C->log()->elem("virtual_call bci='%d'", jvms->bci()); } @@ -271,14 +275,13 @@ LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : DirectCallGenerator(method, true), _inline_cg(inline_cg) {} - virtual bool is_late_inline() const { return true; } + virtual bool is_late_inline() const { return true; } // Convert the CallStaticJava into an inline virtual void do_late_inline(); virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); - C->print_inlining_skip(this); // Record that this call site should be revisited once the main // parse is finished. @@ -296,10 +299,11 @@ virtual void print_inlining_late(const char* msg) { CallNode* call = call_node(); Compile* C = Compile::current(); - C->print_inlining_insert(this); + C->print_inlining_assert_ready(); C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg); + C->print_inlining_move_to(this); + C->print_inlining_update_delayed(this); } - }; void LateInlineCallGenerator::do_late_inline() { @@ -360,6 +364,10 @@ map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1)); } + C->print_inlining_assert_ready(); + + C->print_inlining_move_to(this); + // This check is done here because for_method_handle_inline() method // needs jvms for inlined state. if (!do_late_inline_check(jvms)) { @@ -367,8 +375,6 @@ return; } - C->print_inlining_insert(this); - CompileLog* log = C->log(); if (log != NULL) { log->head("late_inline method='%d'", log->identify(method())); @@ -388,7 +394,7 @@ C->set_default_node_notes(entry_nn); } - // Now perform the inling using the synthesized JVMState + // Now perform the inlining using the synthesized JVMState JVMState* new_jvms = _inline_cg->generate(jvms, NULL); if (new_jvms == NULL) return; // no change if (C->failing()) return; @@ -431,6 +437,7 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser); + if (_input_not_const) { // inlining won't be possible so no need to enqueue right now. call_node()->set_generator(this); @@ -439,17 +446,14 @@ } return new_jvms; } - - virtual void print_inlining_late(const char* msg) { - if (!_input_not_const) return; - LateInlineCallGenerator::print_inlining_late(msg); - } }; bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) { CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const); + Compile::current()->print_inlining_update_delayed(this); + if (!_input_not_const) { _attempt++; } @@ -479,8 +483,6 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); - C->print_inlining_skip(this); - C->add_string_late_inline(this); JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser); @@ -502,7 +504,6 @@ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { Compile *C = Compile::current(); - C->print_inlining_skip(this); C->add_boxing_late_inline(this); @@ -554,6 +555,8 @@ JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { Compile* C = Compile::current(); + C->print_inlining_update(this); + if (C->log() != NULL) { C->log()->elem("warm_call bci='%d'", jvms->bci()); } @@ -632,6 +635,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { GraphKit kit(jvms); + kit.C->print_inlining_update(this); PhaseGVN& gvn = kit.gvn(); // We need an explicit receiver null_check before checking its type. // We share a map with the caller, so his JVMS gets adjusted. @@ -779,6 +783,9 @@ assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); if (cg != NULL && cg->is_inline()) return cg; + } else { + const char* msg = "receiver not constant"; + if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); } } break; @@ -844,11 +851,13 @@ // provide us with a type speculative_receiver_type = receiver_type->speculative_type(); } - CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); if (cg != NULL && cg->is_inline()) return cg; + } else { + const char* msg = "member_name not constant"; + if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); } } break; @@ -904,6 +913,7 @@ if (kit.failing()) return NULL; // might happen because of NodeCountInliningCutoff + kit.C->print_inlining_update(this); SafePointNode* slow_map = NULL; JVMState* slow_jvms; if (slow_ctl != NULL) { @@ -1017,6 +1027,7 @@ JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { GraphKit kit(jvms); + kit.C->print_inlining_update(this); // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver). int nargs = method()->arg_size(); kit.inc_sp(nargs); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/opto/compile.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -662,6 +662,7 @@ _inlining_progress(false), _inlining_incrementally(false), _print_inlining_list(NULL), + _print_inlining_stream(NULL), _print_inlining_idx(0), _preserve_jvm_state(0) { C = this; @@ -723,9 +724,7 @@ PhaseGVN gvn(node_arena(), estimated_size); set_initial_gvn(&gvn); - if (print_inlining() || print_intrinsics()) { - _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); - } + print_inlining_init(); { // Scope for timing the parser TracePhase t3("parse", &_t_parser, true); @@ -967,6 +966,7 @@ _inlining_progress(false), _inlining_incrementally(false), _print_inlining_list(NULL), + _print_inlining_stream(NULL), _print_inlining_idx(0), _preserve_jvm_state(0), _allowed_reasons(0) { @@ -2023,6 +2023,8 @@ ResourceMark rm; int loop_opts_cnt; + print_inlining_reinit(); + NOT_PRODUCT( verify_graph_edges(); ) print_method(PHASE_AFTER_PARSING); @@ -3755,30 +3757,114 @@ } } -void Compile::dump_inlining() { +// The message about the current inlining is accumulated in +// _print_inlining_stream and transfered into the _print_inlining_list +// once we know whether inlining succeeds or not. For regular +// inlining, messages are appended to the buffer pointed by +// _print_inlining_idx in the _print_inlining_list. For late inlining, +// a new buffer is added after _print_inlining_idx in the list. This +// way we can update the inlining message for late inlining call site +// when the inlining is attempted again. +void Compile::print_inlining_init() { + if (print_inlining() || print_intrinsics()) { + _print_inlining_stream = new stringStream(); + _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); + } +} + +void Compile::print_inlining_reinit() { + if (print_inlining() || print_intrinsics()) { + // Re allocate buffer when we change ResourceMark + _print_inlining_stream = new stringStream(); + } +} + +void Compile::print_inlining_reset() { + _print_inlining_stream->reset(); +} + +void Compile::print_inlining_commit() { + assert(print_inlining() || print_intrinsics(), "PrintInlining off?"); + // Transfer the message from _print_inlining_stream to the current + // _print_inlining_list buffer and clear _print_inlining_stream. + _print_inlining_list->at(_print_inlining_idx).ss()->write(_print_inlining_stream->as_string(), _print_inlining_stream->size()); + print_inlining_reset(); +} + +void Compile::print_inlining_push() { + // Add new buffer to the _print_inlining_list at current position + _print_inlining_idx++; + _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer()); +} + +Compile::PrintInliningBuffer& Compile::print_inlining_current() { + return _print_inlining_list->at(_print_inlining_idx); +} + +void Compile::print_inlining_update(CallGenerator* cg) { if (print_inlining() || print_intrinsics()) { + if (!cg->is_late_inline()) { + if (print_inlining_current().cg() != NULL) { + print_inlining_push(); + } + print_inlining_commit(); + } else { + if (print_inlining_current().cg() != cg && + (print_inlining_current().cg() != NULL || + print_inlining_current().ss()->size() != 0)) { + print_inlining_push(); + } + print_inlining_commit(); + print_inlining_current().set_cg(cg); + } + } +} + +void Compile::print_inlining_move_to(CallGenerator* cg) { + // We resume inlining at a late inlining call site. Locate the + // corresponding inlining buffer so that we can update it. + if (print_inlining()) { + for (int i = 0; i < _print_inlining_list->length(); i++) { + if (_print_inlining_list->adr_at(i)->cg() == cg) { + _print_inlining_idx = i; + return; + } + } + ShouldNotReachHere(); + } +} + +void Compile::print_inlining_update_delayed(CallGenerator* cg) { + if (print_inlining()) { + assert(_print_inlining_stream->size() > 0, "missing inlining msg"); + assert(print_inlining_current().cg() == cg, "wrong entry"); + // replace message with new message + _print_inlining_list->at_put(_print_inlining_idx, PrintInliningBuffer()); + print_inlining_commit(); + print_inlining_current().set_cg(cg); + } +} + +void Compile::print_inlining_assert_ready() { + assert(!_print_inlining || _print_inlining_stream->size() == 0, "loosing data"); +} + +void Compile::dump_inlining() { + bool do_print_inlining = print_inlining() || print_intrinsics(); + if (do_print_inlining) { // Print inlining message for candidates that we couldn't inline - // for lack of space or non constant receiver + // for lack of space for (int i = 0; i < _late_inlines.length(); i++) { CallGenerator* cg = _late_inlines.at(i); - cg->print_inlining_late("live nodes > LiveNodeCountInliningCutoff"); - } - Unique_Node_List useful; - useful.push(root()); - for (uint next = 0; next < useful.size(); ++next) { - Node* n = useful.at(next); - if (n->is_Call() && n->as_Call()->generator() != NULL && n->as_Call()->generator()->call_node() == n) { - CallNode* call = n->as_Call(); - CallGenerator* cg = call->generator(); - cg->print_inlining_late("receiver not constant"); - } - uint max = n->len(); - for ( uint i = 0; i < max; ++i ) { - Node *m = n->in(i); - if ( m == NULL ) continue; - useful.push(m); + if (!cg->is_mh_late_inline()) { + const char* msg = "live nodes > LiveNodeCountInliningCutoff"; + if (do_print_inlining) { + cg->print_inlining_late(msg); + } } } + } + if (do_print_inlining) { for (int i = 0; i < _print_inlining_list->length(); i++) { tty->print(_print_inlining_list->adr_at(i)->ss()->as_string()); } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/opto/compile.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -416,6 +416,7 @@ void set_cg(CallGenerator* cg) { _cg = cg; } }; + stringStream* _print_inlining_stream; GrowableArray* _print_inlining_list; int _print_inlining_idx; @@ -433,33 +434,24 @@ void* _replay_inline_data; // Pointer to data loaded from file + void print_inlining_init(); + void print_inlining_reinit(); + void print_inlining_commit(); + void print_inlining_push(); + PrintInliningBuffer& print_inlining_current(); + public: outputStream* print_inlining_stream() const { - return _print_inlining_list->adr_at(_print_inlining_idx)->ss(); - } - - void print_inlining_skip(CallGenerator* cg) { - if (_print_inlining) { - _print_inlining_list->adr_at(_print_inlining_idx)->set_cg(cg); - _print_inlining_idx++; - _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer()); - } + assert(print_inlining() || print_intrinsics(), "PrintInlining off?"); + return _print_inlining_stream; } - void print_inlining_insert(CallGenerator* cg) { - if (_print_inlining) { - for (int i = 0; i < _print_inlining_list->length(); i++) { - if (_print_inlining_list->adr_at(i)->cg() == cg) { - _print_inlining_list->insert_before(i+1, PrintInliningBuffer()); - _print_inlining_idx = i+1; - _print_inlining_list->adr_at(i)->set_cg(NULL); - return; - } - } - ShouldNotReachHere(); - } - } + void print_inlining_update(CallGenerator* cg); + void print_inlining_update_delayed(CallGenerator* cg); + void print_inlining_move_to(CallGenerator* cg); + void print_inlining_assert_ready(); + void print_inlining_reset(); void print_inlining(ciMethod* method, int inline_level, int bci, const char* msg = NULL) { stringStream ss; diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/opto/doCall.cpp --- a/hotspot/src/share/vm/opto/doCall.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/opto/doCall.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -294,6 +294,8 @@ // There was no special inlining tactic, or it bailed out. // Use a more generic tactic, like a simple call. if (call_does_dispatch) { + const char* msg = "virtual call"; + if (PrintInlining) print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg); return CallGenerator::for_virtual_call(callee, vtable_index); } else { // Class Hierarchy Analysis or Type Profile reveals a unique target, @@ -396,6 +398,8 @@ // our contribution to it is cleaned up right here. kill_dead_locals(); + C->print_inlining_assert_ready(); + // Set frequently used booleans const bool is_virtual = bc() == Bytecodes::_invokevirtual; const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; @@ -531,7 +535,8 @@ // intrinsic was expecting to optimize. Should always be possible to // get a normal java call that may inline in that case cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false); - if ((new_jvms = cg->generate(jvms, this)) == NULL) { + new_jvms = cg->generate(jvms, this); + if (new_jvms == NULL) { guarantee(failing(), "call failed to generate: calls should work"); return; } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -620,6 +620,7 @@ } // Push the result from the inlined method onto the stack. kit.push_result(); + C->print_inlining_update(this); return kit.transfer_exceptions_into_jvms(); } @@ -637,6 +638,7 @@ } } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); + C->print_inlining_update(this); return NULL; } diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/prims/jni.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -3877,6 +3877,7 @@ void TestMetachunk_test(); void TestVirtualSpaceNode_test(); void TestNewSize_test(); +void TestOldSize_test(); void TestKlass_test(); void TestBitMap_test(); #if INCLUDE_ALL_GCS @@ -3903,6 +3904,7 @@ run_unit_test(AltHashing::test_alt_hash()); run_unit_test(test_loggc_filename()); run_unit_test(TestNewSize_test()); + run_unit_test(TestOldSize_test()); run_unit_test(TestKlass_test()); run_unit_test(TestBitMap_test()); #if INCLUDE_VM_STRUCTS diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -438,6 +438,30 @@ return (mh->queued_for_compilation() || nm != NULL); WB_END +class VM_WhiteBoxOperation : public VM_Operation { + public: + VM_WhiteBoxOperation() { } + VMOp_Type type() const { return VMOp_WhiteBoxOperation; } + bool allow_nested_vm_operations() const { return true; } +}; + +class AlwaysFalseClosure : public BoolObjectClosure { + public: + bool do_object_b(oop p) { return false; } +}; + +static AlwaysFalseClosure always_false; + +class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation { + public: + VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { } + void doit() { + _mdo->clean_method_data(&always_false); + } + private: + MethodData* _mdo; +}; + WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION(env); @@ -453,6 +477,8 @@ for (int i = 0; i < arg_count; i++) { mdo->set_arg_modified(i, 0); } + VM_WhiteBoxCleanMethodData op(mdo); + VMThread::execute(&op); } mh->clear_not_c1_compilable(); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1262,8 +1262,6 @@ } #endif if (is_virtual) { - nmethod* nm = callee_nm; - if (nm == NULL) CodeCache::find_blob(caller_frame.pc()); CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc()); if (inline_cache->is_clean()) { inline_cache->set_to_monomorphic(virtual_call_info); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -1394,8 +1394,8 @@ void JavaThread::initialize() { // Initialize fields - // Set the claimed par_id to -1 (ie not claiming any par_ids) - set_claimed_par_id(-1); + // Set the claimed par_id to UINT_MAX (ie not claiming any par_ids) + set_claimed_par_id(UINT_MAX); set_saved_exception_pc(NULL); set_threadObj(NULL); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/runtime/thread.hpp --- a/hotspot/src/share/vm/runtime/thread.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -1778,12 +1778,12 @@ void set_done_attaching_via_jni() { _jni_attach_state = _attached_via_jni; OrderAccess::fence(); } private: // This field is used to determine if a thread has claimed - // a par_id: it is -1 if the thread has not claimed a par_id; + // a par_id: it is UINT_MAX if the thread has not claimed a par_id; // otherwise its value is the par_id that has been claimed. - int _claimed_par_id; + uint _claimed_par_id; public: - int get_claimed_par_id() { return _claimed_par_id; } - void set_claimed_par_id(int id) { _claimed_par_id = id;} + uint get_claimed_par_id() { return _claimed_par_id; } + void set_claimed_par_id(uint id) { _claimed_par_id = id;} }; // Inline implementation of JavaThread::current diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/runtime/vm_operations.hpp --- a/hotspot/src/share/vm/runtime/vm_operations.hpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Fri Apr 11 13:04:59 2014 +0200 @@ -97,6 +97,7 @@ template(Exit) \ template(LinuxDllLoad) \ template(RotateGCLog) \ + template(WhiteBoxOperation) \ class VM_Operation: public CHeapObj { public: diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/services/memoryPool.cpp --- a/hotspot/src/share/vm/services/memoryPool.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/services/memoryPool.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -268,7 +268,7 @@ } size_t MetaspacePool::used_in_bytes() { - return MetaspaceAux::allocated_used_bytes(); + return MetaspaceAux::used_bytes(); } size_t MetaspacePool::calculate_max_size() const { @@ -280,7 +280,7 @@ MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { } size_t CompressedKlassSpacePool::used_in_bytes() { - return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); + return MetaspaceAux::used_bytes(Metaspace::ClassType); } MemoryUsage CompressedKlassSpacePool::get_memory_usage() { diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/trace/trace.xml --- a/hotspot/src/share/vm/trace/trace.xml Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/trace/trace.xml Fri Apr 11 13:04:59 2014 +0200 @@ -185,7 +185,7 @@ - + diff -r 536c66fc43d3 -r dc33274a6248 hotspot/src/share/vm/utilities/taskqueue.cpp --- a/hotspot/src/share/vm/utilities/taskqueue.cpp Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp Fri Apr 11 13:04:59 2014 +0200 @@ -239,8 +239,8 @@ #ifdef TRACESPINNING void ParallelTaskTerminator::print_termination_counts() { - gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT - " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT, + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %u" + " Total spins: %u Total peeks: %u", total_yields(), total_spins(), total_peeks()); diff -r 536c66fc43d3 -r dc33274a6248 hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Agent.java Fri Apr 11 13:04:59 2014 +0200 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.*; +import java.lang.instrument.*; +import java.lang.reflect.*; +import java.lang.management.ManagementFactory; +import com.sun.tools.attach.VirtualMachine; + +class A { + void m() { + } +} + +class B extends A { + void m() { + } +} + +class C extends A { + void m() { + } +} + +class Test { + + static public void m() throws Exception { + for (int i = 0; i < 20000; i++) { + m1(a); + } + for (int i = 0; i < 4; i++) { + m1(b); + } + } + + static boolean m1(A a) { + boolean res = Agent.m2(a); + return res; + } + + static public A a = new A(); + static public B b = new B(); + static public C c = new C(); +} + +public class Agent implements ClassFileTransformer { + + + static class MemoryChunk { + MemoryChunk other; + long[] array; + MemoryChunk(MemoryChunk other) { + other = other; + array = new long[1024 * 1024 * 1024]; + } + } + + static public boolean m2(A a) { + boolean res = false; + if (a.getClass() == B.class) { + a.m(); + } else { + res = true; + } + return res; + } + + static public void main(String[] args) throws Exception { + // Create speculative trap entries + Test.m(); + + String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); + int p = nameOfRunningVM.indexOf('@'); + String pid = nameOfRunningVM.substring(0, p); + + // Make the nmethod go away + for (int i = 0; i < 10; i++) { + System.gc(); + } + + // Redefine class + try { + VirtualMachine vm = VirtualMachine.attach(pid); + vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", ""); + vm.detach(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + Test.m(); + // GC will hit dead method pointer + for (int i = 0; i < 10; i++) { + System.gc(); + } + } + + public synchronized byte[] transform(final ClassLoader classLoader, + final String className, + Class classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer) { + System.out.println("Transforming class " + className); + return classfileBuffer; + } + + public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) { + + try { + instrumentation.retransformClasses(to_redefine); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception { + Agent transformer = new Agent(); + instrumentation.addTransformer(transformer, true); + + redefine(agentArgs, instrumentation, Test.class); + } +} diff -r 536c66fc43d3 -r dc33274a6248 hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Fri Apr 11 13:04:59 2014 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.PrintWriter; +import com.oracle.java.testlibrary.*; + +/* + * @test + * @bug 8038636 + * @library /testlibrary + * @build Agent + * @run main ClassFileInstaller Agent + * @run main Launcher + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent + */ +public class Launcher { + public static void main(String[] args) throws Exception { + + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Agent-Class: Agent"); + pw.println("Can-Retransform-Classes: true"); + pw.close(); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"}); + pb.start().waitFor(); + } +} diff -r 536c66fc43d3 -r dc33274a6248 hotspot/test/gc/g1/TestStringDeduplicationTools.java --- a/hotspot/test/gc/g1/TestStringDeduplicationTools.java Tue Apr 08 13:58:38 2014 -0400 +++ b/hotspot/test/gc/g1/TestStringDeduplicationTools.java Fri Apr 11 13:04:59 2014 +0200 @@ -310,7 +310,9 @@ } System.gc(); + System.out.println("Heap Memory Usage: " + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()); + System.out.println("Array Header Size: " + unsafe.ARRAY_CHAR_BASE_OFFSET); System.out.println("End: MemoryUsageTest"); } @@ -482,31 +484,40 @@ public static void testMemoryUsage() throws Exception { // Test that memory usage is reduced after deduplication OutputAnalyzer output; - final String usagePattern = "Heap Memory Usage: (\\d+)"; + final String heapMemoryUsagePattern = "Heap Memory Usage: (\\d+)"; + final String arrayHeaderSizePattern = "Array Header Size: (\\d+)"; // Run without deduplication output = MemoryUsageTest.run(false); output.shouldHaveExitValue(0); - final long memoryUsageWithoutDedup = Long.parseLong(output.firstMatch(usagePattern, 1)); + final long heapMemoryUsageWithoutDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1)); + final long arrayHeaderSizeWithoutDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1)); // Run with deduplication output = MemoryUsageTest.run(true); output.shouldHaveExitValue(0); - final long memoryUsageWithDedup = Long.parseLong(output.firstMatch(usagePattern, 1)); + final long heapMemoryUsageWithDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1)); + final long arrayHeaderSizeWithDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1)); + + // Sanity check to make sure one instance isn't using compressed class pointers and the other not + if (arrayHeaderSizeWithoutDedup != arrayHeaderSizeWithDedup) { + throw new Exception("Unexpected difference between array header sizes"); + } // Calculate expected memory usage with deduplication enabled. This calculation does // not take alignment and padding into account, so it's a conservative estimate. - final long sizeOfChar = 2; // bytes - final long bytesSaved = (LargeNumberOfStrings - 1) * (StringLength * sizeOfChar + unsafe.ARRAY_CHAR_BASE_OFFSET); - final long memoryUsageWithDedupExpected = memoryUsageWithoutDedup - bytesSaved; + final long sizeOfChar = unsafe.ARRAY_CHAR_INDEX_SCALE; + final long sizeOfCharArray = StringLength * sizeOfChar + arrayHeaderSizeWithoutDedup; + final long bytesSaved = (LargeNumberOfStrings - 1) * sizeOfCharArray; + final long heapMemoryUsageWithDedupExpected = heapMemoryUsageWithoutDedup - bytesSaved; System.out.println("Memory usage summary:"); - System.out.println(" memoryUsageWithoutDedup: " + memoryUsageWithoutDedup); - System.out.println(" memoryUsageWithDedup: " + memoryUsageWithDedup); - System.out.println(" memoryUsageWithDedupExpected: " + memoryUsageWithDedupExpected); + System.out.println(" heapMemoryUsageWithoutDedup: " + heapMemoryUsageWithoutDedup); + System.out.println(" heapMemoryUsageWithDedup: " + heapMemoryUsageWithDedup); + System.out.println(" heapMemoryUsageWithDedupExpected: " + heapMemoryUsageWithDedupExpected); - if (memoryUsageWithDedup > memoryUsageWithDedupExpected) { - throw new Exception("Unexpected memory usage, memoryUsageWithDedup should less or equal to memoryUsageWithDedupExpected"); + if (heapMemoryUsageWithDedup > heapMemoryUsageWithDedupExpected) { + throw new Exception("Unexpected memory usage, heapMemoryUsageWithDedup should be less or equal to heapMemoryUsageWithDedupExpected"); } } }