comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 23026:b7c8142a9e0b

8069367: Eagerly reclaimed humongous objects left on mark stack Summary: Prevent eager reclaim of objects that might be on mark stack. Reviewed-by: brutisso, tschatzl
author kbarrett
date Wed, 15 Apr 2015 12:16:01 -0400
parents cbc7c4c9e11c
children 0f8f1250fed5
comparison
equal deleted inserted replaced
23025:24c446b2460d 23026:b7c8142a9e0b
1851 _refine_cte_cl(NULL), 1851 _refine_cte_cl(NULL),
1852 _full_collection(false), 1852 _full_collection(false),
1853 _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()), 1853 _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()),
1854 _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()), 1854 _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
1855 _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()), 1855 _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
1856 _humongous_is_live(), 1856 _humongous_reclaim_candidates(),
1857 _has_humongous_reclaim_candidates(false), 1857 _has_humongous_reclaim_candidates(false),
1858 _free_regions_coming(false), 1858 _free_regions_coming(false),
1859 _young_list(new YoungList(this)), 1859 _young_list(new YoungList(this)),
1860 _gc_time_stamp(0), 1860 _gc_time_stamp(0),
1861 _survivor_plab_stats(YoungPLABSize, PLABWeight), 1861 _survivor_plab_stats(YoungPLABSize, PLABWeight),
2046 2046
2047 _bot_shared = new G1BlockOffsetSharedArray(_reserved, bot_storage); 2047 _bot_shared = new G1BlockOffsetSharedArray(_reserved, bot_storage);
2048 2048
2049 _g1h = this; 2049 _g1h = this;
2050 2050
2051 _in_cset_fast_test.initialize(_hrm.reserved().start(), _hrm.reserved().end(), HeapRegion::GrainBytes); 2051 {
2052 _humongous_is_live.initialize(_hrm.reserved().start(), _hrm.reserved().end(), HeapRegion::GrainBytes); 2052 HeapWord* start = _hrm.reserved().start();
2053 HeapWord* end = _hrm.reserved().end();
2054 size_t granularity = HeapRegion::GrainBytes;
2055
2056 _in_cset_fast_test.initialize(start, end, granularity);
2057 _humongous_reclaim_candidates.initialize(start, end, granularity);
2058 }
2053 2059
2054 // Create the ConcurrentMark data structure and thread. 2060 // Create the ConcurrentMark data structure and thread.
2055 // (Must do this late, so that "max_regions" is defined.) 2061 // (Must do this late, so that "max_regions" is defined.)
2056 _cm = new ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); 2062 _cm = new ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage);
2057 if (_cm == NULL || !_cm->completed_initialization()) { 2063 if (_cm == NULL || !_cm->completed_initialization()) {
2137 _cg1r->stop(); 2143 _cg1r->stop();
2138 _cmThread->stop(); 2144 _cmThread->stop();
2139 if (G1StringDedup::is_enabled()) { 2145 if (G1StringDedup::is_enabled()) {
2140 G1StringDedup::stop(); 2146 G1StringDedup::stop();
2141 } 2147 }
2142 }
2143
2144 void G1CollectedHeap::clear_humongous_is_live_table() {
2145 guarantee(G1EagerReclaimHumongousObjects, "Should only be called if true");
2146 _humongous_is_live.clear();
2147 } 2148 }
2148 2149
2149 size_t G1CollectedHeap::conservative_max_heap_alignment() { 2150 size_t G1CollectedHeap::conservative_max_heap_alignment() {
2150 return HeapRegion::max_region_size(); 2151 return HeapRegion::max_region_size();
2151 } 2152 }
3664 3665
3665 size_t G1CollectedHeap::cards_scanned() { 3666 size_t G1CollectedHeap::cards_scanned() {
3666 return g1_rem_set()->cardsScanned(); 3667 return g1_rem_set()->cardsScanned();
3667 } 3668 }
3668 3669
3669 bool G1CollectedHeap::humongous_region_is_always_live(uint index) {
3670 HeapRegion* region = region_at(index);
3671 assert(region->startsHumongous(), "Must start a humongous object");
3672 return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty();
3673 }
3674
3675 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { 3670 class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
3676 private: 3671 private:
3677 size_t _total_humongous; 3672 size_t _total_humongous;
3678 size_t _candidate_humongous; 3673 size_t _candidate_humongous;
3679 3674
3680 DirtyCardQueue _dcq; 3675 DirtyCardQueue _dcq;
3681 3676
3682 bool humongous_region_is_candidate(uint index) { 3677 // We don't nominate objects with many remembered set entries, on
3683 HeapRegion* region = G1CollectedHeap::heap()->region_at(index); 3678 // the assumption that such objects are likely still live.
3679 bool is_remset_small(HeapRegion* region) const {
3680 HeapRegionRemSet* const rset = region->rem_set();
3681 return G1EagerReclaimHumongousObjectsWithStaleRefs
3682 ? rset->occupancy_less_or_equal_than(G1RSetSparseRegionEntries)
3683 : rset->is_empty();
3684 }
3685
3686 bool is_typeArray_region(HeapRegion* region) const {
3687 return oop(region->bottom())->is_typeArray();
3688 }
3689
3690 bool humongous_region_is_candidate(G1CollectedHeap* heap, HeapRegion* region) const {
3684 assert(region->startsHumongous(), "Must start a humongous object"); 3691 assert(region->startsHumongous(), "Must start a humongous object");
3685 HeapRegionRemSet* const rset = region->rem_set(); 3692
3686 bool const allow_stale_refs = G1EagerReclaimHumongousObjectsWithStaleRefs; 3693 // Candidate selection must satisfy the following constraints
3687 return !oop(region->bottom())->is_objArray() && 3694 // while concurrent marking is in progress:
3688 ((allow_stale_refs && rset->occupancy_less_or_equal_than(G1RSetSparseRegionEntries)) || 3695 //
3689 (!allow_stale_refs && rset->is_empty())); 3696 // * In order to maintain SATB invariants, an object must not be
3697 // reclaimed if it was allocated before the start of marking and
3698 // has not had its references scanned. Such an object must have
3699 // its references (including type metadata) scanned to ensure no
3700 // live objects are missed by the marking process. Objects
3701 // allocated after the start of concurrent marking don't need to
3702 // be scanned.
3703 //
3704 // * An object must not be reclaimed if it is on the concurrent
3705 // mark stack. Objects allocated after the start of concurrent
3706 // marking are never pushed on the mark stack.
3707 //
3708 // Nominating only objects allocated after the start of concurrent
3709 // marking is sufficient to meet both constraints. This may miss
3710 // some objects that satisfy the constraints, but the marking data
3711 // structures don't support efficiently performing the needed
3712 // additional tests or scrubbing of the mark stack.
3713 //
3714 // However, we presently only nominate is_typeArray() objects.
3715 // A humongous object containing references induces remembered
3716 // set entries on other regions. In order to reclaim such an
3717 // object, those remembered sets would need to be cleaned up.
3718 //
3719 // We also treat is_typeArray() objects specially, allowing them
3720 // to be reclaimed even if allocated before the start of
3721 // concurrent mark. For this we rely on mark stack insertion to
3722 // exclude is_typeArray() objects, preventing reclaiming an object
3723 // that is in the mark stack. We also rely on the metadata for
3724 // such objects to be built-in and so ensured to be kept live.
3725 // Frequent allocation and drop of large binary blobs is an
3726 // important use case for eager reclaim, and this special handling
3727 // may reduce needed headroom.
3728
3729 return is_typeArray_region(region) && is_remset_small(region);
3690 } 3730 }
3691 3731
3692 public: 3732 public:
3693 RegisterHumongousWithInCSetFastTestClosure() 3733 RegisterHumongousWithInCSetFastTestClosure()
3694 : _total_humongous(0), 3734 : _total_humongous(0),
3700 if (!r->startsHumongous()) { 3740 if (!r->startsHumongous()) {
3701 return false; 3741 return false;
3702 } 3742 }
3703 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 3743 G1CollectedHeap* g1h = G1CollectedHeap::heap();
3704 3744
3705 uint region_idx = r->hrm_index(); 3745 bool is_candidate = humongous_region_is_candidate(g1h, r);
3706 bool is_candidate = humongous_region_is_candidate(region_idx); 3746 uint rindex = r->hrm_index();
3707 // Is_candidate already filters out humongous object with large remembered sets. 3747 g1h->set_humongous_reclaim_candidate(rindex, is_candidate);
3708 // If we have a humongous object with a few remembered sets, we simply flush these
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.
3712 if (is_candidate) { 3748 if (is_candidate) {
3749 _candidate_humongous++;
3750 g1h->register_humongous_region_with_in_cset_fast_test(rindex);
3751 // Is_candidate already filters out humongous object with large remembered sets.
3752 // If we have a humongous object with a few remembered sets, we simply flush these
3753 // remembered set entries into the DCQS. That will result in automatic
3754 // re-evaluation of their remembered set entries during the following evacuation
3755 // phase.
3713 if (!r->rem_set()->is_empty()) { 3756 if (!r->rem_set()->is_empty()) {
3714 guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries), 3757 guarantee(r->rem_set()->occupancy_less_or_equal_than(G1RSetSparseRegionEntries),
3715 "Found a not-small remembered set here. This is inconsistent with previous assumptions."); 3758 "Found a not-small remembered set here. This is inconsistent with previous assumptions.");
3716 G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set(); 3759 G1SATBCardTableLoggingModRefBS* bs = g1h->g1_barrier_set();
3717 HeapRegionRemSetIterator hrrs(r->rem_set()); 3760 HeapRegionRemSetIterator hrrs(r->rem_set());
3724 } 3767 }
3725 } 3768 }
3726 r->rem_set()->clear_locked(); 3769 r->rem_set()->clear_locked();
3727 } 3770 }
3728 assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty."); 3771 assert(r->rem_set()->is_empty(), "At this point any humongous candidate remembered set must be empty.");
3729 g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
3730 _candidate_humongous++;
3731 } 3772 }
3732 _total_humongous++; 3773 _total_humongous++;
3733 3774
3734 return false; 3775 return false;
3735 } 3776 }
3745 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0); 3786 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0.0, 0, 0);
3746 return; 3787 return;
3747 } 3788 }
3748 double time = os::elapsed_counter(); 3789 double time = os::elapsed_counter();
3749 3790
3791 // Collect reclaim candidate information and register candidates with cset.
3750 RegisterHumongousWithInCSetFastTestClosure cl; 3792 RegisterHumongousWithInCSetFastTestClosure cl;
3751 heap_region_iterate(&cl); 3793 heap_region_iterate(&cl);
3752 3794
3753 time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0; 3795 time = ((double)(os::elapsed_counter() - time) / os::elapsed_frequency()) * 1000.0;
3754 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time, 3796 g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(time,
3755 cl.total_humongous(), 3797 cl.total_humongous(),
3756 cl.candidate_humongous()); 3798 cl.candidate_humongous());
3757 _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; 3799 _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
3758
3759 if (_has_humongous_reclaim_candidates || G1TraceEagerReclaimHumongousObjects) {
3760 clear_humongous_is_live_table();
3761 }
3762 3800
3763 // Finally flush all remembered set entries to re-check into the global DCQS. 3801 // Finally flush all remembered set entries to re-check into the global DCQS.
3764 cl.flush_rem_set_entries(); 3802 cl.flush_rem_set_entries();
3765 } 3803 }
3766 3804
6319 // - never consider object arrays at this time because they would pose 6357 // - never consider object arrays at this time because they would pose
6320 // considerable effort for cleaning up the the remembered sets. This is 6358 // considerable effort for cleaning up the the remembered sets. This is
6321 // required because stale remembered sets might reference locations that 6359 // required because stale remembered sets might reference locations that
6322 // are currently allocated into. 6360 // are currently allocated into.
6323 uint region_idx = r->hrm_index(); 6361 uint region_idx = r->hrm_index();
6324 if (g1h->humongous_is_live(region_idx) || 6362 if (!g1h->is_humongous_reclaim_candidate(region_idx) ||
6325 g1h->humongous_region_is_always_live(region_idx)) { 6363 !r->rem_set()->is_empty()) {
6326 6364
6327 if (G1TraceEagerReclaimHumongousObjects) { 6365 if (G1TraceEagerReclaimHumongousObjects) {
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", 6366 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 reclaim candidate %d type array %d",
6329 region_idx, 6367 region_idx,
6330 obj->size()*HeapWordSize, 6368 obj->size()*HeapWordSize,
6331 r->bottom(), 6369 r->bottom(),
6332 r->region_num(), 6370 r->region_num(),
6333 r->rem_set()->occupied(), 6371 r->rem_set()->occupied(),
6334 r->rem_set()->strong_code_roots_list_length(), 6372 r->rem_set()->strong_code_roots_list_length(),
6335 next_bitmap->isMarked(r->bottom()), 6373 next_bitmap->isMarked(r->bottom()),
6336 g1h->humongous_is_live(region_idx), 6374 g1h->is_humongous_reclaim_candidate(region_idx),
6337 obj->is_objArray() 6375 obj->is_typeArray()
6338 ); 6376 );
6339 } 6377 }
6340 6378
6341 return false; 6379 return false;
6342 } 6380 }
6343 6381
6344 guarantee(!obj->is_objArray(), 6382 guarantee(obj->is_typeArray(),
6345 err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", 6383 err_msg("Only eagerly reclaiming type arrays is supported, but the object "
6384 PTR_FORMAT " is not.",
6346 r->bottom())); 6385 r->bottom()));
6347 6386
6348 if (G1TraceEagerReclaimHumongousObjects) { 6387 if (G1TraceEagerReclaimHumongousObjects) {
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", 6388 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 reclaim candidate %d type array %d",
6350 region_idx, 6389 region_idx,
6351 obj->size()*HeapWordSize, 6390 obj->size()*HeapWordSize,
6352 r->bottom(), 6391 r->bottom(),
6353 r->region_num(), 6392 r->region_num(),
6354 r->rem_set()->occupied(), 6393 r->rem_set()->occupied(),
6355 r->rem_set()->strong_code_roots_list_length(), 6394 r->rem_set()->strong_code_roots_list_length(),
6356 next_bitmap->isMarked(r->bottom()), 6395 next_bitmap->isMarked(r->bottom()),
6357 g1h->humongous_is_live(region_idx), 6396 g1h->is_humongous_reclaim_candidate(region_idx),
6358 obj->is_objArray() 6397 obj->is_typeArray()
6359 ); 6398 );
6360 } 6399 }
6361 // Need to clear mark bit of the humongous object if already set. 6400 // Need to clear mark bit of the humongous object if already set.
6362 if (next_bitmap->isMarked(r->bottom())) { 6401 if (next_bitmap->isMarked(r->bottom())) {
6363 next_bitmap->clear(r->bottom()); 6402 next_bitmap->clear(r->bottom());