8258142: Simplify G1RedirtyCardsQueue

Separate local redirty qset from redirty queue.

Reviewed-by: tschatzl, iwalulya
This commit is contained in:
Kim Barrett 2020-12-14 16:13:23 +00:00
parent e8c40bafa5
commit 1ff0f1673d
5 changed files with 47 additions and 63 deletions

View File

@ -199,6 +199,7 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
uint _worker_id; uint _worker_id;
G1RedirtyCardsLocalQueueSet _rdc_local_qset;
G1RedirtyCardsQueue _rdcq; G1RedirtyCardsQueue _rdcq;
UpdateLogBuffersDeferred _log_buffer_cl; UpdateLogBuffersDeferred _log_buffer_cl;
@ -206,10 +207,16 @@ public:
RemoveSelfForwardPtrHRClosure(G1RedirtyCardsQueueSet* rdcqs, uint worker_id) : RemoveSelfForwardPtrHRClosure(G1RedirtyCardsQueueSet* rdcqs, uint worker_id) :
_g1h(G1CollectedHeap::heap()), _g1h(G1CollectedHeap::heap()),
_worker_id(worker_id), _worker_id(worker_id),
_rdcq(rdcqs), _rdc_local_qset(rdcqs),
_rdcq(&_rdc_local_qset),
_log_buffer_cl(&_rdcq) { _log_buffer_cl(&_rdcq) {
} }
~RemoveSelfForwardPtrHRClosure() {
_rdcq.flush();
_rdc_local_qset.flush();
}
size_t remove_self_forward_ptr_by_walking_hr(HeapRegion* hr, size_t remove_self_forward_ptr_by_walking_hr(HeapRegion* hr,
bool during_concurrent_start) { bool during_concurrent_start) {
RemoveSelfForwardPtrObjClosure rspc(hr, RemoveSelfForwardPtrObjClosure rspc(hr,

View File

@ -58,7 +58,8 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
size_t optional_cset_length) size_t optional_cset_length)
: _g1h(g1h), : _g1h(g1h),
_task_queue(g1h->task_queue(worker_id)), _task_queue(g1h->task_queue(worker_id)),
_rdcq(rdcqs), _rdc_local_qset(rdcqs),
_rdcq(&_rdc_local_qset),
_ct(g1h->card_table()), _ct(g1h->card_table()),
_closures(NULL), _closures(NULL),
_plab_allocator(NULL), _plab_allocator(NULL),
@ -114,6 +115,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
size_t G1ParScanThreadState::flush(size_t* surviving_young_words) { size_t G1ParScanThreadState::flush(size_t* surviving_young_words) {
_rdcq.flush(); _rdcq.flush();
_rdc_local_qset.flush();
flush_numa_stats(); flush_numa_stats();
// Update allocation statistics. // Update allocation statistics.
_plab_allocator->flush_and_retire_stats(); _plab_allocator->flush_and_retire_stats();

View File

@ -48,6 +48,7 @@ class outputStream;
class G1ParScanThreadState : public CHeapObj<mtGC> { class G1ParScanThreadState : public CHeapObj<mtGC> {
G1CollectedHeap* _g1h; G1CollectedHeap* _g1h;
G1ScannerTasksQueue* _task_queue; G1ScannerTasksQueue* _task_queue;
G1RedirtyCardsLocalQueueSet _rdc_local_qset;
G1RedirtyCardsQueue _rdcq; G1RedirtyCardsQueue _rdcq;
G1CardTable* _ct; G1CardTable* _ct;
G1EvacuationRootClosures* _closures; G1EvacuationRootClosures* _closures;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,19 +30,21 @@
// G1RedirtyCardsQueueBase::LocalQSet // G1RedirtyCardsQueueBase::LocalQSet
G1RedirtyCardsQueueBase::LocalQSet::LocalQSet(G1RedirtyCardsQueueSet* shared_qset) : G1RedirtyCardsLocalQueueSet::G1RedirtyCardsLocalQueueSet(G1RedirtyCardsQueueSet* shared_qset) :
PtrQueueSet(shared_qset->allocator()), PtrQueueSet(shared_qset->allocator()),
_shared_qset(shared_qset), _shared_qset(shared_qset),
_buffers() _buffers()
{} {}
G1RedirtyCardsQueueBase::LocalQSet::~LocalQSet() { #ifdef ASSERT
G1RedirtyCardsLocalQueueSet::~G1RedirtyCardsLocalQueueSet() {
assert(_buffers._head == NULL, "unflushed qset"); assert(_buffers._head == NULL, "unflushed qset");
assert(_buffers._tail == NULL, "invariant"); assert(_buffers._tail == NULL, "invariant");
assert(_buffers._entry_count == 0, "invariant"); assert(_buffers._entry_count == 0, "invariant");
} }
#endif // ASSERT
void G1RedirtyCardsQueueBase::LocalQSet::enqueue_completed_buffer(BufferNode* node) { void G1RedirtyCardsLocalQueueSet::enqueue_completed_buffer(BufferNode* node) {
_buffers._entry_count += buffer_size() - node->index(); _buffers._entry_count += buffer_size() - node->index();
node->set_next(_buffers._head); node->set_next(_buffers._head);
_buffers._head = node; _buffers._head = node;
@ -51,26 +53,22 @@ void G1RedirtyCardsQueueBase::LocalQSet::enqueue_completed_buffer(BufferNode* no
} }
} }
G1BufferNodeList G1RedirtyCardsQueueBase::LocalQSet::take_all_completed_buffers() { void G1RedirtyCardsLocalQueueSet::flush() {
G1BufferNodeList result = _buffers; _shared_qset->add_bufferlist(_buffers);
_buffers = G1BufferNodeList(); _buffers = G1BufferNodeList();
return result;
}
void G1RedirtyCardsQueueBase::LocalQSet::flush() {
_shared_qset->merge_bufferlist(this);
} }
// G1RedirtyCardsQueue // G1RedirtyCardsQueue
G1RedirtyCardsQueue::G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset) : G1RedirtyCardsQueue::G1RedirtyCardsQueue(G1RedirtyCardsLocalQueueSet* qset) :
G1RedirtyCardsQueueBase(qset), // Init _local_qset before passing to PtrQueue. PtrQueue(qset, true /* always active */)
PtrQueue(&_local_qset, true /* active (always) */)
{} {}
#ifdef ASSERT
G1RedirtyCardsQueue::~G1RedirtyCardsQueue() { G1RedirtyCardsQueue::~G1RedirtyCardsQueue() {
flush(); assert(is_empty(), "unflushed queue");
} }
#endif // ASSERT
void G1RedirtyCardsQueue::handle_completed_buffer() { void G1RedirtyCardsQueue::handle_completed_buffer() {
enqueue_completed_buffer(); enqueue_completed_buffer();
@ -78,7 +76,6 @@ void G1RedirtyCardsQueue::handle_completed_buffer() {
void G1RedirtyCardsQueue::flush() { void G1RedirtyCardsQueue::flush() {
flush_impl(); flush_impl();
_local_qset.flush();
} }
// G1RedirtyCardsQueueSet // G1RedirtyCardsQueueSet
@ -134,13 +131,12 @@ void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) {
update_tail(node); update_tail(node);
} }
void G1RedirtyCardsQueueSet::merge_bufferlist(LocalQSet* src) { void G1RedirtyCardsQueueSet::add_bufferlist(const G1BufferNodeList& buffers) {
assert(_collecting, "precondition"); assert(_collecting, "precondition");
const G1BufferNodeList from = src->take_all_completed_buffers(); if (buffers._head != NULL) {
if (from._head != NULL) { assert(buffers._tail != NULL, "invariant");
assert(from._tail != NULL, "invariant"); Atomic::add(&_entry_count, buffers._entry_count);
Atomic::add(&_entry_count, from._entry_count); _list.prepend(*buffers._head, *buffers._tail);
_list.prepend(*from._head, *from._tail); update_tail(buffers._tail);
update_tail(from._tail);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -27,56 +27,36 @@
#include "gc/g1/g1BufferNodeList.hpp" #include "gc/g1/g1BufferNodeList.hpp"
#include "gc/shared/ptrQueue.hpp" #include "gc/shared/ptrQueue.hpp"
#include "memory/allocation.hpp"
#include "memory/padded.hpp" #include "memory/padded.hpp"
class G1CardTableEntryClosure;
class G1RedirtyCardsQueue;
class G1RedirtyCardsQueueSet; class G1RedirtyCardsQueueSet;
// Provide G1RedirtyCardsQueue with a thread-local qset. It provides an // Provide G1RedirtyCardsQueue with a thread-local qset. It provides an
// uncontended staging area for completed buffers, to be flushed to the // uncontended staging area for completed buffers, to be flushed to the
// shared qset en masse. Using the "base from member" idiom so the local // shared qset en masse.
// qset is constructed before being passed to the PtrQueue constructor. class G1RedirtyCardsLocalQueueSet : public PtrQueueSet {
class G1RedirtyCardsQueueBase { G1RedirtyCardsQueueSet* _shared_qset;
friend class G1RedirtyCardsQueue; G1BufferNodeList _buffers;
friend class G1RedirtyCardsQueueSet;
class LocalQSet : public PtrQueueSet { public:
G1RedirtyCardsQueueSet* _shared_qset; G1RedirtyCardsLocalQueueSet(G1RedirtyCardsQueueSet* shared_qset);
G1BufferNodeList _buffers; ~G1RedirtyCardsLocalQueueSet() NOT_DEBUG(= default);
public: // Add the buffer to the local list.
LocalQSet(G1RedirtyCardsQueueSet* shared_qset); virtual void enqueue_completed_buffer(BufferNode* node);
~LocalQSet();
// Add the buffer to the local list. // Transfer all completed buffers to the shared qset.
virtual void enqueue_completed_buffer(BufferNode* node); void flush();
// Transfer all completed buffers to the shared qset.
void flush();
G1BufferNodeList take_all_completed_buffers();
};
G1RedirtyCardsQueueBase(G1RedirtyCardsQueueSet* shared_qset) :
_local_qset(shared_qset) {}
~G1RedirtyCardsQueueBase() {}
LocalQSet _local_qset;
}; };
// Worker-local queues of card table entries. // Worker-local queues of card table entries.
class G1RedirtyCardsQueue : private G1RedirtyCardsQueueBase, public PtrQueue { class G1RedirtyCardsQueue : public PtrQueue {
protected: protected:
virtual void handle_completed_buffer(); virtual void handle_completed_buffer();
public: public:
G1RedirtyCardsQueue(G1RedirtyCardsQueueSet* qset); G1RedirtyCardsQueue(G1RedirtyCardsLocalQueueSet* qset);
~G1RedirtyCardsQueue() NOT_DEBUG(= default);
// Flushes the queue.
~G1RedirtyCardsQueue();
// Flushes all enqueued cards to qset. // Flushes all enqueued cards to qset.
void flush(); void flush();
@ -97,8 +77,6 @@ class G1RedirtyCardsQueueSet : public PtrQueueSet {
BufferNode* _tail; BufferNode* _tail;
DEBUG_ONLY(mutable bool _collecting;) DEBUG_ONLY(mutable bool _collecting;)
typedef G1RedirtyCardsQueueBase::LocalQSet LocalQSet;
void update_tail(BufferNode* node); void update_tail(BufferNode* node);
public: public:
@ -110,7 +88,7 @@ public:
// Collect buffers. These functions are thread-safe. // Collect buffers. These functions are thread-safe.
// precondition: Must not be concurrent with buffer processing. // precondition: Must not be concurrent with buffer processing.
virtual void enqueue_completed_buffer(BufferNode* node); virtual void enqueue_completed_buffer(BufferNode* node);
void merge_bufferlist(LocalQSet* src); void add_bufferlist(const G1BufferNodeList& buffers);
// Processing phase operations. // Processing phase operations.
// precondition: Must not be concurrent with buffer collection. // precondition: Must not be concurrent with buffer collection.