comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 23024:cbc7c4c9e11c

8048179: Early reclaim of large objects that are referenced by a few objects Summary: Push the remembered sets of large objects with few referenced into the dirty card queue at the beginning of the evacuation so that they may end up with zero remembered set entries at the end of the collection, and are potentially reclaimed. Also improve timing measurements of the early reclaim mechanism, and shorten flag names. Reviewed-by: brutisso, jmasa, dfazunen
author tschatzl
date Wed, 07 Jan 2015 15:15:37 +0100
parents 30e04eba9e29
children b7c8142a9e0b
comparison
equal deleted inserted replaced
23023:82617ab0e8b3 23024:cbc7c4c9e11c
2140 G1StringDedup::stop(); 2140 G1StringDedup::stop();
2141 } 2141 }
2142 } 2142 }
2143 2143
2144 void G1CollectedHeap::clear_humongous_is_live_table() { 2144 void G1CollectedHeap::clear_humongous_is_live_table() {
2145 guarantee(G1ReclaimDeadHumongousObjectsAtYoungGC, "Should only be called if true"); 2145 guarantee(G1EagerReclaimHumongousObjects, "Should only be called if true");
2146 _humongous_is_live.clear(); 2146 _humongous_is_live.clear();
2147 } 2147 }
2148 2148
2149 size_t G1CollectedHeap::conservative_max_heap_alignment() { 2149 size_t G1CollectedHeap::conservative_max_heap_alignment() {
2150 return HeapRegion::max_region_size(); 2150 return HeapRegion::max_region_size();
3674 3674
3675 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { 3675 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
3676 private: 3676 private:
3677 size_t _total_humongous; 3677 size_t _total_humongous;
3678 size_t _candidate_humongous; 3678 size_t _candidate_humongous;
3679
3680 DirtyCardQueue _dcq;
3681
3682 bool humongous_region_is_candidate(uint index) {
3683 HeapRegion* region = G1CollectedHeap::heap()->region_at(index);
3684 assert(region->startsHumongous(), "Must start a humongous object");
3685 HeapRegionRemSet* const rset = region->rem_set();
3686 bool const allow_stale_refs = G1EagerReclaimHumongousObjectsWithStaleRefs;
3687 return !oop(region->bottom())->is_objArray() &&
3688 ((allow_stale_refs && rset->occupancy_less_or_equal_than(G1RSetSparseRegionEntries)) ||
3689 (!allow_stale_refs && rset->is_empty()));
3690 }
3691
3679 public: 3692 public:
3680 RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) { 3693 RegisterHumongousWithInCSetFastTestClosure()
3694 : _total_humongous(0),
3695 _candidate_humongous(0),
3696 _dcq(&JavaThread::dirty_card_queue_set()) {
3681 } 3697 }
3682 3698
3683 virtual bool doHeapRegion(HeapRegion* r) { 3699 virtual bool doHeapRegion(HeapRegion* r) {
3684 if (!r->startsHumongous()) { 3700 if (!r->startsHumongous()) {
3685 return false; 3701 return false;
3686 } 3702 }
3687 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 3703 G1CollectedHeap* g1h = G1CollectedHeap::heap();
3688 3704
3689 uint region_idx = r->hrm_index(); 3705 uint region_idx = r->hrm_index();
3690 bool is_candidate = !g1h->humongous_region_is_always_live(region_idx); 3706 bool is_candidate = humongous_region_is_candidate(region_idx);
3691 // Is_candidate already filters out humongous regions with some remembered set. 3707 // Is_candidate already filters out humongous object with large remembered sets.
3692 // This will not lead to humongous object that we mistakenly keep alive because 3708 // If we have a humongous object with a few remembered sets, we simply flush these
3693 // during young collection the remembered sets will only be added to. 3709 // remembered set entries into the DCQS. That will result in automatic
3710 // re-evaluation of their remembered set entries during the following evacuation
3711 // phase.
3694 if (is_candidate) { 3712 if (is_candidate) {
3713 if (!r->rem_set()->is_empty()) {
3714 guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
3715 "Found a not-small remembered set here. This is inconsistent with previous assumptions.");
3716 G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set();
3717 HeapRegionRemSetIterator hrrs(r->rem_set());
3718 size_t card_index;
3719 while (hrrs.has_next(card_index)) {
3720 jbyte* card_ptr = (jbyte*)bs->byte_for_index(card_index);
3721 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
3722 *card_ptr = CardTableModRefBS::dirty_card_val();
3723 _dcq.enqueue(card_ptr);
3724 }
3725 }
3726 r->rem_set()->clear_locked();
3727 }
3728 assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
3695 g1h->register_humongous_region_with_in_cset_fast_test(region_idx); 3729 g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
3696 _candidate_humongous++; 3730 _candidate_humongous++;
3697 } 3731 }
3698 _total_humongous++; 3732 _total_humongous++;
3699 3733
3700 return false; 3734 return false;
3701 } 3735 }
3702 3736
3703 size_t total_humongous() const { return _total_humongous; } 3737 size_t total_humongous() const { return _total_humongous; }
3704 size_t candidate_humongous() const { return _candidate_humongous; } 3738 size_t candidate_humongous() const { return _candidate_humongous; }
3739
3740 void flush_rem_set_entries() { _dcq.flush(); }
3705 }; 3741 };
3706 3742
3707 void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { 3743 void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() {
3708 if (!G1ReclaimDeadHumongousObjectsAtYoungGC) { 3744 if (!G1EagerReclaimHumongousObjects) {
3709 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0); 3745 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0);
3710 return; 3746 return;
3711 } 3747 }
3748 double time = os::elapsed_counter();
3712 3749
3713 RegisterHumongousWithInCSetFastTestClosure cl; 3750 RegisterHumongousWithInCSetFastTestClosure cl;
3714 heap_region_iterate(&cl); 3751 heap_region_iterate(&cl);
3715 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(), 3752
3753 time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0;
3754 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time,
3755 cl.total_humongous(),
3716 cl.candidate_humongous()); 3756 cl.candidate_humongous());
3717 _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; 3757 _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
3718 3758
3719 if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) { 3759 if (_has_humongous_reclaim_candidates || G1TraceEagerReclaimHumongousObjects) {
3720 clear_humongous_is_live_table(); 3760 clear_humongous_is_live_table();
3721 } 3761 }
3762
3763 // Finally flush all remembered set entries to re-check into the global DCQS.
3764 cl.flush_rem_set_entries();
3722 } 3765 }
3723 3766
3724 void 3767 void
3725 G1CollectedHeap::setup_surviving_young_words() { 3768 G1CollectedHeap::setup_surviving_young_words() {
3726 assert(_surviving_young_words == NULL, "pre-condition"); 3769 assert(_surviving_young_words == NULL, "pre-condition");
6271 // nobody has a reference to it. 6314 // nobody has a reference to it.
6272 // At the start of collection we flush all refinement logs, and remembered sets 6315 // At the start of collection we flush all refinement logs, and remembered sets
6273 // are completely up-to-date wrt to references to the humongous object. 6316 // are completely up-to-date wrt to references to the humongous object.
6274 // 6317 //
6275 // Other implementation considerations: 6318 // Other implementation considerations:
6276 // - never consider object arrays: while they are a valid target, they have not 6319 // - never consider object arrays at this time because they would pose
6277 // been observed to be used as temporary objects. 6320 // considerable effort for cleaning up the the remembered sets. This is
6278 // - they would also pose considerable effort for cleaning up the the remembered 6321 // required because stale remembered sets might reference locations that
6279 // sets. 6322 // are currently allocated into.
6280 // While this cleanup is not strictly necessary to be done (or done instantly),
6281 // given that their occurrence is very low, this saves us this additional
6282 // complexity.
6283 uint region_idx = r->hrm_index(); 6323 uint region_idx = r->hrm_index();
6284 if (g1h->humongous_is_live(region_idx) || 6324 if (g1h->humongous_is_live(region_idx) ||
6285 g1h->humongous_region_is_always_live(region_idx)) { 6325 g1h->humongous_region_is_always_live(region_idx)) {
6286 6326
6287 if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { 6327 if (G1TraceEagerReclaimHumongousObjects) {
6288 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", 6328 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",
6289 r->isHumongous(),
6290 region_idx, 6329 region_idx,
6291 obj->size()*HeapWordSize, 6330 obj->size()*HeapWordSize,
6331 r->bottom(),
6332 r->region_num(),
6292 r->rem_set()->occupied(), 6333 r->rem_set()->occupied(),
6293 r->rem_set()->strong_code_roots_list_length(), 6334 r->rem_set()->strong_code_roots_list_length(),
6294 next_bitmap->isMarked(r->bottom()), 6335 next_bitmap->isMarked(r->bottom()),
6295 g1h->humongous_is_live(region_idx), 6336 g1h->humongous_is_live(region_idx),
6296 obj->is_objArray() 6337 obj->is_objArray()
6302 6343
6303 guarantee(!obj->is_objArray(), 6344 guarantee(!obj->is_objArray(),
6304 err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", 6345 err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
6305 r->bottom())); 6346 r->bottom()));
6306 6347
6307 if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { 6348 if (G1TraceEagerReclaimHumongousObjects) {
6308 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 ", 6349 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",
6309 r->isHumongous(), 6350 region_idx,
6310 obj->size()*HeapWordSize, 6351 obj->size()*HeapWordSize,
6311 r->bottom(), 6352 r->bottom(),
6312 region_idx,
6313 r->region_num(), 6353 r->region_num(),
6314 r->rem_set()->occupied(), 6354 r->rem_set()->occupied(),
6315 r->rem_set()->strong_code_roots_list_length(), 6355 r->rem_set()->strong_code_roots_list_length(),
6316 next_bitmap->isMarked(r->bottom()), 6356 next_bitmap->isMarked(r->bottom()),
6317 g1h->humongous_is_live(region_idx), 6357 g1h->humongous_is_live(region_idx),
6344 }; 6384 };
6345 6385
6346 void G1CollectedHeap::eagerly_reclaim_humongous_regions() { 6386 void G1CollectedHeap::eagerly_reclaim_humongous_regions() {
6347 assert_at_safepoint(true); 6387 assert_at_safepoint(true);
6348 6388
6349 if (!G1ReclaimDeadHumongousObjectsAtYoungGC || 6389 if (!G1EagerReclaimHumongousObjects ||
6350 (!_has_humongous_reclaim_candidates && !G1TraceReclaimDeadHumongousObjectsAtYoungGC)) { 6390 (!_has_humongous_reclaim_candidates && !G1TraceEagerReclaimHumongousObjects)) {
6351 g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0); 6391 g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0);
6352 return; 6392 return;
6353 } 6393 }
6354 6394
6355 double start_time = os::elapsedTime(); 6395 double start_time = os::elapsedTime();