mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-25 13:04:05 +00:00
8135152: Create a G1ParScanThreadStateSet class for managing G1 GC per thread states
Reviewed-by: tschatzl, ehelin
This commit is contained in:
parent
802664728f
commit
2dbd4dd578
@ -4164,8 +4164,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||
// Initialize the GC alloc regions.
|
||||
_allocator->init_gc_alloc_regions(evacuation_info);
|
||||
|
||||
G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers());
|
||||
// Actually do the work...
|
||||
evacuate_collection_set(evacuation_info);
|
||||
evacuate_collection_set(evacuation_info, &per_thread_states);
|
||||
|
||||
free_collection_set(g1_policy()->collection_set(), evacuation_info);
|
||||
|
||||
@ -4545,15 +4546,15 @@ class G1KlassScanClosure : public KlassClosure {
|
||||
|
||||
class G1ParTask : public AbstractGangTask {
|
||||
protected:
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadState** _pss;
|
||||
RefToScanQueueSet* _queues;
|
||||
G1RootProcessor* _root_processor;
|
||||
ParallelTaskTerminator _terminator;
|
||||
uint _n_workers;
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadStateSet* _pss;
|
||||
RefToScanQueueSet* _queues;
|
||||
G1RootProcessor* _root_processor;
|
||||
ParallelTaskTerminator _terminator;
|
||||
uint _n_workers;
|
||||
|
||||
public:
|
||||
G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadState** per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
|
||||
G1ParTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers)
|
||||
: AbstractGangTask("G1 collection"),
|
||||
_g1h(g1h),
|
||||
_pss(per_thread_states),
|
||||
@ -4611,7 +4612,7 @@ public:
|
||||
|
||||
ReferenceProcessor* rp = _g1h->ref_processor_stw();
|
||||
|
||||
G1ParScanThreadState* pss = _pss[worker_id];
|
||||
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
|
||||
pss->set_ref_processor(rp);
|
||||
|
||||
bool only_young = _g1h->collector_state()->gcs_are_young();
|
||||
@ -5267,15 +5268,15 @@ public:
|
||||
|
||||
class G1STWRefProcTaskExecutor: public AbstractRefProcTaskExecutor {
|
||||
private:
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadState** _pss;
|
||||
RefToScanQueueSet* _queues;
|
||||
WorkGang* _workers;
|
||||
uint _active_workers;
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadStateSet* _pss;
|
||||
RefToScanQueueSet* _queues;
|
||||
WorkGang* _workers;
|
||||
uint _active_workers;
|
||||
|
||||
public:
|
||||
G1STWRefProcTaskExecutor(G1CollectedHeap* g1h,
|
||||
G1ParScanThreadState** per_thread_states,
|
||||
G1ParScanThreadStateSet* per_thread_states,
|
||||
WorkGang* workers,
|
||||
RefToScanQueueSet *task_queues,
|
||||
uint n_workers) :
|
||||
@ -5299,14 +5300,14 @@ class G1STWRefProcTaskProxy: public AbstractGangTask {
|
||||
typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask;
|
||||
ProcessTask& _proc_task;
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadState** _pss;
|
||||
G1ParScanThreadStateSet* _pss;
|
||||
RefToScanQueueSet* _task_queues;
|
||||
ParallelTaskTerminator* _terminator;
|
||||
|
||||
public:
|
||||
G1STWRefProcTaskProxy(ProcessTask& proc_task,
|
||||
G1CollectedHeap* g1h,
|
||||
G1ParScanThreadState** per_thread_states,
|
||||
G1ParScanThreadStateSet* per_thread_states,
|
||||
RefToScanQueueSet *task_queues,
|
||||
ParallelTaskTerminator* terminator) :
|
||||
AbstractGangTask("Process reference objects in parallel"),
|
||||
@ -5324,7 +5325,7 @@ public:
|
||||
|
||||
G1STWIsAliveClosure is_alive(_g1h);
|
||||
|
||||
G1ParScanThreadState* pss = _pss[worker_id];
|
||||
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
|
||||
pss->set_ref_processor(NULL);
|
||||
|
||||
G1ParScanExtRootClosure only_copy_non_heap_cl(_g1h, pss);
|
||||
@ -5403,14 +5404,14 @@ void G1STWRefProcTaskExecutor::execute(EnqueueTask& enq_task) {
|
||||
|
||||
class G1ParPreserveCMReferentsTask: public AbstractGangTask {
|
||||
protected:
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadState** _pss;
|
||||
RefToScanQueueSet* _queues;
|
||||
ParallelTaskTerminator _terminator;
|
||||
uint _n_workers;
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadStateSet* _pss;
|
||||
RefToScanQueueSet* _queues;
|
||||
ParallelTaskTerminator _terminator;
|
||||
uint _n_workers;
|
||||
|
||||
public:
|
||||
G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadState** per_thread_states, int workers, RefToScanQueueSet *task_queues) :
|
||||
G1ParPreserveCMReferentsTask(G1CollectedHeap* g1h, G1ParScanThreadStateSet* per_thread_states, int workers, RefToScanQueueSet *task_queues) :
|
||||
AbstractGangTask("ParPreserveCMReferents"),
|
||||
_g1h(g1h),
|
||||
_pss(per_thread_states),
|
||||
@ -5423,7 +5424,7 @@ public:
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
|
||||
G1ParScanThreadState* pss = _pss[worker_id];
|
||||
G1ParScanThreadState* pss = _pss->state_for_worker(worker_id);
|
||||
pss->set_ref_processor(NULL);
|
||||
assert(pss->queue_is_empty(), "both queue and overflow should be empty");
|
||||
|
||||
@ -5484,7 +5485,7 @@ public:
|
||||
};
|
||||
|
||||
// Weak Reference processing during an evacuation pause (part 1).
|
||||
void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_thread_states) {
|
||||
void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) {
|
||||
double ref_proc_start = os::elapsedTime();
|
||||
|
||||
ReferenceProcessor* rp = _ref_processor_stw;
|
||||
@ -5529,7 +5530,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_t
|
||||
// JNI refs.
|
||||
|
||||
// Use only a single queue for this PSS.
|
||||
G1ParScanThreadState* pss = per_thread_states[0];
|
||||
G1ParScanThreadState* pss = per_thread_states->state_for_worker(0);
|
||||
pss->set_ref_processor(NULL);
|
||||
assert(pss->queue_is_empty(), "pre-condition");
|
||||
|
||||
@ -5590,7 +5591,7 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadState** per_t
|
||||
}
|
||||
|
||||
// Weak Reference processing during an evacuation pause (part 2).
|
||||
void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadState** per_thread_states) {
|
||||
void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states) {
|
||||
double ref_enq_start = os::elapsedTime();
|
||||
|
||||
ReferenceProcessor* rp = _ref_processor_stw;
|
||||
@ -5625,7 +5626,7 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadState** per_t
|
||||
g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
|
||||
_expand_heap_after_alloc_failure = true;
|
||||
_evacuation_failed = false;
|
||||
|
||||
@ -5645,11 +5646,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
double start_par_time_sec = os::elapsedTime();
|
||||
double end_par_time_sec;
|
||||
|
||||
G1ParScanThreadState** per_thread_states = NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC);
|
||||
for (uint i = 0; i < n_workers; i++) {
|
||||
per_thread_states[i] = new_par_scan_state(i);
|
||||
}
|
||||
|
||||
{
|
||||
G1RootProcessor root_processor(this, n_workers);
|
||||
G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers);
|
||||
@ -5703,11 +5699,7 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
_allocator->release_gc_alloc_regions(evacuation_info);
|
||||
g1_rem_set()->cleanup_after_oops_into_collection_set_do();
|
||||
|
||||
for (uint i = 0; i < n_workers; i++) {
|
||||
G1ParScanThreadState* pss = per_thread_states[i];
|
||||
delete pss;
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(G1ParScanThreadState*, per_thread_states);
|
||||
per_thread_states->flush();
|
||||
|
||||
record_obj_copy_mem_stats();
|
||||
|
||||
|
||||
@ -56,6 +56,7 @@ class HRRSCleanupTask;
|
||||
class GenerationSpec;
|
||||
class OopsInHeapRegionClosure;
|
||||
class G1ParScanThreadState;
|
||||
class G1ParScanThreadStateSet;
|
||||
class G1KlassScanClosure;
|
||||
class G1ParScanThreadState;
|
||||
class ObjectClosure;
|
||||
@ -192,6 +193,7 @@ class G1CollectedHeap : public CollectedHeap {
|
||||
|
||||
// Closures used in implementation.
|
||||
friend class G1ParScanThreadState;
|
||||
friend class G1ParScanThreadStateSet;
|
||||
friend class G1ParTask;
|
||||
friend class G1PLABAllocator;
|
||||
friend class G1PrepareCompactClosure;
|
||||
@ -584,11 +586,11 @@ protected:
|
||||
|
||||
// Process any reference objects discovered during
|
||||
// an incremental evacuation pause.
|
||||
void process_discovered_references(G1ParScanThreadState** per_thread_states);
|
||||
void process_discovered_references(G1ParScanThreadStateSet* per_thread_states);
|
||||
|
||||
// Enqueue any remaining discovered references
|
||||
// after processing.
|
||||
void enqueue_discovered_references(G1ParScanThreadState** per_thread_states);
|
||||
void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states);
|
||||
|
||||
public:
|
||||
WorkGang* workers() const { return _workers; }
|
||||
@ -683,9 +685,6 @@ public:
|
||||
// Allocates a new heap region instance.
|
||||
HeapRegion* new_heap_region(uint hrs_index, MemRegion mr);
|
||||
|
||||
// Allocates a new per thread par scan state for the given thread id.
|
||||
G1ParScanThreadState* new_par_scan_state(uint worker_id);
|
||||
|
||||
// Allocate the highest free region in the reserved heap. This will commit
|
||||
// regions as necessary.
|
||||
HeapRegion* alloc_highest_free_region();
|
||||
@ -799,7 +798,7 @@ protected:
|
||||
bool do_collection_pause_at_safepoint(double target_pause_time_ms);
|
||||
|
||||
// Actually do the work of evacuating the collection set.
|
||||
void evacuate_collection_set(EvacuationInfo& evacuation_info);
|
||||
void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states);
|
||||
|
||||
// Print the header for the per-thread termination statistics.
|
||||
static void print_termination_stats_hdr(outputStream* const st);
|
||||
|
||||
@ -38,7 +38,3 @@ HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
|
||||
MemRegion mr) {
|
||||
return new HeapRegion(hrs_index, bot_shared(), mr);
|
||||
}
|
||||
|
||||
G1ParScanThreadState* G1CollectedHeap::new_par_scan_state(uint worker_id) {
|
||||
return new G1ParScanThreadState(this, worker_id);
|
||||
}
|
||||
|
||||
@ -865,8 +865,8 @@ public:
|
||||
return _recorded_survivor_regions;
|
||||
}
|
||||
|
||||
void record_thread_age_table(ageTable* age_table) {
|
||||
_survivors_age_table.merge_par(age_table);
|
||||
void record_age_table(ageTable* age_table) {
|
||||
_survivors_age_table.merge(age_table);
|
||||
}
|
||||
|
||||
void update_max_gc_locker_expansion();
|
||||
|
||||
@ -71,11 +71,16 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id)
|
||||
_dest[InCSetState::Old] = InCSetState::Old;
|
||||
}
|
||||
|
||||
G1ParScanThreadState::~G1ParScanThreadState() {
|
||||
// Pass locally gathered statistics to global state.
|
||||
void G1ParScanThreadState::flush() {
|
||||
_dcq.flush();
|
||||
// Update allocation statistics.
|
||||
_plab_allocator->flush_and_retire_stats();
|
||||
_g1h->g1_policy()->record_age_table(&_age_table);
|
||||
}
|
||||
|
||||
G1ParScanThreadState::~G1ParScanThreadState() {
|
||||
delete _plab_allocator;
|
||||
_g1h->g1_policy()->record_thread_age_table(&_age_table);
|
||||
// Update heap statistics.
|
||||
_g1h->update_surviving_young_words(_surviving_young_words);
|
||||
FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
|
||||
@ -314,6 +319,25 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
|
||||
}
|
||||
}
|
||||
|
||||
G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) {
|
||||
assert(worker_id < _n_workers, "out of bounds access");
|
||||
return _states[worker_id];
|
||||
}
|
||||
|
||||
void G1ParScanThreadStateSet::flush() {
|
||||
assert(!_flushed, "thread local state from the per thread states should be flushed once");
|
||||
|
||||
for (uint worker_index = 0; worker_index < _n_workers; ++worker_index) {
|
||||
G1ParScanThreadState* pss = _states[worker_index];
|
||||
|
||||
pss->flush();
|
||||
|
||||
delete pss;
|
||||
_states[worker_index] = NULL;
|
||||
}
|
||||
_flushed = true;
|
||||
}
|
||||
|
||||
oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
|
||||
assert(_g1h->obj_in_cs(old),
|
||||
err_msg("Object " PTR_FORMAT " should be in the CSet", p2i(old)));
|
||||
|
||||
@ -121,6 +121,8 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
|
||||
return _surviving_young_words + 1;
|
||||
}
|
||||
|
||||
void flush();
|
||||
|
||||
private:
|
||||
#define G1_PARTIAL_ARRAY_MASK 0x2
|
||||
|
||||
@ -189,4 +191,34 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
|
||||
oop handle_evacuation_failure_par(oop obj, markOop m);
|
||||
};
|
||||
|
||||
class G1ParScanThreadStateSet : public StackObj {
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadState** _states;
|
||||
uint _n_workers;
|
||||
bool _flushed;
|
||||
|
||||
public:
|
||||
G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers) :
|
||||
_g1h(g1h),
|
||||
_states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)),
|
||||
_n_workers(n_workers),
|
||||
_flushed(false) {
|
||||
for (uint i = 0; i < n_workers; ++i) {
|
||||
_states[i] = new_par_scan_state(i);
|
||||
}
|
||||
}
|
||||
|
||||
~G1ParScanThreadStateSet() {
|
||||
assert(_flushed, "thread local state from the per thread states should have been flushed");
|
||||
FREE_C_HEAP_ARRAY(G1ParScanThreadState*, _states);
|
||||
}
|
||||
|
||||
void flush();
|
||||
|
||||
G1ParScanThreadState* state_for_worker(uint worker_id);
|
||||
|
||||
private:
|
||||
G1ParScanThreadState* new_par_scan_state(uint worker_id);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_GC_G1_G1PARSCANTHREADSTATE_HPP
|
||||
|
||||
31
hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp
Normal file
31
hotspot/src/share/vm/gc/g1/g1ParScanThreadState_ext.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1ParScanThreadState.hpp"
|
||||
|
||||
G1ParScanThreadState* G1ParScanThreadStateSet::new_par_scan_state(uint worker_id) {
|
||||
return new G1ParScanThreadState(_g1h, worker_id);
|
||||
}
|
||||
@ -28,7 +28,6 @@
|
||||
#include "gc/shared/collectorPolicy.hpp"
|
||||
#include "gc/shared/gcPolicyCounters.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/atomic.inline.hpp"
|
||||
#include "utilities/copy.hpp"
|
||||
|
||||
/* Copyright (c) 1992, 2015, Oracle and/or its affiliates, and Stanford University.
|
||||
@ -73,12 +72,6 @@ void ageTable::merge(ageTable* subTable) {
|
||||
}
|
||||
}
|
||||
|
||||
void ageTable::merge_par(ageTable* subTable) {
|
||||
for (int i = 0; i < table_size; i++) {
|
||||
Atomic::add_ptr(subTable->sizes[i], &sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters) {
|
||||
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
|
||||
uint result;
|
||||
|
||||
@ -68,7 +68,6 @@ class ageTable VALUE_OBJ_CLASS_SPEC {
|
||||
// Merge another age table with the current one. Used
|
||||
// for parallel young generation gc.
|
||||
void merge(ageTable* subTable);
|
||||
void merge_par(ageTable* subTable);
|
||||
|
||||
// calculate new tenuring threshold based on age information
|
||||
uint compute_tenuring_threshold(size_t survivor_capacity, GCPolicyCounters* gc_counters);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user