Mercurial > hg > graal-jvmci-8
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()); |