8229044: G1RedirtyCardsQueueSet should be local to a collection

Stack allocate redirty qsets in do_collection_pause_at_safepoint.

Reviewed-by: tschatzl, sangheki
This commit is contained in:
Kim Barrett 2019-08-16 14:46:52 -04:00
parent c0b8844dce
commit 0b9a90e0d1
8 changed files with 43 additions and 44 deletions

View File

@ -1082,7 +1082,6 @@ void G1CollectedHeap::abort_refinement() {
G1BarrierSet::dirty_card_queue_set().abandon_logs();
assert(G1BarrierSet::dirty_card_queue_set().num_completed_buffers() == 0,
"DCQS should be empty");
redirty_cards_queue_set().verify_empty();
}
void G1CollectedHeap::verify_after_full_collection() {
@ -1521,7 +1520,6 @@ G1CollectedHeap::G1CollectedHeap() :
_collection_set(this, _policy),
_hot_card_cache(NULL),
_rem_set(NULL),
_redirty_cards_queue_set(),
_cm(NULL),
_cm_thread(NULL),
_cr(NULL),
@ -1691,9 +1689,6 @@ jint G1CollectedHeap::initialize() {
&bs->dirty_card_queue_buffer_allocator(),
true); // init_free_ids
// Use same buffer allocator as dirty card qset, to allow merging.
_redirty_cards_queue_set.initialize(&bs->dirty_card_queue_buffer_allocator());
// Create the hot card cache.
_hot_card_cache = new G1HotCardCache(this);
@ -3028,7 +3023,9 @@ bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_
calculate_collection_set(evacuation_info, target_pause_time_ms);
G1RedirtyCardsQueueSet rdcqs(G1BarrierSet::dirty_card_queue_set().allocator());
G1ParScanThreadStateSet per_thread_states(this,
&rdcqs,
workers()->active_workers(),
collection_set()->young_region_length(),
collection_set()->optional_region_length());
@ -3040,7 +3037,7 @@ bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_
if (_collection_set.optional_region_length() != 0) {
evacuate_optional_collection_set(&per_thread_states);
}
post_evacuate_collection_set(evacuation_info, &per_thread_states);
post_evacuate_collection_set(evacuation_info, &rdcqs, &per_thread_states);
start_new_collection_set();
@ -3122,15 +3119,15 @@ bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_
return true;
}
void G1CollectedHeap::remove_self_forwarding_pointers() {
G1ParRemoveSelfForwardPtrsTask rsfp_task;
void G1CollectedHeap::remove_self_forwarding_pointers(G1RedirtyCardsQueueSet* rdcqs) {
G1ParRemoveSelfForwardPtrsTask rsfp_task(rdcqs);
workers()->run_task(&rsfp_task);
}
void G1CollectedHeap::restore_after_evac_failure() {
void G1CollectedHeap::restore_after_evac_failure(G1RedirtyCardsQueueSet* rdcqs) {
double remove_self_forwards_start = os::elapsedTime();
remove_self_forwarding_pointers();
remove_self_forwarding_pointers(rdcqs);
SharedRestorePreservedMarksTaskExecutor task_executor(workers());
_preserved_marks_set.restore(&task_executor);
@ -3264,15 +3261,14 @@ class G1RedirtyLoggedCardsTask : public AbstractGangTask {
}
};
void G1CollectedHeap::redirty_logged_cards() {
void G1CollectedHeap::redirty_logged_cards(G1RedirtyCardsQueueSet* rdcqs) {
double redirty_logged_cards_start = os::elapsedTime();
G1RedirtyLoggedCardsTask redirty_task(&redirty_cards_queue_set(), this);
G1RedirtyLoggedCardsTask redirty_task(rdcqs, this);
workers()->run_task(&redirty_task);
G1DirtyCardQueueSet& dcq = G1BarrierSet::dirty_card_queue_set();
dcq.merge_bufferlists(&redirty_cards_queue_set());
redirty_cards_queue_set().verify_empty();
dcq.merge_bufferlists(rdcqs);
phase_times()->record_redirty_logged_cards_time_ms((os::elapsedTime() - redirty_logged_cards_start) * 1000.0);
}
@ -3603,8 +3599,6 @@ void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_i
// Should G1EvacuationFailureALot be in effect for this GC?
NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
redirty_cards_queue_set().verify_empty();
}
class G1EvacuateRegionsBaseTask : public AbstractGangTask {
@ -3806,7 +3800,9 @@ void G1CollectedHeap::evacuate_optional_collection_set(G1ParScanThreadStateSet*
_collection_set.abandon_optional_collection_set(per_thread_states);
}
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info,
G1RedirtyCardsQueueSet* rdcqs,
G1ParScanThreadStateSet* per_thread_states) {
rem_set()->cleanup_after_scan_heap_roots();
// Process any discovered reference objects - we have
@ -3834,7 +3830,7 @@ void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_
_allocator->release_gc_alloc_regions(evacuation_info);
if (evacuation_failed()) {
restore_after_evac_failure();
restore_after_evac_failure(rdcqs);
// Reset the G1EvacuationFailureALot counters and flags
NOT_PRODUCT(reset_evacuation_should_fail();)
@ -3869,7 +3865,7 @@ void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_
purge_code_root_memory();
redirty_logged_cards();
redirty_logged_cards(rdcqs);
free_collection_set(&_collection_set, evacuation_info, per_thread_states->surviving_young_words());

View File

@ -762,7 +762,9 @@ private:
public:
void pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info,
G1RedirtyCardsQueueSet* rdcqs,
G1ParScanThreadStateSet* pss);
void expand_heap_after_young_collection();
// Update object copying statistics.
@ -774,10 +776,6 @@ public:
// The g1 remembered set of the heap.
G1RemSet* _rem_set;
// A set of cards that cover the objects for which the Rsets should be updated
// concurrently after the collection.
G1RedirtyCardsQueueSet _redirty_cards_queue_set;
// After a collection pause, convert the regions in the collection set into free
// regions.
void free_collection_set(G1CollectionSet* collection_set, G1EvacuationInfo& evacuation_info, const size_t* surviving_young_words);
@ -803,11 +801,11 @@ public:
// Failed evacuations cause some logical from-space objects to have
// forwarding pointers to themselves. Reset them.
void remove_self_forwarding_pointers();
void remove_self_forwarding_pointers(G1RedirtyCardsQueueSet* rdcqs);
// Restore the objects in the regions in the collection set after an
// evacuation failure.
void restore_after_evac_failure();
void restore_after_evac_failure(G1RedirtyCardsQueueSet* rdcqs);
PreservedMarksSet _preserved_marks_set;
@ -935,11 +933,6 @@ public:
uint num_task_queues() const;
// A set of cards where updates happened during the GC
G1RedirtyCardsQueueSet& redirty_cards_queue_set() {
return _redirty_cards_queue_set;
}
// Create a G1CollectedHeap.
// Must call the initialize method afterwards.
// May not return if something goes wrong.
@ -1366,7 +1359,8 @@ public:
void complete_cleaning(BoolObjectClosure* is_alive, bool class_unloading_occurred);
// Redirty logged cards in the refinement queue.
void redirty_logged_cards();
void redirty_logged_cards(G1RedirtyCardsQueueSet* rdcqs);
// Verification
// Deduplicate the string

View File

@ -203,10 +203,10 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
UpdateLogBuffersDeferred _log_buffer_cl;
public:
RemoveSelfForwardPtrHRClosure(uint worker_id) :
RemoveSelfForwardPtrHRClosure(G1RedirtyCardsQueueSet* rdcqs, uint worker_id) :
_g1h(G1CollectedHeap::heap()),
_worker_id(worker_id),
_rdcq(&_g1h->redirty_cards_queue_set()),
_rdcq(rdcqs),
_log_buffer_cl(&_rdcq) {
}
@ -250,13 +250,14 @@ public:
}
};
G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask() :
G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask(G1RedirtyCardsQueueSet* rdcqs) :
AbstractGangTask("G1 Remove Self-forwarding Pointers"),
_g1h(G1CollectedHeap::heap()),
_rdcqs(rdcqs),
_hrclaimer(_g1h->workers()->active_workers()) { }
void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) {
RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id);
RemoveSelfForwardPtrHRClosure rsfp_cl(_rdcqs, worker_id);
_g1h->collection_set_iterate_increment_from(&rsfp_cl, &_hrclaimer, worker_id);
}

