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;
|
||||
bool _verbose;
|
||||
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1ParVerifyFinalCountTask(G1CollectedHeap* g1h,
|
||||
BitMap* region_bm, BitMap* card_bm,
|
||||
@ -1692,19 +1694,8 @@ public:
|
||||
_actual_region_bm(region_bm), _actual_card_bm(card_bm),
|
||||
_expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm),
|
||||
_failures(0), _verbose(false),
|
||||
_n_workers(0) {
|
||||
_n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) {
|
||||
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_region_bm->size() == _actual_region_bm->size(), "sanity");
|
||||
|
||||
@ -1721,10 +1712,7 @@ public:
|
||||
_verbose);
|
||||
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
_g1h->heap_region_par_iterate_chunked(&verify_cl,
|
||||
worker_id,
|
||||
_n_workers,
|
||||
HeapRegion::VerifyCountClaimValue);
|
||||
_g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer);
|
||||
} else {
|
||||
_g1h->heap_region_iterate(&verify_cl);
|
||||
}
|
||||
@ -1813,22 +1801,14 @@ protected:
|
||||
BitMap* _actual_card_bm;
|
||||
|
||||
uint _n_workers;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm)
|
||||
: AbstractGangTask("G1 final counting"),
|
||||
_g1h(g1h), _cm(_g1h->concurrent_mark()),
|
||||
_actual_region_bm(region_bm), _actual_card_bm(card_bm),
|
||||
_n_workers(0) {
|
||||
// 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;
|
||||
}
|
||||
_n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
@ -1839,10 +1819,7 @@ public:
|
||||
_actual_card_bm);
|
||||
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
_g1h->heap_region_par_iterate_chunked(&final_update_cl,
|
||||
worker_id,
|
||||
_n_workers,
|
||||
HeapRegion::FinalCountClaimValue);
|
||||
_g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer);
|
||||
} else {
|
||||
_g1h->heap_region_iterate(&final_update_cl);
|
||||
}
|
||||
@ -1929,12 +1906,12 @@ protected:
|
||||
size_t _max_live_bytes;
|
||||
size_t _freed_bytes;
|
||||
FreeRegionList* _cleanup_list;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1ParNoteEndTask(G1CollectedHeap* g1h,
|
||||
FreeRegionList* cleanup_list) :
|
||||
AbstractGangTask("G1 note end"), _g1h(g1h),
|
||||
_max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
|
||||
G1ParNoteEndTask(G1CollectedHeap* g1h, FreeRegionList* cleanup_list, uint n_workers) :
|
||||
AbstractGangTask("G1 note end"), _g1h(g1h), _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list), _hrclaimer(n_workers) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
double start = os::elapsedTime();
|
||||
@ -1943,9 +1920,7 @@ public:
|
||||
G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list,
|
||||
&hrrs_cleanup_task);
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
_g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id,
|
||||
_g1h->workers()->active_workers(),
|
||||
HeapRegion::NoteEndClaimValue);
|
||||
_g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer);
|
||||
} else {
|
||||
_g1h->heap_region_iterate(&g1_note_end);
|
||||
}
|
||||
@ -1991,16 +1966,16 @@ protected:
|
||||
G1RemSet* _g1rs;
|
||||
BitMap* _region_bm;
|
||||
BitMap* _card_bm;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1ParScrubRemSetTask(G1CollectedHeap* g1h,
|
||||
BitMap* region_bm, BitMap* card_bm) :
|
||||
AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()),
|
||||
_region_bm(region_bm), _card_bm(card_bm) { }
|
||||
G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, uint n_workers) :
|
||||
AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
_g1rs->scrub_par(_region_bm, _card_bm, worker_id,
|
||||
HeapRegion::ScrubRemSetClaimValue);
|
||||
_g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer);
|
||||
} else {
|
||||
_g1rs->scrub(_region_bm, _card_bm);
|
||||
}
|
||||
@ -2043,9 +2018,6 @@ void ConcurrentMark::cleanup() {
|
||||
G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm);
|
||||
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
assert(g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
||||
"sanity check");
|
||||
|
||||
g1h->set_par_threads();
|
||||
n_workers = g1h->n_par_threads();
|
||||
assert(g1h->n_par_threads() == n_workers,
|
||||
@ -2053,9 +2025,6 @@ void ConcurrentMark::cleanup() {
|
||||
g1h->workers()->run_task(&g1_par_count_task);
|
||||
// Done with the parallel phase so reset to 0.
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
assert(g1h->check_heap_region_claim_values(HeapRegion::FinalCountClaimValue),
|
||||
"sanity check");
|
||||
} else {
|
||||
n_workers = 1;
|
||||
g1_par_count_task.work(0);
|
||||
@ -2080,9 +2049,6 @@ void ConcurrentMark::cleanup() {
|
||||
g1h->workers()->run_task(&g1_par_verify_task);
|
||||
// Done with the parallel phase so reset to 0.
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
assert(g1h->check_heap_region_claim_values(HeapRegion::VerifyCountClaimValue),
|
||||
"sanity check");
|
||||
} else {
|
||||
g1_par_verify_task.work(0);
|
||||
}
|
||||
@ -2108,14 +2074,11 @@ void ConcurrentMark::cleanup() {
|
||||
g1h->reset_gc_time_stamp();
|
||||
|
||||
// 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()) {
|
||||
g1h->set_par_threads((int)n_workers);
|
||||
g1h->workers()->run_task(&g1_par_note_end_task);
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue),
|
||||
"sanity check");
|
||||
} else {
|
||||
g1_par_note_end_task.work(0);
|
||||
}
|
||||
@ -2132,15 +2095,11 @@ void ConcurrentMark::cleanup() {
|
||||
// regions.
|
||||
if (G1ScrubRemSets) {
|
||||
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()) {
|
||||
g1h->set_par_threads((int)n_workers);
|
||||
g1h->workers()->run_task(&g1_par_scrub_rs_task);
|
||||
g1h->set_par_threads(0);
|
||||
|
||||
assert(g1h->check_heap_region_claim_values(
|
||||
HeapRegion::ScrubRemSetClaimValue),
|
||||
"sanity check");
|
||||
} else {
|
||||
g1_par_scrub_rs_task.work(0);
|
||||
}
|
||||
@ -3288,6 +3247,7 @@ protected:
|
||||
BitMap* _cm_card_bm;
|
||||
uint _max_worker_id;
|
||||
int _active_workers;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1AggregateCountDataTask(G1CollectedHeap* g1h,
|
||||
@ -3295,18 +3255,18 @@ public:
|
||||
BitMap* cm_card_bm,
|
||||
uint max_worker_id,
|
||||
int n_workers) :
|
||||
AbstractGangTask("Count Aggregation"),
|
||||
_g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
|
||||
_max_worker_id(max_worker_id),
|
||||
_active_workers(n_workers) { }
|
||||
AbstractGangTask("Count Aggregation"),
|
||||
_g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm),
|
||||
_max_worker_id(max_worker_id),
|
||||
_active_workers(n_workers),
|
||||
_hrclaimer(_active_workers) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id);
|
||||
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
_g1h->heap_region_par_iterate_chunked(&cl, worker_id,
|
||||
_active_workers,
|
||||
HeapRegion::AggregateCountClaimValue);
|
||||
_g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer);
|
||||
} else {
|
||||
_g1h->heap_region_iterate(&cl);
|
||||
}
|
||||
@ -3323,15 +3283,9 @@ void ConcurrentMark::aggregate_count_data() {
|
||||
_max_worker_id, n_workers);
|
||||
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
assert(_g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
||||
"sanity check");
|
||||
_g1h->set_par_threads(n_workers);
|
||||
_g1h->workers()->run_task(&g1_par_agg_task);
|
||||
_g1h->set_par_threads(0);
|
||||
|
||||
assert(_g1h->check_heap_region_claim_values(HeapRegion::AggregateCountClaimValue),
|
||||
"sanity check");
|
||||
_g1h->reset_heap_region_claim_values();
|
||||
} else {
|
||||
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.
|
||||
//
|
||||
// G1ParVerifyTask uses heap_region_par_iterate_chunked() for parallelism.
|
||||
// The number of GC workers is passed to heap_region_par_iterate_chunked().
|
||||
// G1ParVerifyTask uses heap_region_par_iterate() for parallelism.
|
||||
// The number of GC workers is passed to heap_region_par_iterate().
|
||||
// It does use run_task() which sets _n_workers in the task.
|
||||
// G1ParTask executes g1_process_roots() ->
|
||||
// SharedHeap::process_roots() which calls eventually to
|
||||
@ -1215,17 +1215,15 @@ public:
|
||||
|
||||
class ParRebuildRSTask: public AbstractGangTask {
|
||||
G1CollectedHeap* _g1;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
ParRebuildRSTask(G1CollectedHeap* g1)
|
||||
: AbstractGangTask("ParRebuildRSTask"),
|
||||
_g1(g1)
|
||||
{ }
|
||||
ParRebuildRSTask(G1CollectedHeap* g1) :
|
||||
AbstractGangTask("ParRebuildRSTask"), _g1(g1), _hrclaimer(g1->workers()->active_workers()) {}
|
||||
|
||||
void work(uint worker_id) {
|
||||
RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id);
|
||||
_g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id,
|
||||
_g1->workers()->active_workers(),
|
||||
HeapRegion::RebuildRSClaimValue);
|
||||
_g1->heap_region_par_iterate(&rebuild_rs, worker_id, &_hrclaimer);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1455,8 +1453,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
|
||||
set_par_threads(n_workers);
|
||||
|
||||
ParRebuildRSTask rebuild_rs_task(this);
|
||||
assert(check_heap_region_claim_values(
|
||||
HeapRegion::InitialClaimValue), "sanity check");
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
workers()->active_workers() == workers()->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());
|
||||
workers()->run_task(&rebuild_rs_task);
|
||||
set_par_threads(0);
|
||||
assert(check_heap_region_claim_values(
|
||||
HeapRegion::RebuildRSClaimValue), "sanity check");
|
||||
reset_heap_region_claim_values();
|
||||
} else {
|
||||
RebuildRSOutOfRegionClosure rebuild_rs(this);
|
||||
heap_region_iterate(&rebuild_rs);
|
||||
@ -2634,111 +2627,12 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
|
||||
}
|
||||
|
||||
void
|
||||
G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl,
|
||||
uint worker_id,
|
||||
uint num_workers,
|
||||
jint claim_value) const {
|
||||
_hrm.par_iterate(cl, worker_id, num_workers, claim_value);
|
||||
G1CollectedHeap::heap_region_par_iterate(HeapRegionClosure* cl,
|
||||
uint worker_id,
|
||||
HeapRegionClaimer *hrclaimer) const {
|
||||
_hrm.par_iterate(cl, worker_id, hrclaimer);
|
||||
}
|
||||
|
||||
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)
|
||||
// the time stamps. Called when we reset the GC time stamp.
|
||||
void G1CollectedHeap::clear_cset_start_regions() {
|
||||
@ -3252,19 +3146,21 @@ public:
|
||||
|
||||
class G1ParVerifyTask: public AbstractGangTask {
|
||||
private:
|
||||
G1CollectedHeap* _g1h;
|
||||
VerifyOption _vo;
|
||||
bool _failures;
|
||||
G1CollectedHeap* _g1h;
|
||||
VerifyOption _vo;
|
||||
bool _failures;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
// _vo == UsePrevMarking -> use "prev" marking information,
|
||||
// _vo == UseNextMarking -> use "next" marking information,
|
||||
// _vo == UseMarkWord -> use mark word from object header.
|
||||
G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) :
|
||||
AbstractGangTask("Parallel verify task"),
|
||||
_g1h(g1h),
|
||||
_vo(vo),
|
||||
_failures(false) { }
|
||||
AbstractGangTask("Parallel verify task"),
|
||||
_g1h(g1h),
|
||||
_vo(vo),
|
||||
_failures(false),
|
||||
_hrclaimer(g1h->workers()->active_workers()) {}
|
||||
|
||||
bool failures() {
|
||||
return _failures;
|
||||
@ -3273,9 +3169,7 @@ public:
|
||||
void work(uint worker_id) {
|
||||
HandleMark hm;
|
||||
VerifyRegionClosure blk(true, _vo);
|
||||
_g1h->heap_region_par_iterate_chunked(&blk, worker_id,
|
||||
_g1h->workers()->active_workers(),
|
||||
HeapRegion::ParVerifyClaimValue);
|
||||
_g1h->heap_region_par_iterate(&blk, worker_id, &_hrclaimer);
|
||||
if (blk.failures()) {
|
||||
_failures = true;
|
||||
}
|
||||
@ -3317,8 +3211,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
|
||||
|
||||
if (!silent) { gclog_or_tty->print("HeapRegions "); }
|
||||
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
|
||||
assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
||||
"sanity check");
|
||||
|
||||
G1ParVerifyTask task(this, vo);
|
||||
assert(UseDynamicNumberOfGCThreads ||
|
||||
@ -3332,15 +3224,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) {
|
||||
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 {
|
||||
VerifyRegionClosure blk(false, vo);
|
||||
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_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
||||
"sanity check");
|
||||
|
||||
// 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,
|
||||
@ -4289,26 +4170,12 @@ void G1CollectedHeap::finalize_for_evac_failure() {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::remove_self_forwarding_pointers() {
|
||||
assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
|
||||
|
||||
double remove_self_forwards_start = os::elapsedTime();
|
||||
|
||||
set_par_threads();
|
||||
G1ParRemoveSelfForwardPtrsTask rsfp_task(this);
|
||||
|
||||
if (G1CollectedHeap::use_parallel_gc_threads()) {
|
||||
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");
|
||||
workers()->run_task(&rsfp_task);
|
||||
set_par_threads(0);
|
||||
|
||||
// Now restore saved marks, if any.
|
||||
assert(_objs_with_preserved_marks.size() ==
|
||||
@ -5949,11 +5816,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) {
|
||||
|
||||
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();
|
||||
|
||||
if (evacuation_failed()) {
|
||||
|
@ -211,6 +211,7 @@ class G1CollectedHeap : public SharedHeap {
|
||||
friend class G1FreeHumongousRegionClosure;
|
||||
// Other related classes.
|
||||
friend class G1MarkSweep;
|
||||
friend class HeapRegionClaimer;
|
||||
|
||||
private:
|
||||
// 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;
|
||||
|
||||
// Divide the heap region sequence into "chunks" of some size (the number
|
||||
// of regions divided by the number of parallel threads times some
|
||||
// overpartition factor, currently 4). Assumes that this will be called
|
||||
// in parallel by ParallelGCThreads worker threads with distinct worker
|
||||
// ids in the range [0..max(ParallelGCThreads-1, 1)], that all parallel
|
||||
// calls will use the same "claim_value", and that that claim value is
|
||||
// different from the claim_value of any heap region before the start of
|
||||
// the iteration. Applies "blk->doHeapRegion" to each of the regions, by
|
||||
// attempting to claim the first region in each chunk, and, if
|
||||
// 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
|
||||
// Iterate over the heap regions in parallel. Assumes that this will be called
|
||||
// in parallel by ParallelGCThreads worker threads with distinct worker ids
|
||||
// in the range [0..max(ParallelGCThreads-1, 1)]. Applies "blk->doHeapRegion"
|
||||
// to each of the regions, by attempting to claim the region using the
|
||||
// HeapRegionClaimer and, if successful, applying the closure to the claimed
|
||||
// region.
|
||||
void heap_region_par_iterate(HeapRegionClosure* cl,
|
||||
uint worker_id,
|
||||
HeapRegionClaimer* hrclaimer) const;
|
||||
|
||||
// Clear the cached cset start regions and (more importantly)
|
||||
// the time stamps. Called when we reset the GC time stamp.
|
||||
|
@ -1598,19 +1598,17 @@ class ParKnownGarbageTask: public AbstractGangTask {
|
||||
CollectionSetChooser* _hrSorted;
|
||||
uint _chunk_size;
|
||||
G1CollectedHeap* _g1;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size) :
|
||||
AbstractGangTask("ParKnownGarbageTask"),
|
||||
_hrSorted(hrSorted), _chunk_size(chunk_size),
|
||||
_g1(G1CollectedHeap::heap()) { }
|
||||
ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size, uint n_workers) :
|
||||
AbstractGangTask("ParKnownGarbageTask"),
|
||||
_hrSorted(hrSorted), _chunk_size(chunk_size),
|
||||
_g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) {}
|
||||
|
||||
void work(uint worker_id) {
|
||||
ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size);
|
||||
|
||||
// Back to zero for the claim value.
|
||||
_g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id,
|
||||
_g1->workers()->active_workers(),
|
||||
HeapRegion::InitialClaimValue);
|
||||
_g1->heap_region_par_iterate(&parKnownGarbageCl, worker_id, &_hrclaimer);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1641,12 +1639,8 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
|
||||
}
|
||||
_collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(),
|
||||
WorkUnit);
|
||||
ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
|
||||
(int) WorkUnit);
|
||||
ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, WorkUnit, (uint) no_of_gc_threads);
|
||||
_g1->workers()->run_task(&parKnownGarbageTask);
|
||||
|
||||
assert(_g1->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
|
||||
"sanity check");
|
||||
} else {
|
||||
KnownGarbageClosure knownGarbagecl(_collectionSetChooser);
|
||||
_g1->heap_region_iterate(&knownGarbagecl);
|
||||
|
@ -177,16 +177,18 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1h;
|
||||
ConcurrentMark* _cm;
|
||||
uint _worker_id;
|
||||
HeapRegionClaimer* _hrclaimer;
|
||||
|
||||
DirtyCardQueue _dcq;
|
||||
UpdateRSetDeferred _update_rset_cl;
|
||||
|
||||
public:
|
||||
RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h,
|
||||
uint worker_id) :
|
||||
_g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq),
|
||||
_worker_id(worker_id), _cm(_g1h->concurrent_mark()) {
|
||||
}
|
||||
uint worker_id,
|
||||
HeapRegionClaimer* hrclaimer) :
|
||||
_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 during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause();
|
||||
@ -195,7 +197,7 @@ public:
|
||||
assert(!hr->is_humongous(), "sanity");
|
||||
assert(hr->in_collection_set(), "bad CS");
|
||||
|
||||
if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) {
|
||||
if (_hrclaimer->claim_region(hr->hrm_index())) {
|
||||
if (hr->evacuation_failed()) {
|
||||
RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl,
|
||||
during_initial_mark,
|
||||
@ -233,14 +235,15 @@ public:
|
||||
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
|
||||
protected:
|
||||
G1CollectedHeap* _g1h;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
||||
public:
|
||||
G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) :
|
||||
AbstractGangTask("G1 Remove Self-forwarding Pointers"),
|
||||
_g1h(g1h) { }
|
||||
AbstractGangTask("G1 Remove Self-forwarding Pointers"), _g1h(g1h),
|
||||
_hrclaimer(g1h->workers()->active_workers()) {}
|
||||
|
||||
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);
|
||||
_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);
|
||||
}
|
||||
|
||||
void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
|
||||
uint worker_num, int claim_val) {
|
||||
void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) {
|
||||
ScrubRSClosure scrub_cl(region_bm, card_bm);
|
||||
_g1->heap_region_par_iterate_chunked(&scrub_cl,
|
||||
worker_num,
|
||||
n_workers(),
|
||||
claim_val);
|
||||
_g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer);
|
||||
}
|
||||
|
||||
G1TriggerClosure::G1TriggerClosure() :
|
||||
|
@ -128,10 +128,10 @@ public:
|
||||
void scrub(BitMap* region_bm, BitMap* card_bm);
|
||||
|
||||
// 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
|
||||
// value that should be used to claim heap regions.
|
||||
// parallel thread id of the current thread, and "hrclaimer" is the shared
|
||||
// HeapRegionClaimer that should be used to claim heap regions.
|
||||
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".
|
||||
// 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 {
|
||||
hrrs->clear();
|
||||
}
|
||||
_claimed = InitialClaimValue;
|
||||
}
|
||||
zero_marked_bytes();
|
||||
|
||||
@ -294,17 +293,6 @@ void HeapRegion::clear_humongous() {
|
||||
_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,
|
||||
G1BlockOffsetSharedArray* sharedOffsetArray,
|
||||
MemRegion mr) :
|
||||
@ -314,7 +302,7 @@ HeapRegion::HeapRegion(uint hrm_index,
|
||||
_humongous_start_region(NULL),
|
||||
_in_collection_set(false),
|
||||
_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),
|
||||
_next_young_region(NULL),
|
||||
_next_dirty_cards_region(NULL), _next(NULL), _prev(NULL),
|
||||
|
@ -254,9 +254,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||
HeapRegionSetBase* _containing_set;
|
||||
#endif // ASSERT
|
||||
|
||||
// For parallel heapRegion traversal.
|
||||
jint _claimed;
|
||||
|
||||
// We use concurrent marking to determine the amount of live data
|
||||
// in each heap region.
|
||||
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.
|
||||
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
|
||||
bool block_is_obj(const HeapWord* p) const;
|
||||
|
||||
@ -691,12 +675,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
uint HeapRegionManager::start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const {
|
||||
return num_regions * worker_i / num_workers;
|
||||
}
|
||||
|
||||
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);
|
||||
void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const {
|
||||
const uint start_index = hrclaimer->start_region_for_worker(worker_id);
|
||||
|
||||
// Every worker will actually look at all regions, skipping over regions that
|
||||
// are currently not committed.
|
||||
// This also (potentially) iterates over regions newly allocated during GC. This
|
||||
// is no problem except for some extra work.
|
||||
for (uint count = 0; count < _allocated_heapregions_length; count++) {
|
||||
const uint index = (start_index + count) % _allocated_heapregions_length;
|
||||
assert(0 <= index && index < _allocated_heapregions_length, "sanity");
|
||||
const uint n_regions = hrclaimer->n_regions();
|
||||
for (uint count = 0; count < n_regions; count++) {
|
||||
const uint index = (start_index + count) % n_regions;
|
||||
assert(0 <= index && index < n_regions, "sanity");
|
||||
// Skip over unavailable regions
|
||||
if (!is_available(index)) {
|
||||
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
|
||||
// when we come across their corresponding "start humongous"
|
||||
// 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;
|
||||
}
|
||||
// OK, try to claim it
|
||||
if (!r->claimHeapRegion(claim_value)) {
|
||||
if (!hrclaimer->claim_region(index)) {
|
||||
continue;
|
||||
}
|
||||
// Success!
|
||||
@ -306,13 +303,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint
|
||||
assert(chr->humongous_start_region() == r,
|
||||
err_msg("Must work on humongous continuation of the original start region "
|
||||
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");
|
||||
|
||||
bool claim_result = chr->claimHeapRegion(claim_value);
|
||||
// We should always be able to claim it; no one else should
|
||||
// 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");
|
||||
// There's no need to actually claim the continues humongous region, but we can do it in an assert as an extra precaution.
|
||||
assert(hrclaimer->claim_region(ch_index), "We should always be able to claim the continuesHumongous part of the humongous object");
|
||||
|
||||
bool res2 = blk->doHeapRegion(chr);
|
||||
if (res2) {
|
||||
@ -445,3 +440,31 @@ void HeapRegionManager::verify_optional() {
|
||||
}
|
||||
#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 HeapRegionClosure;
|
||||
class HeapRegionClaimer;
|
||||
class FreeRegionList;
|
||||
|
||||
class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
|
||||
@ -66,6 +67,7 @@ class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
|
||||
|
||||
class HeapRegionManager: public CHeapObj<mtGC> {
|
||||
friend class VMStructs;
|
||||
friend class HeapRegionClaimer;
|
||||
|
||||
G1HeapRegionTable _regions;
|
||||
|
||||
@ -99,9 +101,6 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
||||
|
||||
// Notify other data structures about change in the heap layout.
|
||||
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
|
||||
// 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.
|
||||
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.
|
||||
// Return the actual number of uncommitted regions.
|
||||
@ -235,5 +234,33 @@ public:
|
||||
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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user