--- old/src/hotspot/share/gc/g1/dirtyCardQueue.cpp 2018-11-27 15:42:57.514070445 -0500 +++ new/src/hotspot/share/gc/g1/dirtyCardQueue.cpp 2018-11-27 15:42:57.250056351 -0500 @@ -31,6 +31,7 @@ #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/workgroup.hpp" #include "runtime/atomic.hpp" +#include "runtime/flags/flagSetting.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.inline.hpp" @@ -148,14 +149,9 @@ void DirtyCardQueueSet::initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator, - int process_completed_threshold, - int max_completed_queue, Mutex* lock, bool init_free_ids) { - PtrQueueSet::initialize(cbl_mon, - allocator, - process_completed_threshold, - max_completed_queue); + PtrQueueSet::initialize(cbl_mon, allocator); _shared_dirty_card_queue.set_lock(lock); if (init_free_ids) { _free_ids = new FreeIdSet(num_par_ids(), _cbl_mon); @@ -334,13 +330,11 @@ // Iterate over all the threads, if we find a partial log add it to // the global list of logs. Temporarily turn off the limit on the number // of outstanding buffers. - int save_max_completed_queue = _max_completed_queue; - _max_completed_queue = max_jint; assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); + SizeTFlagSetting local_max(_max_completed_buffers, + MaxCompletedBuffersUnlimited); for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) { concatenate_log(G1ThreadLocalData::dirty_card_queue(t)); } concatenate_log(_shared_dirty_card_queue); - // Restore the completed buffer queue limit. - _max_completed_queue = save_max_completed_queue; } --- old/src/hotspot/share/gc/g1/dirtyCardQueue.hpp 2018-11-27 15:42:58.438119774 -0500 +++ new/src/hotspot/share/gc/g1/dirtyCardQueue.hpp 2018-11-27 15:42:58.162105040 -0500 @@ -119,8 +119,6 @@ void initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator, - int process_completed_threshold, - int max_completed_queue, Mutex* lock, bool init_free_ids = false); --- old/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-11-27 15:42:59.362169104 -0500 +++ new/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-11-27 15:42:59.090154582 -0500 @@ -1659,20 +1659,17 @@ G1SATBProcessCompletedThreshold, G1SATBBufferEnqueueingThresholdPercent, Shared_SATB_Q_lock); + - // process_completed_threshold and max_completed_queue are updated + // process_completed_buffers_threshold and max_completed_buffers are updated // later, based on the concurrent refinement object. G1BarrierSet::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, &bs->dirty_card_queue_buffer_allocator(), - -1, // temp. never trigger - -1, // temp. no limit Shared_DirtyCardQ_lock, true); // init_free_ids dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon, &bs->dirty_card_queue_buffer_allocator(), - -1, // never trigger processing - -1, // no limit on length Shared_DirtyCardQ_lock); // Create the hot card cache. @@ -1783,8 +1780,8 @@ { DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); - dcqs.set_process_completed_threshold((int)concurrent_refine()->yellow_zone()); - dcqs.set_max_completed_queue((int)concurrent_refine()->red_zone()); + dcqs.set_process_completed_buffers_threshold(concurrent_refine()->yellow_zone()); + dcqs.set_max_completed_buffers(concurrent_refine()->red_zone()); } // Here we allocate the dummy HeapRegion that is required by the --- old/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp 2018-11-27 15:43:00.330220781 -0500 +++ new/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp 2018-11-27 15:43:00.062206474 -0500 @@ -144,7 +144,7 @@ STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2)); const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort); const size_t max_green_zone = max_yellow_zone / 2; -const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue. +const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_buffers. STATIC_ASSERT(max_yellow_zone <= max_red_zone); // Range check assertions for green zone values. @@ -386,21 +386,22 @@ // Change the barrier params if (max_num_threads() == 0) { // Disable dcqs notification when there are no threads to notify. - dcqs.set_process_completed_threshold(INT_MAX); + dcqs.set_process_completed_buffers_threshold(DirtyCardQueueSet::ProcessCompletedBuffersThresholdNever); } else { // Worker 0 is the primary; wakeup is via dcqs notification. STATIC_ASSERT(max_yellow_zone <= INT_MAX); size_t activate = activation_threshold(0); - dcqs.set_process_completed_threshold((int)activate); + dcqs.set_process_completed_buffers_threshold(activate); } - dcqs.set_max_completed_queue((int)red_zone()); + dcqs.set_max_completed_buffers(red_zone()); } size_t curr_queue_size = dcqs.completed_buffers_num(); - if (curr_queue_size >= yellow_zone()) { - dcqs.set_completed_queue_padding(curr_queue_size); + if ((dcqs.max_completed_buffers() > 0) && + (curr_queue_size >= yellow_zone())) { + dcqs.set_completed_buffers_padding(curr_queue_size); } else { - dcqs.set_completed_queue_padding(0); + dcqs.set_completed_buffers_padding(0); } dcqs.notify_if_necessary(); } @@ -433,8 +434,8 @@ // that means that the transition period after the evacuation pause has ended. // Since the value written to the DCQS is the same for all threads, there is no // need to synchronize. - if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= yellow_zone()) { - dcqs.set_completed_queue_padding(0); + if (dcqs.completed_buffers_padding() > 0 && curr_buffer_num <= yellow_zone()) { + dcqs.set_completed_buffers_padding(0); } maybe_activate_more_threads(worker_id, curr_buffer_num); --- old/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp 2018-11-27 15:43:01.270270964 -0500 +++ new/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp 2018-11-27 15:43:00.998256443 -0500 @@ -37,12 +37,12 @@ void G1SATBMarkQueueSet::initialize(G1CollectedHeap* g1h, Monitor* cbl_mon, BufferNode::Allocator* allocator, - int process_completed_threshold, + size_t process_completed_buffers_threshold, uint buffer_enqueue_threshold_percentage, Mutex* lock) { SATBMarkQueueSet::initialize(cbl_mon, allocator, - process_completed_threshold, + process_completed_buffers_threshold, buffer_enqueue_threshold_percentage, lock); _g1h = g1h; --- old/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.hpp 2018-11-27 15:43:02.198320507 -0500 +++ new/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.hpp 2018-11-27 15:43:01.926305986 -0500 @@ -39,7 +39,7 @@ void initialize(G1CollectedHeap* g1h, Monitor* cbl_mon, BufferNode::Allocator* allocator, - int process_completed_threshold, + size_t process_completed_buffers_threshold, uint buffer_enqueue_threshold_percentage, Mutex* lock); --- old/src/hotspot/share/gc/shared/ptrQueue.cpp 2018-11-27 15:43:03.058366419 -0500 +++ new/src/hotspot/share/gc/shared/ptrQueue.cpp 2018-11-27 15:43:02.802352752 -0500 @@ -164,12 +164,12 @@ _completed_buffers_head(NULL), _completed_buffers_tail(NULL), _n_completed_buffers(0), - _process_completed_threshold(0), + _process_completed_buffers_threshold(ProcessCompletedBuffersThresholdNever), _process_completed(false), _all_active(false), _notify_when_complete(notify_when_complete), - _max_completed_queue(0), - _completed_queue_padding(0) + _max_completed_buffers(MaxCompletedBuffersUnlimited), + _completed_buffers_padding(0) {} PtrQueueSet::~PtrQueueSet() { @@ -179,12 +179,7 @@ } void PtrQueueSet::initialize(Monitor* cbl_mon, - BufferNode::Allocator* allocator, - int process_completed_threshold, - int max_completed_queue) { - _max_completed_queue = max_completed_queue; - _process_completed_threshold = process_completed_threshold; - _completed_queue_padding = 0; + BufferNode::Allocator* allocator) { assert(cbl_mon != NULL && allocator != NULL, "Init order issue?"); _cbl_mon = cbl_mon; _allocator = allocator; @@ -238,13 +233,14 @@ bool PtrQueueSet::process_or_enqueue_complete_buffer(BufferNode* node) { if (Thread::current()->is_Java_thread()) { - // We don't lock. It is fine to be epsilon-precise here. - if (_max_completed_queue == 0 || - (_max_completed_queue > 0 && - _n_completed_buffers >= _max_completed_queue + _completed_queue_padding)) { - bool b = mut_process_buffer(node); - if (b) { - // True here means that the buffer hasn't been deallocated and the caller may reuse it. + // If the number of buffers exceeds the limit, make this Java + // thread do the processing itself. We don't lock to access + // buffer count or padding; it is fine to be imprecise here. The + // add of padding could overflow, which is treated as unlimited. + size_t limit = _max_completed_buffers + _completed_buffers_padding; + if ((_n_completed_buffers > limit) && (limit >= _max_completed_buffers)) { + if (mut_process_buffer(node)) { + // Successfully processed; return true to allow buffer reuse. return true; } } @@ -267,8 +263,8 @@ } _n_completed_buffers++; - if (!_process_completed && _process_completed_threshold >= 0 && - _n_completed_buffers >= (size_t)_process_completed_threshold) { + if (!_process_completed && + (_n_completed_buffers > _process_completed_buffers_threshold)) { _process_completed = true; if (_notify_when_complete) { _cbl_mon->notify(); @@ -327,8 +323,7 @@ void PtrQueueSet::notify_if_necessary() { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - assert(_process_completed_threshold >= 0, "_process_completed_threshold is negative"); - if (_n_completed_buffers >= (size_t)_process_completed_threshold || _max_completed_queue == 0) { + if (_n_completed_buffers > _process_completed_buffers_threshold) { _process_completed = true; if (_notify_when_complete) _cbl_mon->notify(); --- old/src/hotspot/share/gc/shared/ptrQueue.hpp 2018-11-27 15:43:03.954414253 -0500 +++ new/src/hotspot/share/gc/shared/ptrQueue.hpp 2018-11-27 15:43:03.690400159 -0500 @@ -284,7 +284,7 @@ BufferNode* _completed_buffers_head; BufferNode* _completed_buffers_tail; size_t _n_completed_buffers; - int _process_completed_threshold; + size_t _process_completed_buffers_threshold; volatile bool _process_completed; bool _all_active; @@ -293,9 +293,9 @@ bool _notify_when_complete; // Maximum number of elements allowed on completed queue: after that, - // enqueuer does the work itself. Zero indicates no maximum. - int _max_completed_queue; - size_t _completed_queue_padding; + // enqueuer does the work itself. + size_t _max_completed_buffers; + size_t _completed_buffers_padding; size_t completed_buffers_list_length(); void assert_completed_buffer_list_len_correct_locked(); @@ -316,10 +316,7 @@ // Because of init-order concerns, we can't pass these as constructor // arguments. - void initialize(Monitor* cbl_mon, - BufferNode::Allocator* allocator, - int process_completed_threshold, - int max_completed_queue); + void initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator); public: @@ -350,18 +347,34 @@ } // Get/Set the number of completed buffers that triggers log processing. - void set_process_completed_threshold(int sz) { _process_completed_threshold = sz; } - int process_completed_threshold() const { return _process_completed_threshold; } + // Log processing should be done when the number of buffers exceeds the + // threshold. + void set_process_completed_buffers_threshold(size_t sz) { + _process_completed_buffers_threshold = sz; + } + size_t process_completed_buffers_threshold() const { + return _process_completed_buffers_threshold; + } + static const size_t ProcessCompletedBuffersThresholdNever = ~size_t(0); - size_t completed_buffers_num() { return _n_completed_buffers; } + size_t completed_buffers_num() const { return _n_completed_buffers; } void merge_bufferlists(PtrQueueSet* src); - void set_max_completed_queue(int m) { _max_completed_queue = m; } - int max_completed_queue() { return _max_completed_queue; } + void set_max_completed_buffers(size_t m) { + _max_completed_buffers = m; + } + size_t max_completed_buffers() const { + return _max_completed_buffers; + } + static const size_t MaxCompletedBuffersUnlimited = ~size_t(0); - void set_completed_queue_padding(size_t padding) { _completed_queue_padding = padding; } - size_t completed_queue_padding() { return _completed_queue_padding; } + void set_completed_buffers_padding(size_t padding) { + _completed_buffers_padding = padding; + } + size_t completed_buffers_padding() const { + return _completed_buffers_padding; + } // Notify the consumer if the number of buffers crossed the threshold void notify_if_necessary(); --- old/src/hotspot/share/gc/shared/satbMarkQueue.cpp 2018-11-27 15:43:04.894464435 -0500 +++ new/src/hotspot/share/gc/shared/satbMarkQueue.cpp 2018-11-27 15:43:04.626450128 -0500 @@ -113,10 +113,11 @@ void SATBMarkQueueSet::initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator, - int process_completed_threshold, + size_t process_completed_buffers_threshold, uint buffer_enqueue_threshold_percentage, Mutex* lock) { - PtrQueueSet::initialize(cbl_mon, allocator, process_completed_threshold, -1); + PtrQueueSet::initialize(cbl_mon, allocator); + set_process_completed_buffers_threshold(process_completed_buffers_threshold); _shared_satb_queue.set_lock(lock); assert(buffer_size() != 0, "buffer size not initialized"); // Minimum threshold of 1 ensures enqueuing of completely full buffers. --- old/src/hotspot/share/gc/shared/satbMarkQueue.hpp 2018-11-27 15:43:05.814513550 -0500 +++ new/src/hotspot/share/gc/shared/satbMarkQueue.hpp 2018-11-27 15:43:05.538498816 -0500 @@ -110,7 +110,7 @@ void initialize(Monitor* cbl_mon, BufferNode::Allocator* allocator, - int process_completed_threshold, + size_t process_completed_buffers_threshold, uint buffer_enqueue_threshold_percentage, Mutex* lock);