8058298: Separate heap region iterator claim values from the data structures iterated over
Reviewed-by: tschatzl, brutisso
This commit is contained in:
parent
18eb46eb95
commit
6d1c35615a
@ -1683,6 +1683,8 @@ protected:
|
|||||||
int _failures;
|
int _failures;
|
||||||
bool _verbose;
|
bool _verbose;
|
||||||
|
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1ParVerifyFinalCountTask(G1CollectedHeap* g1h,
|
G1ParVerifyFinalCountTask(G1CollectedHeap* g1h,
|
||||||
BitMap* region_bm, BitMap* card_bm,
|
BitMap* region_bm, BitMap* card_bm,
|
||||||
@ -1692,19 +1694,8 @@ public:
|
|||||||
_actual_region_bm(region_bm), _actual_card_bm(card_bm),
|
_actual_region_bm(region_bm), _actual_card_bm(card_bm),
|
||||||
_expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm),
|
_expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm),
|
||||||
_failures(0), _verbose(false),
|
_failures(0), _verbose(false),
|
||||||
_n_workers(0) {
|
_n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) {
|
||||||
assert(VerifyDuringGC, "don't call this otherwise");
|
assert(VerifyDuringGC, "don't call this otherwise");
|
||||||
|
|
||||||
// Use the value already set as the number of active threads
|
|
||||||
// in the call to run_task().
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
|
||||||
assert( _g1h->workers()->active_workers() > 0,
|
|
||||||
"Should have been previously set");
|
|
||||||
_n_workers = _g1h->workers()->active_workers();
|
|
||||||
} else {
|
|
||||||
_n_workers = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity");
|
assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity");
|
||||||
assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity");
|
assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity");
|
||||||
|
|
||||||
@ -1721,10 +1712,7 @@ public:
|
|||||||
_verbose);
|
_verbose);
|
||||||
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
_g1h->heap_region_par_iterate_chunked(&verify_cl,
|
_g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer);
|
||||||
worker_id,
|
|
||||||
_n_workers,
|
|
||||||
HeapRegion::VerifyCountClaimValue);
|
|
||||||
} else {
|
} else {
|
||||||
_g1h->heap_region_iterate(&verify_cl);
|
_g1h->heap_region_iterate(&verify_cl);
|
||||||
}
|
}
|
||||||
@ -1813,22 +1801,14 @@ protected:
|
|||||||
BitMap* _actual_card_bm;
|
BitMap* _actual_card_bm;
|
||||||
|
|
||||||
uint _n_workers;
|
uint _n_workers;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm)
|
G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm)
|
||||||
: AbstractGangTask("G1 final counting"),
|
: AbstractGangTask("G1 final counting"),
|
||||||
_g1h(g1h), _cm(_g1h->concurrent_mark()),
|
_g1h(g1h), _cm(_g1h->concurrent_mark()),
|
||||||
_actual_region_bm(region_bm), _actual_card_bm(card_bm),
|
_actual_region_bm(region_bm), _actual_card_bm(card_bm),
|
||||||
_n_workers(0) {
|
_n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) {
|
||||||
// Use the value already set as the number of active threads
|
|
||||||
// in the call to run_task().
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
|
||||||
assert( _g1h->workers()->active_workers() > 0,
|
|
||||||
"Should have been previously set");
|
|
||||||
_n_workers = _g1h->workers()->active_workers();
|
|
||||||
} else {
|
|
||||||
_n_workers = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
@ -1839,10 +1819,7 @@ public:
|
|||||||
_actual_card_bm);
|
_actual_card_bm);
|
||||||
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
_g1h->heap_region_par_iterate_chunked(&final_update_cl,
|
_g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer);
|
||||||
worker_id,
|
|
||||||
_n_workers,
|
|
||||||
HeapRegion::FinalCountClaimValue);
|
|
||||||
} else {
|
} else {
|
||||||
_g1h->heap_region_iterate(&final_update_cl);
|
_g1h->heap_region_iterate(&final_update_cl);
|
||||||
}
|
}
|
||||||
@ -1929,12 +1906,12 @@ protected:
|
|||||||
size_t _max_live_bytes;
|
size_t _max_live_bytes;
|
||||||
size_t _freed_bytes;
|
size_t _freed_bytes;
|
||||||
FreeRegionList* _cleanup_list;
|
FreeRegionList* _cleanup_list;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1ParNoteEndTask(G1CollectedHeap* g1h,
|
G1ParNoteEndTask(G1CollectedHeap* g1h, FreeRegionList* cleanup_list, uint n_workers) :
|
||||||
FreeRegionList* cleanup_list) :
|
AbstractGangTask("G1 note end"), _g1h(g1h), _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list), _hrclaimer(n_workers) {
|
||||||
AbstractGangTask("G1 note end"), _g1h(g1h),
|
}
|
||||||
_max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
|
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
double start = os::elapsedTime();
|
double start = os::elapsedTime();
|
||||||
@ -1943,9 +1920,7 @@ public:
|
|||||||
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
|
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
|
||||||
&hrrs_cleanup_task);
|
&hrrs_cleanup_task);
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
_g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id,
|
_g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer);
|
||||||
_g1h->workers()->active_workers(),
|
|
||||||
HeapRegion::NoteEndClaimValue);
|
|
||||||
} else {
|
} else {
|
||||||
_g1h->heap_region_iterate(&g1_note_end);
|
_g1h->heap_region_iterate(&g1_note_end);
|
||||||
}
|
}
|
||||||
@ -1991,16 +1966,16 @@ protected:
|
|||||||
G1RemSet* _g1rs;
|
G1RemSet* _g1rs;
|
||||||
BitMap* _region_bm;
|
BitMap* _region_bm;
|
||||||
BitMap* _card_bm;
|
BitMap* _card_bm;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1ParScrubRemSetTask(G1CollectedHeap* g1h,
|
G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, uint n_workers) :
|
||||||
BitMap* region_bm, BitMap* card_bm) :
|
AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) {
|
||||||
AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()),
|
}
|
||||||
_region_bm(region_bm), _card_bm(card_bm) { }
|
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
_g1rs->scrub_par(_region_bm, _card_bm, worker_id,
|
_g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer);
|
||||||
HeapRegion::ScrubRemSetClaimValue);
|
|
||||||
} else {
|
} else {
|
||||||
_g1rs->scrub(_region_bm, _card_bm);
|
_g1rs->scrub(_region_bm, _card_bm);
|
||||||
}
|
}
|
||||||
@ -2043,9 +2018,6 @@ void ConcurrentMark::cleanup() {
|
|||||||
G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm);
|
G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm);
|
||||||
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
assert(g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
|
|
||||||
g1h->set_par_threads();
|
g1h->set_par_threads();
|
||||||
n_workers = g1h->n_par_threads();
|
n_workers = g1h->n_par_threads();
|
||||||
assert(g1h->n_par_threads() == n_workers,
|
assert(g1h->n_par_threads() == n_workers,
|
||||||
@ -2053,9 +2025,6 @@ void ConcurrentMark::cleanup() {
|
|||||||
g1h->workers()->run_task(&g1_par_count_task);
|
g1h->workers()->run_task(&g1_par_count_task);
|
||||||
// Done with the parallel phase so reset to 0.
|
// Done with the parallel phase so reset to 0.
|
||||||
g1h->set_par_threads(0);
|
g1h->set_par_threads(0);
|
||||||
|
|
||||||
assert(g1h->check_heap_region_claim_values(HeapRegion::FinalCountClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
} else {
|
} else {
|
||||||
n_workers = 1;
|
n_workers = 1;
|
||||||
g1_par_count_task.work(0);
|
g1_par_count_task.work(0);
|
||||||
@ -2080,9 +2049,6 @@ void ConcurrentMark::cleanup() {
|
|||||||
g1h->workers()->run_task(&g1_par_verify_task);
|
g1h->workers()->run_task(&g1_par_verify_task);
|
||||||
// Done with the parallel phase so reset to 0.
|
// Done with the parallel phase so reset to 0.
|
||||||
g1h->set_par_threads(0);
|
g1h->set_par_threads(0);
|
||||||
|
|
||||||
assert(g1h->check_heap_region_claim_values(HeapRegion::VerifyCountClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
} else {
|
} else {
|
||||||
g1_par_verify_task.work(0);
|
g1_par_verify_task.work(0);
|
||||||
}
|
}
|
||||||
@ -2108,14 +2074,11 @@ void ConcurrentMark::cleanup() {
|
|||||||
g1h->reset_gc_time_stamp();
|
g1h->reset_gc_time_stamp();
|
||||||
|
|
||||||
// Note end of marking in all heap regions.
|
// Note end of marking in all heap regions.
|
||||||
G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list);
|
G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers);
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
g1h->set_par_threads((int)n_workers);
|
g1h->set_par_threads((int)n_workers);
|
||||||
g1h->workers()->run_task(&g1_par_note_end_task);
|
g1h->workers()->run_task(&g1_par_note_end_task);
|
||||||
g1h->set_par_threads(0);
|
g1h->set_par_threads(0);
|
||||||
|
|
||||||
assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
} else {
|
} else {
|
||||||
g1_par_note_end_task.work(0);
|
g1_par_note_end_task.work(0);
|
||||||
}
|
}
|
||||||
@ -2132,15 +2095,11 @@ void ConcurrentMark::cleanup() {
|
|||||||
// regions.
|
// regions.
|
||||||
if (G1ScrubRemSets) {
|
if (G1ScrubRemSets) {
|
||||||
double rs_scrub_start = os::elapsedTime();
|
double rs_scrub_start = os::elapsedTime();
|
||||||
G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm);
|
G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers);
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
g1h->set_par_threads((int)n_workers);
|
g1h->set_par_threads((int)n_workers);
|
||||||
g1h->workers()->run_task(&g1_par_scrub_rs_task);
|
g1h->workers()->run_task(&g1_par_scrub_rs_task);
|
||||||
g1h->set_par_threads(0);
|
g1h->set_par_threads(0);
|
||||||
|
|
||||||
assert(g1h->check_heap_region_claim_values(
|
|
||||||
HeapRegion::ScrubRemSetClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
} else {
|
} else {
|
||||||
g1_par_scrub_rs_task.work(0);
|
g1_par_scrub_rs_task.work(0);
|
||||||
}
|
}
|
||||||
@ -3288,6 +3247,7 @@ protected:
|
|||||||
BitMap* _cm_card_bm;
|
BitMap* _cm_card_bm;
|
||||||
uint _max_worker_id;
|
uint _max_worker_id;
|
||||||
int _active_workers;
|
int _active_workers;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1AggregateCountDataTask(G1CollectedHeap* g1h,
|
G1AggregateCountDataTask(G1CollectedHeap* g1h,
|
||||||
@ -3295,18 +3255,18 @@ public:
|
|||||||
BitMap* cm_card_bm,
|
BitMap* cm_card_bm,
|
||||||
uint max_worker_id,
|
uint max_worker_id,
|
||||||
int n_workers) :
|
int n_workers) :
|
||||||
AbstractGangTask("Count Aggregation"),
|
AbstractGangTask("Count Aggregation"),
|
||||||
_g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
|
_g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
|
||||||
_max_worker_id(max_worker_id),
|
_max_worker_id(max_worker_id),
|
||||||
_active_workers(n_workers) { }
|
_active_workers(n_workers),
|
||||||
|
_hrclaimer(_active_workers) {
|
||||||
|
}
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id);
|
AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id);
|
||||||
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
_g1h->heap_region_par_iterate_chunked(&cl, worker_id,
|
_g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer);
|
||||||
_active_workers,
|
|
||||||
HeapRegion::AggregateCountClaimValue);
|
|
||||||
} else {
|
} else {
|
||||||
_g1h->heap_region_iterate(&cl);
|
_g1h->heap_region_iterate(&cl);
|
||||||
}
|
}
|
||||||
@ -3323,15 +3283,9 @@ void ConcurrentMark::aggregate_count_data() {
|
|||||||
_max_worker_id, n_workers);
|
_max_worker_id, n_workers);
|
||||||
|
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||||
assert(_g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
_g1h->set_par_threads(n_workers);
|
_g1h->set_par_threads(n_workers);
|
||||||
_g1h->workers()->run_task(&g1_par_agg_task);
|
_g1h->workers()->run_task(&g1_par_agg_task);
|
||||||
_g1h->set_par_threads(0);
|
_g1h->set_par_threads(0);
|
||||||
|
|
||||||
assert(_g1h->check_heap_region_claim_values(HeapRegion::AggregateCountClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
_g1h->reset_heap_region_claim_values();
|
|
||||||
} else {
|
} else {
|
||||||
g1_par_agg_task.work(0);
|
g1_par_agg_task.work(0);
|
||||||
}
|
}
|
||||||
|
@ -90,8 +90,8 @@ size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
|
|||||||
|
|
||||||
// Notes on implementation of parallelism in different tasks.
|
// Notes on implementation of parallelism in different tasks.
|
||||||
//
|
//
|
||||||
// G1ParVerifyTask uses heap_region_par_iterate_chunked() for parallelism.
|
// G1ParVerifyTask uses heap_region_par_iterate() for parallelism.
|
||||||
// The number of GC workers is passed to heap_region_par_iterate_chunked().
|
// The number of GC workers is passed to heap_region_par_iterate().
|
||||||
// It does use run_task() which sets _n_workers in the task.
|
// It does use run_task() which sets _n_workers in the task.
|
||||||
// G1ParTask executes g1_process_roots() ->
|
// G1ParTask executes g1_process_roots() ->
|
||||||
// SharedHeap::process_roots() which calls eventually to
|
// SharedHeap::process_roots() which calls eventually to
|
||||||
@ -1215,17 +1215,15 @@ public:
|
|||||||
|
|
||||||
class ParRebuildRSTask: public AbstractGangTask {
|
class ParRebuildRSTask: public AbstractGangTask {
|
||||||
G1CollectedHeap* _g1;
|
G1CollectedHeap* _g1;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParRebuildRSTask(G1CollectedHeap* g1)
|
ParRebuildRSTask(G1CollectedHeap* g1) :
|
||||||
: AbstractGangTask("ParRebuildRSTask"),
|
AbstractGangTask("ParRebuildRSTask"), _g1(g1), _hrclaimer(g1->workers()->active_workers()) {}
|
||||||
_g1(g1)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id);
|
RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id);
|
||||||
_g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id,
|
_g1->heap_region_par_iterate(&rebuild_rs, worker_id, &_hrclaimer);
|
||||||
_g1->workers()->active_workers(),
|
|
||||||
HeapRegion::RebuildRSClaimValue);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1455,8 +1453,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
|||||||
set_par_threads(n_workers);
|
set_par_threads(n_workers);
|
||||||
|
|
||||||
ParRebuildRSTask rebuild_rs_task(this);
|
ParRebuildRSTask rebuild_rs_task(this);
|
||||||
assert(check_heap_region_claim_values(
|
|
||||||
HeapRegion::InitialClaimValue), "sanity check");
|
|
||||||
assert(UseDynamicNumberOfGCThreads ||
|
assert(UseDynamicNumberOfGCThreads ||
|
||||||
workers()->active_workers() == workers()->total_workers(),
|
workers()->active_workers() == workers()->total_workers(),
|
||||||
"Unless dynamic should use total workers");
|
"Unless dynamic should use total workers");
|
||||||
@ -1466,9 +1462,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
|||||||
set_par_threads(workers()->active_workers());
|
set_par_threads(workers()->active_workers());
|
||||||
workers()->run_task(&rebuild_rs_task);
|
workers()->run_task(&rebuild_rs_task);
|
||||||
set_par_threads(0);
|
set_par_threads(0);
|
||||||
assert(check_heap_region_claim_values(
|
|
||||||
HeapRegion::RebuildRSClaimValue), "sanity check");
|
|
||||||
reset_heap_region_claim_values();
|
|
||||||
} else {
|
} else {
|
||||||
RebuildRSOutOfRegionClosure rebuild_rs(this);
|
RebuildRSOutOfRegionClosure rebuild_rs(this);
|
||||||
heap_region_iterate(&rebuild_rs);
|
heap_region_iterate(&rebuild_rs);
|
||||||
@ -2634,111 +2627,12 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl,
|
G1CollectedHeap::heap_region_par_iterate(HeapRegionClosure* cl,
|
||||||
uint worker_id,
|
uint worker_id,
|
||||||
uint num_workers,
|
HeapRegionClaimer *hrclaimer) const {
|
||||||
jint claim_value) const {
|
_hrm.par_iterate(cl, worker_id, hrclaimer);
|
||||||
_hrm.par_iterate(cl, worker_id, num_workers, claim_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResetClaimValuesClosure: public HeapRegionClosure {
|
|
||||||
public:
|
|
||||||
bool doHeapRegion(HeapRegion* r) {
|
|
||||||
r->set_claim_value(HeapRegion::InitialClaimValue);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void G1CollectedHeap::reset_heap_region_claim_values() {
|
|
||||||
ResetClaimValuesClosure blk;
|
|
||||||
heap_region_iterate(&blk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void G1CollectedHeap::reset_cset_heap_region_claim_values() {
|
|
||||||
ResetClaimValuesClosure blk;
|
|
||||||
collection_set_iterate(&blk);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
// This checks whether all regions in the heap have the correct claim
|
|
||||||
// value. I also piggy-backed on this a check to ensure that the
|
|
||||||
// humongous_start_region() information on "continues humongous"
|
|
||||||
// regions is correct.
|
|
||||||
|
|
||||||
class CheckClaimValuesClosure : public HeapRegionClosure {
|
|
||||||
private:
|
|
||||||
jint _claim_value;
|
|
||||||
uint _failures;
|
|
||||||
HeapRegion* _sh_region;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CheckClaimValuesClosure(jint claim_value) :
|
|
||||||
_claim_value(claim_value), _failures(0), _sh_region(NULL) { }
|
|
||||||
bool doHeapRegion(HeapRegion* r) {
|
|
||||||
if (r->claim_value() != _claim_value) {
|
|
||||||
gclog_or_tty->print_cr("Region " HR_FORMAT ", "
|
|
||||||
"claim value = %d, should be %d",
|
|
||||||
HR_FORMAT_PARAMS(r),
|
|
||||||
r->claim_value(), _claim_value);
|
|
||||||
++_failures;
|
|
||||||
}
|
|
||||||
if (!r->is_humongous()) {
|
|
||||||
_sh_region = NULL;
|
|
||||||
} else if (r->is_starts_humongous()) {
|
|
||||||
_sh_region = r;
|
|
||||||
} else if (r->is_continues_humongous()) {
|
|
||||||
if (r->humongous_start_region() != _sh_region) {
|
|
||||||
gclog_or_tty->print_cr("Region " HR_FORMAT ", "
|
|
||||||
"HS = "PTR_FORMAT", should be "PTR_FORMAT,
|
|
||||||
HR_FORMAT_PARAMS(r),
|
|
||||||
r->humongous_start_region(),
|
|
||||||
_sh_region);
|
|
||||||
++_failures;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint failures() { return _failures; }
|
|
||||||
};
|
|
||||||
|
|
||||||
bool G1CollectedHeap::check_heap_region_claim_values(jint claim_value) {
|
|
||||||
CheckClaimValuesClosure cl(claim_value);
|
|
||||||
heap_region_iterate(&cl);
|
|
||||||
return cl.failures() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CheckClaimValuesInCSetHRClosure: public HeapRegionClosure {
|
|
||||||
private:
|
|
||||||
jint _claim_value;
|
|
||||||
uint _failures;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CheckClaimValuesInCSetHRClosure(jint claim_value) :
|
|
||||||
_claim_value(claim_value), _failures(0) { }
|
|
||||||
|
|
||||||
uint failures() { return _failures; }
|
|
||||||
|
|
||||||
bool doHeapRegion(HeapRegion* hr) {
|
|
||||||
assert(hr->in_collection_set(), "how?");
|
|
||||||
assert(!hr->is_humongous(), "H-region in CSet");
|
|
||||||
if (hr->claim_value() != _claim_value) {
|
|
||||||
gclog_or_tty->print_cr("CSet Region " HR_FORMAT ", "
|
|
||||||
"claim value = %d, should be %d",
|
|
||||||
HR_FORMAT_PARAMS(hr),
|
|
||||||
hr->claim_value(), _claim_value);
|
|
||||||
_failures += 1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool G1CollectedHeap::check_cset_heap_region_claim_values(jint claim_value) {
|
|
||||||
CheckClaimValuesInCSetHRClosure cl(claim_value);
|
|
||||||
collection_set_iterate(&cl);
|
|
||||||
return cl.failures() == 0;
|
|
||||||
}
|
|
||||||
#endif // ASSERT
|
|
||||||
|
|
||||||
// Clear the cached CSet starting regions and (more importantly)
|
// Clear the cached CSet starting regions and (more importantly)
|
||||||
// the time stamps. Called when we reset the GC time stamp.
|
// the time stamps. Called when we reset the GC time stamp.
|
||||||
void G1CollectedHeap::clear_cset_start_regions() {
|
void G1CollectedHeap::clear_cset_start_regions() {
|
||||||
@ -3252,19 +3146,21 @@ public:
|
|||||||
|
|
||||||
class G1ParVerifyTask: public AbstractGangTask {
|
class G1ParVerifyTask: public AbstractGangTask {
|
||||||
private:
|
private:
|
||||||
G1CollectedHeap* _g1h;
|
G1CollectedHeap* _g1h;
|
||||||
VerifyOption _vo;
|
VerifyOption _vo;
|
||||||
bool _failures;
|
bool _failures;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// _vo == UsePrevMarking -> use "prev" marking information,
|
// _vo == UsePrevMarking -> use "prev" marking information,
|
||||||
// _vo == UseNextMarking -> use "next" marking information,
|
// _vo == UseNextMarking -> use "next" marking information,
|
||||||
// _vo == UseMarkWord -> use mark word from object header.
|
// _vo == UseMarkWord -> use mark word from object header.
|
||||||
G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) :
|
G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) :
|
||||||
AbstractGangTask("Parallel verify task"),
|
AbstractGangTask("Parallel verify task"),
|
||||||
_g1h(g1h),
|
_g1h(g1h),
|
||||||
_vo(vo),
|
_vo(vo),
|
||||||
_failures(false) { }
|
_failures(false),
|
||||||
|
_hrclaimer(g1h->workers()->active_workers()) {}
|
||||||
|
|
||||||
bool failures() {
|
bool failures() {
|
||||||
return _failures;
|
return _failures;
|
||||||
@ -3273,9 +3169,7 @@ public:
|
|||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
VerifyRegionClosure blk(true, _vo);
|
VerifyRegionClosure blk(true, _vo);
|
||||||
_g1h->heap_region_par_iterate_chunked(&blk, worker_id,
|
_g1h->heap_region_par_iterate(&blk, worker_id, &_hrclaimer);
|
||||||
_g1h->workers()->active_workers(),
|
|
||||||
HeapRegion::ParVerifyClaimValue);
|
|
||||||
if (blk.failures()) {
|
if (blk.failures()) {
|
||||||
_failures = true;
|
_failures = true;
|
||||||
}
|
}
|
||||||
@ -3317,8 +3211,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
|
|||||||
|
|
||||||
if (!silent) { gclog_or_tty->print("HeapRegions "); }
|
if (!silent) { gclog_or_tty->print("HeapRegions "); }
|
||||||
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
|
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
|
||||||
assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
|
|
||||||
G1ParVerifyTask task(this, vo);
|
G1ParVerifyTask task(this, vo);
|
||||||
assert(UseDynamicNumberOfGCThreads ||
|
assert(UseDynamicNumberOfGCThreads ||
|
||||||
@ -3332,15 +3224,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
|
|||||||
failures = true;
|
failures = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that the expected amount of parallel work was done.
|
|
||||||
// The implication is that n_workers is > 0.
|
|
||||||
assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
|
|
||||||
reset_heap_region_claim_values();
|
|
||||||
|
|
||||||
assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
} else {
|
} else {
|
||||||
VerifyRegionClosure blk(false, vo);
|
VerifyRegionClosure blk(false, vo);
|
||||||
heap_region_iterate(&blk);
|
heap_region_iterate(&blk);
|
||||||
@ -3927,8 +3810,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(check_young_list_well_formed(), "young list should be well formed");
|
assert(check_young_list_well_formed(), "young list should be well formed");
|
||||||
assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
|
|
||||||
// Don't dynamically change the number of GC threads this early. A value of
|
// Don't dynamically change the number of GC threads this early. A value of
|
||||||
// 0 is used to indicate serial work. When parallel work is done,
|
// 0 is used to indicate serial work. When parallel work is done,
|
||||||
@ -4289,26 +4170,12 @@ void G1CollectedHeap::finalize_for_evac_failure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::remove_self_forwarding_pointers() {
|
void G1CollectedHeap::remove_self_forwarding_pointers() {
|
||||||
assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
|
|
||||||
|
|
||||||
double remove_self_forwards_start = os::elapsedTime();
|
double remove_self_forwards_start = os::elapsedTime();
|
||||||
|
|
||||||
|
set_par_threads();
|
||||||
G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
|
G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
|
||||||
|
workers()->run_task(&rsfp_task);
|
||||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
set_par_threads(0);
|
||||||
set_par_threads();
|
|
||||||
workers()->run_task(&rsfp_task);
|
|
||||||
set_par_threads(0);
|
|
||||||
} else {
|
|
||||||
rsfp_task.work(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(check_cset_heap_region_claim_values(HeapRegion::ParEvacFailureClaimValue), "sanity");
|
|
||||||
|
|
||||||
// Reset the claim values in the regions in the collection set.
|
|
||||||
reset_cset_heap_region_claim_values();
|
|
||||||
|
|
||||||
assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
|
|
||||||
|
|
||||||
// Now restore saved marks, if any.
|
// Now restore saved marks, if any.
|
||||||
assert(_objs_with_preserved_marks.size() ==
|
assert(_objs_with_preserved_marks.size() ==
|
||||||
@ -5949,11 +5816,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
|||||||
|
|
||||||
purge_code_root_memory();
|
purge_code_root_memory();
|
||||||
|
|
||||||
if (g1_policy()->during_initial_mark_pause()) {
|
|
||||||
// Reset the claim values set during marking the strong code roots
|
|
||||||
reset_heap_region_claim_values();
|
|
||||||
}
|
|
||||||
|
|
||||||
finalize_for_evac_failure();
|
finalize_for_evac_failure();
|
||||||
|
|
||||||
if (evacuation_failed()) {
|
if (evacuation_failed()) {
|
||||||
|
@ -211,6 +211,7 @@ class G1CollectedHeap : public SharedHeap {
|
|||||||
friend class G1FreeHumongousRegionClosure;
|
friend class G1FreeHumongousRegionClosure;
|
||||||
// Other related classes.
|
// Other related classes.
|
||||||
friend class G1MarkSweep;
|
friend class G1MarkSweep;
|
||||||
|
friend class HeapRegionClaimer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The one and only G1CollectedHeap, so static functions can find it.
|
// The one and only G1CollectedHeap, so static functions can find it.
|
||||||
@ -1377,38 +1378,15 @@ public:
|
|||||||
|
|
||||||
inline HeapWord* bottom_addr_for_region(uint index) const;
|
inline HeapWord* bottom_addr_for_region(uint index) const;
|
||||||
|
|
||||||
// Divide the heap region sequence into "chunks" of some size (the number
|
// Iterate over the heap regions in parallel. Assumes that this will be called
|
||||||
// of regions divided by the number of parallel threads times some
|
// in parallel by ParallelGCThreads worker threads with distinct worker ids
|
||||||
// overpartition factor, currently 4). Assumes that this will be called
|
// in the range [0..max(ParallelGCThreads-1, 1)]. Applies "blk->doHeapRegion"
|
||||||
// in parallel by ParallelGCThreads worker threads with distinct worker
|
// to each of the regions, by attempting to claim the region using the
|
||||||
// ids in the range [0..max(ParallelGCThreads-1, 1)], that all parallel
|
// HeapRegionClaimer and, if successful, applying the closure to the claimed
|
||||||
// calls will use the same "claim_value", and that that claim value is
|
// region.
|
||||||
// different from the claim_value of any heap region before the start of
|
void heap_region_par_iterate(HeapRegionClosure* cl,
|
||||||
// the iteration. Applies "blk->doHeapRegion" to each of the regions, by
|
uint worker_id,
|
||||||
// attempting to claim the first region in each chunk, and, if
|
HeapRegionClaimer* hrclaimer) const;
|
||||||
// successful, applying the closure to each region in the chunk (and
|
|
||||||
// setting the claim value of the second and subsequent regions of the
|
|
||||||
// chunk.) For now requires that "doHeapRegion" always returns "false",
|
|
||||||
// i.e., that a closure never attempt to abort a traversal.
|
|
||||||
void heap_region_par_iterate_chunked(HeapRegionClosure* cl,
|
|
||||||
uint worker_id,
|
|
||||||
uint num_workers,
|
|
||||||
jint claim_value) const;
|
|
||||||
|
|
||||||
// It resets all the region claim values to the default.
|
|
||||||
void reset_heap_region_claim_values();
|
|
||||||
|
|
||||||
// Resets the claim values of regions in the current
|
|
||||||
// collection set to the default.
|
|
||||||
void reset_cset_heap_region_claim_values();
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
bool check_heap_region_claim_values(jint claim_value);
|
|
||||||
|
|
||||||
// Same as the routine above but only checks regions in the
|
|
||||||
// current collection set.
|
|
||||||
bool check_cset_heap_region_claim_values(jint claim_value);
|
|
||||||
#endif // ASSERT
|
|
||||||
|
|
||||||
// Clear the cached cset start regions and (more importantly)
|
// Clear the cached cset start regions and (more importantly)
|
||||||
// the time stamps. Called when we reset the GC time stamp.
|
// the time stamps. Called when we reset the GC time stamp.
|
||||||
|
@ -1598,19 +1598,17 @@ class ParKnownGarbageTask: public AbstractGangTask {
|
|||||||
CollectionSetChooser* _hrSorted;
|
CollectionSetChooser* _hrSorted;
|
||||||
uint _chunk_size;
|
uint _chunk_size;
|
||||||
G1CollectedHeap* _g1;
|
G1CollectedHeap* _g1;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size) :
|
ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size, uint n_workers) :
|
||||||
AbstractGangTask("ParKnownGarbageTask"),
|
AbstractGangTask("ParKnownGarbageTask"),
|
||||||
_hrSorted(hrSorted), _chunk_size(chunk_size),
|
_hrSorted(hrSorted), _chunk_size(chunk_size),
|
||||||
_g1(G1CollectedHeap::heap()) { }
|
_g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) {}
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size);
|
ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size);
|
||||||
|
_g1->heap_region_par_iterate(&parKnownGarbageCl, worker_id, &_hrclaimer);
|
||||||
// Back to zero for the claim value.
|
|
||||||
_g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id,
|
|
||||||
_g1->workers()->active_workers(),
|
|
||||||
HeapRegion::InitialClaimValue);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1641,12 +1639,8 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
|
|||||||
}
|
}
|
||||||
_collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(),
|
_collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(),
|
||||||
WorkUnit);
|
WorkUnit);
|
||||||
ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
|
ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, WorkUnit, (uint) no_of_gc_threads);
|
||||||
(int) WorkUnit);
|
|
||||||
_g1->workers()->run_task(&parKnownGarbageTask);
|
_g1->workers()->run_task(&parKnownGarbageTask);
|
||||||
|
|
||||||
assert(_g1->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
|
||||||
"sanity check");
|
|
||||||
} else {
|
} else {
|
||||||
KnownGarbageClosure knownGarbagecl(_collectionSetChooser);
|
KnownGarbageClosure knownGarbagecl(_collectionSetChooser);
|
||||||
_g1->heap_region_iterate(&knownGarbagecl);
|
_g1->heap_region_iterate(&knownGarbagecl);
|
||||||
|
@ -177,16 +177,18 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
|
|||||||
G1CollectedHeap* _g1h;
|
G1CollectedHeap* _g1h;
|
||||||
ConcurrentMark* _cm;
|
ConcurrentMark* _cm;
|
||||||
uint _worker_id;
|
uint _worker_id;
|
||||||
|
HeapRegionClaimer* _hrclaimer;
|
||||||
|
|
||||||
DirtyCardQueue _dcq;
|
DirtyCardQueue _dcq;
|
||||||
UpdateRSetDeferred _update_rset_cl;
|
UpdateRSetDeferred _update_rset_cl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h,
|
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h,
|
||||||
uint worker_id) :
|
uint worker_id,
|
||||||
_g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq),
|
HeapRegionClaimer* hrclaimer) :
|
||||||
_worker_id(worker_id), _cm(_g1h->concurrent_mark()) {
|
_g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq),
|
||||||
}
|
_worker_id(worker_id), _cm(_g1h->concurrent_mark()), _hrclaimer(hrclaimer) {
|
||||||
|
}
|
||||||
|
|
||||||
bool doHeapRegion(HeapRegion *hr) {
|
bool doHeapRegion(HeapRegion *hr) {
|
||||||
bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause();
|
bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause();
|
||||||
@ -195,7 +197,7 @@ public:
|
|||||||
assert(!hr->is_humongous(), "sanity");
|
assert(!hr->is_humongous(), "sanity");
|
||||||
assert(hr->in_collection_set(), "bad CS");
|
assert(hr->in_collection_set(), "bad CS");
|
||||||
|
|
||||||
if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) {
|
if (_hrclaimer->claim_region(hr->hrm_index())) {
|
||||||
if (hr->evacuation_failed()) {
|
if (hr->evacuation_failed()) {
|
||||||
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl,
|
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl,
|
||||||
during_initial_mark,
|
during_initial_mark,
|
||||||
@ -233,14 +235,15 @@ public:
|
|||||||
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
|
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
|
||||||
protected:
|
protected:
|
||||||
G1CollectedHeap* _g1h;
|
G1CollectedHeap* _g1h;
|
||||||
|
HeapRegionClaimer _hrclaimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) :
|
G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) :
|
||||||
AbstractGangTask("G1 Remove Self-forwarding Pointers"),
|
AbstractGangTask("G1 Remove Self-forwarding Pointers"), _g1h(g1h),
|
||||||
_g1h(g1h) { }
|
_hrclaimer(g1h->workers()->active_workers()) {}
|
||||||
|
|
||||||
void work(uint worker_id) {
|
void work(uint worker_id) {
|
||||||
RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id);
|
RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id, &_hrclaimer);
|
||||||
|
|
||||||
HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
|
HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id);
|
||||||
_g1h->collection_set_iterate_from(hr, &rsfp_cl);
|
_g1h->collection_set_iterate_from(hr, &rsfp_cl);
|
||||||
|
@ -425,13 +425,9 @@ void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
|
|||||||
_g1->heap_region_iterate(&scrub_cl);
|
_g1->heap_region_iterate(&scrub_cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
|
void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) {
|
||||||
uint worker_num, int claim_val) {
|
|
||||||
ScrubRSClosure scrub_cl(region_bm, card_bm);
|
ScrubRSClosure scrub_cl(region_bm, card_bm);
|
||||||
_g1->heap_region_par_iterate_chunked(&scrub_cl,
|
_g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
|
||||||
worker_num,
|
|
||||||
n_workers(),
|
|
||||||
claim_val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G1TriggerClosure::G1TriggerClosure() :
|
G1TriggerClosure::G1TriggerClosure() :
|
||||||
|
@ -128,10 +128,10 @@ public:
|
|||||||
void scrub(BitMap* region_bm, BitMap* card_bm);
|
void scrub(BitMap* region_bm, BitMap* card_bm);
|
||||||
|
|
||||||
// Like the above, but assumes is called in parallel: "worker_num" is the
|
// Like the above, but assumes is called in parallel: "worker_num" is the
|
||||||
// parallel thread id of the current thread, and "claim_val" is the
|
// parallel thread id of the current thread, and "hrclaimer" is the shared
|
||||||
// value that should be used to claim heap regions.
|
// HeapRegionClaimer that should be used to claim heap regions.
|
||||||
void scrub_par(BitMap* region_bm, BitMap* card_bm,
|
void scrub_par(BitMap* region_bm, BitMap* card_bm,
|
||||||
uint worker_num, int claim_val);
|
uint worker_num, HeapRegionClaimer* hrclaimer);
|
||||||
|
|
||||||
// Refine the card corresponding to "card_ptr".
|
// Refine the card corresponding to "card_ptr".
|
||||||
// If check_for_refs_into_cset is true, a true result is returned
|
// If check_for_refs_into_cset is true, a true result is returned
|
||||||
|
@ -217,7 +217,6 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) {
|
|||||||
} else {
|
} else {
|
||||||
hrrs->clear();
|
hrrs->clear();
|
||||||
}
|
}
|
||||||
_claimed = InitialClaimValue;
|
|
||||||
}
|
}
|
||||||
zero_marked_bytes();
|
zero_marked_bytes();
|
||||||
|
|
||||||
@ -294,17 +293,6 @@ void HeapRegion::clear_humongous() {
|
|||||||
_humongous_start_region = NULL;
|
_humongous_start_region = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeapRegion::claimHeapRegion(jint claimValue) {
|
|
||||||
jint current = _claimed;
|
|
||||||
if (current != claimValue) {
|
|
||||||
jint res = Atomic::cmpxchg(claimValue, &_claimed, current);
|
|
||||||
if (res == current) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapRegion::HeapRegion(uint hrm_index,
|
HeapRegion::HeapRegion(uint hrm_index,
|
||||||
G1BlockOffsetSharedArray* sharedOffsetArray,
|
G1BlockOffsetSharedArray* sharedOffsetArray,
|
||||||
MemRegion mr) :
|
MemRegion mr) :
|
||||||
@ -314,7 +302,7 @@ HeapRegion::HeapRegion(uint hrm_index,
|
|||||||
_humongous_start_region(NULL),
|
_humongous_start_region(NULL),
|
||||||
_in_collection_set(false),
|
_in_collection_set(false),
|
||||||
_next_in_special_set(NULL),
|
_next_in_special_set(NULL),
|
||||||
_claimed(InitialClaimValue), _evacuation_failed(false),
|
_evacuation_failed(false),
|
||||||
_prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
|
_prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
|
||||||
_next_young_region(NULL),
|
_next_young_region(NULL),
|
||||||
_next_dirty_cards_region(NULL), _next(NULL), _prev(NULL),
|
_next_dirty_cards_region(NULL), _next(NULL), _prev(NULL),
|
||||||
|
@ -254,9 +254,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||||||
HeapRegionSetBase* _containing_set;
|
HeapRegionSetBase* _containing_set;
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
// For parallel heapRegion traversal.
|
|
||||||
jint _claimed;
|
|
||||||
|
|
||||||
// We use concurrent marking to determine the amount of live data
|
// We use concurrent marking to determine the amount of live data
|
||||||
// in each heap region.
|
// in each heap region.
|
||||||
size_t _prev_marked_bytes; // Bytes known to be live via last completed marking.
|
size_t _prev_marked_bytes; // Bytes known to be live via last completed marking.
|
||||||
@ -336,19 +333,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||||||
// up once during initialization time.
|
// up once during initialization time.
|
||||||
static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size);
|
static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size);
|
||||||
|
|
||||||
enum ClaimValues {
|
|
||||||
InitialClaimValue = 0,
|
|
||||||
FinalCountClaimValue = 1,
|
|
||||||
NoteEndClaimValue = 2,
|
|
||||||
ScrubRemSetClaimValue = 3,
|
|
||||||
ParVerifyClaimValue = 4,
|
|
||||||
RebuildRSClaimValue = 5,
|
|
||||||
ParEvacFailureClaimValue = 6,
|
|
||||||
AggregateCountClaimValue = 7,
|
|
||||||
VerifyCountClaimValue = 8,
|
|
||||||
ParMarkRootClaimValue = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
// All allocated blocks are occupied by objects in a HeapRegion
|
// All allocated blocks are occupied by objects in a HeapRegion
|
||||||
bool block_is_obj(const HeapWord* p) const;
|
bool block_is_obj(const HeapWord* p) const;
|
||||||
|
|
||||||
@ -691,12 +675,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
|||||||
return (HeapWord *) obj >= next_top_at_mark_start();
|
return (HeapWord *) obj >= next_top_at_mark_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For parallel heapRegion traversal.
|
|
||||||
bool claimHeapRegion(int claimValue);
|
|
||||||
jint claim_value() { return _claimed; }
|
|
||||||
// Use this carefully: only when you're sure no one is claiming...
|
|
||||||
void set_claim_value(int claimValue) { _claimed = claimValue; }
|
|
||||||
|
|
||||||
// Returns the "evacuation_failed" property of the region.
|
// Returns the "evacuation_failed" property of the region.
|
||||||
bool evacuation_failed() { return _evacuation_failed; }
|
bool evacuation_failed() { return _evacuation_failed; }
|
||||||
|
|
||||||
|
@ -260,20 +260,17 @@ uint HeapRegionManager::find_unavailable_from_idx(uint start_idx, uint* res_idx)
|
|||||||
return num_regions;
|
return num_regions;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint HeapRegionManager::start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const {
|
void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const {
|
||||||
return num_regions * worker_i / num_workers;
|
const uint start_index = hrclaimer->start_region_for_worker(worker_id);
|
||||||
}
|
|
||||||
|
|
||||||
void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const {
|
|
||||||
const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length);
|
|
||||||
|
|
||||||
// Every worker will actually look at all regions, skipping over regions that
|
// Every worker will actually look at all regions, skipping over regions that
|
||||||
// are currently not committed.
|
// are currently not committed.
|
||||||
// This also (potentially) iterates over regions newly allocated during GC. This
|
// This also (potentially) iterates over regions newly allocated during GC. This
|
||||||
// is no problem except for some extra work.
|
// is no problem except for some extra work.
|
||||||
for (uint count = 0; count < _allocated_heapregions_length; count++) {
|
const uint n_regions = hrclaimer->n_regions();
|
||||||
const uint index = (start_index + count) % _allocated_heapregions_length;
|
for (uint count = 0; count < n_regions; count++) {
|
||||||
assert(0 <= index && index < _allocated_heapregions_length, "sanity");
|
const uint index = (start_index + count) % n_regions;
|
||||||
|
assert(0 <= index && index < n_regions, "sanity");
|
||||||
// Skip over unavailable regions
|
// Skip over unavailable regions
|
||||||
if (!is_available(index)) {
|
if (!is_available(index)) {
|
||||||
continue;
|
continue;
|
||||||
@ -282,11 +279,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint
|
|||||||
// We'll ignore "continues humongous" regions (we'll process them
|
// We'll ignore "continues humongous" regions (we'll process them
|
||||||
// when we come across their corresponding "start humongous"
|
// when we come across their corresponding "start humongous"
|
||||||
// region) and regions already claimed.
|
// region) and regions already claimed.
|
||||||
if (r->claim_value() == claim_value || r->is_continues_humongous()) {
|
if (hrclaimer->is_region_claimed(index) || r->is_continues_humongous()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// OK, try to claim it
|
// OK, try to claim it
|
||||||
if (!r->claimHeapRegion(claim_value)) {
|
if (!hrclaimer->claim_region(index)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
@ -306,13 +303,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint
|
|||||||
assert(chr->humongous_start_region() == r,
|
assert(chr->humongous_start_region() == r,
|
||||||
err_msg("Must work on humongous continuation of the original start region "
|
err_msg("Must work on humongous continuation of the original start region "
|
||||||
PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr)));
|
PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr)));
|
||||||
assert(chr->claim_value() != claim_value,
|
assert(!hrclaimer->is_region_claimed(ch_index),
|
||||||
"Must not have been claimed yet because claiming of humongous continuation first claims the start region");
|
"Must not have been claimed yet because claiming of humongous continuation first claims the start region");
|
||||||
|
|
||||||
bool claim_result = chr->claimHeapRegion(claim_value);
|
// There's no need to actually claim the continues humongous region, but we can do it in an assert as an extra precaution.
|
||||||
// We should always be able to claim it; no one else should
|
assert(hrclaimer->claim_region(ch_index), "We should always be able to claim the continuesHumongous part of the humongous object");
|
||||||
// be trying to claim this region.
|
|
||||||
guarantee(claim_result, "We should always be able to claim the is_continues_humongous part of the humongous object");
|
|
||||||
|
|
||||||
bool res2 = blk->doHeapRegion(chr);
|
bool res2 = blk->doHeapRegion(chr);
|
||||||
if (res2) {
|
if (res2) {
|
||||||
@ -445,3 +440,31 @@ void HeapRegionManager::verify_optional() {
|
|||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
|
HeapRegionClaimer::HeapRegionClaimer(uint n_workers) :
|
||||||
|
_n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) {
|
||||||
|
assert(n_workers > 0, "Need at least one worker.");
|
||||||
|
_claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC);
|
||||||
|
memset(_claims, Unclaimed, sizeof(*_claims) * _n_regions);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapRegionClaimer::~HeapRegionClaimer() {
|
||||||
|
if (_claims != NULL) {
|
||||||
|
FREE_C_HEAP_ARRAY(uint, _claims, mtGC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint HeapRegionClaimer::start_region_for_worker(uint worker_id) const {
|
||||||
|
assert(worker_id < _n_workers, "Invalid worker_id.");
|
||||||
|
return _n_regions * worker_id / _n_workers;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeapRegionClaimer::is_region_claimed(uint region_index) const {
|
||||||
|
assert(region_index < _n_regions, "Invalid index.");
|
||||||
|
return _claims[region_index] == Claimed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeapRegionClaimer::claim_region(uint region_index) {
|
||||||
|
assert(region_index < _n_regions, "Invalid index.");
|
||||||
|
uint old_val = Atomic::cmpxchg(Claimed, &_claims[region_index], Unclaimed);
|
||||||
|
return old_val == Unclaimed;
|
||||||
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
class HeapRegion;
|
class HeapRegion;
|
||||||
class HeapRegionClosure;
|
class HeapRegionClosure;
|
||||||
|
class HeapRegionClaimer;
|
||||||
class FreeRegionList;
|
class FreeRegionList;
|
||||||
|
|
||||||
class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
|
class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
|
||||||
@ -66,6 +67,7 @@ class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
|
|||||||
|
|
||||||
class HeapRegionManager: public CHeapObj<mtGC> {
|
class HeapRegionManager: public CHeapObj<mtGC> {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
friend class HeapRegionClaimer;
|
||||||
|
|
||||||
G1HeapRegionTable _regions;
|
G1HeapRegionTable _regions;
|
||||||
|
|
||||||
@ -99,9 +101,6 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
|||||||
|
|
||||||
// Notify other data structures about change in the heap layout.
|
// Notify other data structures about change in the heap layout.
|
||||||
void update_committed_space(HeapWord* old_end, HeapWord* new_end);
|
void update_committed_space(HeapWord* old_end, HeapWord* new_end);
|
||||||
// Calculate the starting region for each worker during parallel iteration so
|
|
||||||
// that they do not all start from the same region.
|
|
||||||
uint start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const;
|
|
||||||
|
|
||||||
// Find a contiguous set of empty or uncommitted regions of length num and return
|
// Find a contiguous set of empty or uncommitted regions of length num and return
|
||||||
// the index of the first region or G1_NO_HRM_INDEX if the search was unsuccessful.
|
// the index of the first region or G1_NO_HRM_INDEX if the search was unsuccessful.
|
||||||
@ -223,7 +222,7 @@ public:
|
|||||||
// terminating the iteration early if doHeapRegion() returns true.
|
// terminating the iteration early if doHeapRegion() returns true.
|
||||||
void iterate(HeapRegionClosure* blk) const;
|
void iterate(HeapRegionClosure* blk) const;
|
||||||
|
|
||||||
void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const;
|
void par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const;
|
||||||
|
|
||||||
// Uncommit up to num_regions_to_remove regions that are completely free.
|
// Uncommit up to num_regions_to_remove regions that are completely free.
|
||||||
// Return the actual number of uncommitted regions.
|
// Return the actual number of uncommitted regions.
|
||||||
@ -235,5 +234,33 @@ public:
|
|||||||
void verify_optional() PRODUCT_RETURN;
|
void verify_optional() PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The HeapRegionClaimer is used during parallel iteration over heap regions,
|
||||||
|
// allowing workers to claim heap regions, gaining exclusive rights to these regions.
|
||||||
|
class HeapRegionClaimer : public StackObj {
|
||||||
|
uint _n_workers;
|
||||||
|
uint _n_regions;
|
||||||
|
uint* _claims;
|
||||||
|
|
||||||
|
static const uint Unclaimed = 0;
|
||||||
|
static const uint Claimed = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
HeapRegionClaimer(uint n_workers);
|
||||||
|
~HeapRegionClaimer();
|
||||||
|
|
||||||
|
inline uint n_regions() const {
|
||||||
|
return _n_regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the starting region for given worker so
|
||||||
|
// that they do not all start from the same region.
|
||||||
|
uint start_region_for_worker(uint worker_id) const;
|
||||||
|
|
||||||
|
// Check if region has been claimed with this HRClaimer.
|
||||||
|
bool is_region_claimed(uint region_index) const;
|
||||||
|
|
||||||
|
// Claim the given region, returns true if successfully claimed.
|
||||||
|
bool claim_region(uint region_index);
|
||||||
|
};
|
||||||
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONMANAGER_HPP
|
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONMANAGER_HPP
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user