View File

@ -31,16 +31,18 @@
#include "utilities/globalDefinitions.hpp"
class G1CollectedHeap;
class G1RedirtyCardsQueueSet;
// Task to fixup self-forwarding pointers
// installed as a result of an evacuation failure.
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
G1RedirtyCardsQueueSet* _rdcqs;
HeapRegionClaimer _hrclaimer;
public:
G1ParRemoveSelfForwardPtrsTask();
G1ParRemoveSelfForwardPtrsTask(G1RedirtyCardsQueueSet* rdcqs);
void work(uint worker_id);
};

View File

@ -38,12 +38,13 @@
#include "runtime/prefetch.inline.hpp"
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
uint worker_id,
size_t young_cset_length,
size_t optional_cset_length)
: _g1h(g1h),
_refs(g1h->task_queue(worker_id)),
_rdcq(&g1h->redirty_cards_queue_set()),
_rdcq(rdcqs),
_ct(g1h->card_table()),
_closures(NULL),
_plab_allocator(NULL),
@ -336,7 +337,7 @@ G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id)
assert(worker_id < _n_workers, "out of bounds access");
if (_states[worker_id] == NULL) {
_states[worker_id] =
new G1ParScanThreadState(_g1h, worker_id, _young_cset_length, _optional_cset_length);
new G1ParScanThreadState(_g1h, _rdcqs, worker_id, _young_cset_length, _optional_cset_length);
}
return _states[worker_id];
}
@ -407,10 +408,12 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m) {
}
}
G1ParScanThreadStateSet::G1ParScanThreadStateSet(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
uint n_workers,
size_t young_cset_length,
size_t optional_cset_length) :
_g1h(g1h),
_rdcqs(rdcqs),
_states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)),
_surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)),
_young_cset_length(young_cset_length),

