< prev index next >

src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp

Print this page
rev 7518 : 8048179: Early reclaim of large objects that are referenced by a few objects
Summary:
Reviewed-by:

*** 3482,3538 **** HeapRegion* region = region_at(index); assert(region->is_starts_humongous(), "Must start a humongous object"); return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty(); } class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { private: size_t _total_humongous; size_t _candidate_humongous; public: ! RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) { } virtual bool doHeapRegion(HeapRegion* r) { if (!r->is_starts_humongous()) { return false; } G1CollectedHeap* g1h = G1CollectedHeap::heap(); uint region_idx = r->hrm_index(); ! bool is_candidate = !g1h->humongous_region_is_always_live(region_idx); ! // Is_candidate already filters out humongous regions with some remembered set. ! // This will not lead to humongous object that we mistakenly keep alive because ! // during young collection the remembered sets will only be added to. if (is_candidate) { g1h->register_humongous_region_with_in_cset_fast_test(region_idx); _candidate_humongous++; } _total_humongous++; return false; } size_t total_humongous() const { return _total_humongous; } size_t candidate_humongous() const { return _candidate_humongous; } }; void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { if (!G1ReclaimDeadHumongousObjectsAtYoungGC) { ! g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0); return; } RegisterHumongousWithInCSetFastTestClosure cl; heap_region_iterate(&cl); ! g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(), cl.candidate_humongous()); _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) { clear_humongous_is_live_table(); } } void G1CollectedHeap::setup_surviving_young_words() { assert(_surviving_young_words == NULL, "pre-condition"); --- 3482,3578 ---- HeapRegion* region = region_at(index); assert(region->is_starts_humongous(), "Must start a humongous object"); return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty(); } + bool G1CollectedHeap::humongous_region_is_candidate(uint index) { + HeapRegion* region = region_at(index); + assert(region->is_starts_humongous(), "Must start a humongous object"); + return !oop(region->bottom())->is_objArray() && + ((G1ReclaimDeadHumongousObjectsWithRefsAtYoungGC && region->rem_set()->is_small_for_eager_reclaim()) || + (!G1ReclaimDeadHumongousObjectsWithRefsAtYoungGC && region->rem_set()->is_empty())); + } + class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { private: size_t _total_humongous; size_t _candidate_humongous; + + DirtyCardQueue _dcq; public: ! RegisterHumongousWithInCSetFastTestClosure() ! : _total_humongous(0), ! _candidate_humongous(0), ! _dcq(&JavaThread::dirty_card_queue_set()) { } virtual bool doHeapRegion(HeapRegion* r) { if (!r->is_starts_humongous()) { return false; } G1CollectedHeap* g1h = G1CollectedHeap::heap(); uint region_idx = r->hrm_index(); ! bool is_candidate = g1h->humongous_region_is_candidate(region_idx); ! // Is_candidate already filters out humongous object with large remembered sets. ! // If we have a humongous object with a few remembered sets, we simply flush these ! // remembered set entries into the DCQS. That will result in automatic ! // re-evaluation of their remembered set entries during the following evacuation ! // phase. if (is_candidate) { + if (!r->rem_set()->is_empty()) { + guarantee(r->rem_set()->is_small_for_eager_reclaim(), + "Found a not-small remembered set here. This is inconsistent with previous assumptions."); + G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set(); + HeapRegionRemSetIterator hrrs(r->rem_set()); + size_t card_index; + while (hrrs.has_next(card_index)) { + jbyte* card_ptr = (jbyte*)bs->byte_for_index(card_index); + if (*card_ptr != CardTableModRefBS::dirty_card_val()) { + *card_ptr = CardTableModRefBS::dirty_card_val(); + _dcq.enqueue(card_ptr); + } + } + r->rem_set()->clear_locked(); + } + assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty."); g1h->register_humongous_region_with_in_cset_fast_test(region_idx); _candidate_humongous++; } _total_humongous++; return false; } size_t total_humongous() const { return _total_humongous; } size_t candidate_humongous() const { return _candidate_humongous; } + + void flush_rem_set_entries() { _dcq.flush(); } }; void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { if (!G1ReclaimDeadHumongousObjectsAtYoungGC) { ! g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0); return; } + double time = os::elapsed_counter(); RegisterHumongousWithInCSetFastTestClosure cl; heap_region_iterate(&cl); ! ! time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0; ! g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time, ! cl.total_humongous(), cl.candidate_humongous()); _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) { clear_humongous_is_live_table(); } + + // Finally flush all remembered set entries to re-check into the global DCQS. + cl.flush_rem_set_entries(); } void G1CollectedHeap::setup_surviving_young_words() { assert(_surviving_young_words == NULL, "pre-condition");
*** 6131,6156 **** // nobody has a reference to it. // At the start of collection we flush all refinement logs, and remembered sets // are completely up-to-date wrt to references to the humongous object. // // Other implementation considerations: ! // - never consider object arrays: while they are a valid target, they have not ! // been observed to be used as temporary objects. ! // - they would also pose considerable effort for cleaning up the the remembered ! // sets. ! // While this cleanup is not strictly necessary to be done (or done instantly), ! // given that their occurrence is very low, this saves us this additional ! // complexity. uint region_idx = r->hrm_index(); if (g1h->humongous_is_live(region_idx) || g1h->humongous_region_is_always_live(region_idx)) { if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { ! gclog_or_tty->print_cr("Live humongous %d region %d size "SIZE_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", ! r->is_humongous(), region_idx, obj->size()*HeapWordSize, r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), g1h->humongous_is_live(region_idx), obj->is_objArray() --- 6171,6194 ---- // nobody has a reference to it. // At the start of collection we flush all refinement logs, and remembered sets // are completely up-to-date wrt to references to the humongous object. // // Other implementation considerations: ! // - never consider object arrays at this time because they would pose ! // considerable effort for cleaning up the the remembered sets. This is ! // required because stale remembered sets might reference locations that ! // are currently allocated into. uint region_idx = r->hrm_index(); if (g1h->humongous_is_live(region_idx) || g1h->humongous_region_is_always_live(region_idx)) { if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { ! gclog_or_tty->print_cr("Live humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", region_idx, obj->size()*HeapWordSize, + r->bottom(), + r->region_num(), r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), g1h->humongous_is_live(region_idx), obj->is_objArray()
*** 6163,6177 **** guarantee(!obj->is_objArray(), err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", r->bottom())); if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { ! gclog_or_tty->print_cr("Reclaim humongous region %d size "SIZE_FORMAT" start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", ! r->is_humongous(), obj->size()*HeapWordSize, r->bottom(), - region_idx, r->region_num(), r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), g1h->humongous_is_live(region_idx), --- 6201,6214 ---- guarantee(!obj->is_objArray(), err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", r->bottom())); if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { ! gclog_or_tty->print_cr("Dead humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", ! region_idx, obj->size()*HeapWordSize, r->bottom(), r->region_num(), r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), g1h->humongous_is_live(region_idx),
< prev index next >