View File

@ -97,6 +97,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
public:
G1ParScanThreadState(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
uint worker_id,
size_t young_cset_length,
size_t optional_cset_length);
@ -237,6 +238,7 @@ public:
class G1ParScanThreadStateSet : public StackObj {
G1CollectedHeap* _g1h;
G1RedirtyCardsQueueSet* _rdcqs;
G1ParScanThreadState** _states;
size_t* _surviving_young_words_total;
size_t _young_cset_length;
@ -246,6 +248,7 @@ class G1ParScanThreadStateSet : public StackObj {
public:
G1ParScanThreadStateSet(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
uint n_workers,
size_t young_cset_length,
size_t optional_cset_length);

View File

@ -99,13 +99,15 @@ void G1RedirtyCardsQueue::flush() {
// G1RedirtyCardsQueueSet
G1RedirtyCardsQueueSet::G1RedirtyCardsQueueSet() :
G1RedirtyCardsQueueSet::G1RedirtyCardsQueueSet(BufferNode::Allocator* allocator) :
PtrQueueSet(),
_list(),
_entry_count(0),
_tail(NULL)
DEBUG_ONLY(COMMA _collecting(true))
{}
{
initialize(allocator);
}
G1RedirtyCardsQueueSet::~G1RedirtyCardsQueueSet() {
verify_empty();

View File

@ -110,11 +110,9 @@ class G1RedirtyCardsQueueSet : public PtrQueueSet {
void update_tail(BufferNode* node);
public:
G1RedirtyCardsQueueSet();
G1RedirtyCardsQueueSet(BufferNode::Allocator* allocator);
~G1RedirtyCardsQueueSet();
using PtrQueueSet::initialize;
void verify_empty() const NOT_DEBUG_RETURN;
// Collect buffers. These functions are thread-safe.