diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 8b290a31cccc20dd460cd89d61d79912eff21586..36a070a18265222afe7706e5d7d35a822c7deb63 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -896,7 +896,7 @@ bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(size_t max_promoti size_t available = max_available(); size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average(); bool res = (available >= av_promo) || (available >= max_promotion_in_bytes); - if (PrintGC && Verbose) { + if (Verbose && PrintGCDetails) { gclog_or_tty->print_cr( "CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT")," "max_promo("SIZE_FORMAT")", @@ -1562,8 +1562,8 @@ bool CMSCollector::shouldConcurrentCollect() { GenCollectedHeap* gch = GenCollectedHeap::heap(); assert(gch->collector_policy()->is_two_generation_policy(), "You may want to check the correctness of the following"); - if (gch->incremental_collection_will_fail()) { - if (PrintGCDetails && Verbose) { + if (gch->incremental_collection_will_fail(true /* consult_young */)) { + if (Verbose && PrintGCDetails) { gclog_or_tty->print("CMSCollector: collect because incremental collection will fail "); } return true; @@ -1927,7 +1927,7 @@ void CMSCollector::decide_foreground_collection_type( "You may want to check the correctness of the following"); // Inform cms gen if this was due to partial collection failing. // The CMS gen may use this fact to determine its expansion policy. - if (gch->incremental_collection_will_fail()) { + if (gch->incremental_collection_will_fail(false /* don't consult_young */)) { assert(!_cmsGen->incremental_collection_failed(), "Should have been noticed, reacted to and cleared"); _cmsGen->set_incremental_collection_failed(); @@ -1936,7 +1936,7 @@ void CMSCollector::decide_foreground_collection_type( UseCMSCompactAtFullCollection && ((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) || GCCause::is_user_requested_gc(gch->gc_cause()) || - gch->incremental_collection_will_fail()); + gch->incremental_collection_will_fail(true /* consult_young */)); *should_start_over = false; if (clear_all_soft_refs && !*should_compact) { // We are about to do a last ditch collection attempt diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp index bd883f2e6223014d8c59dddfaff8ebe9cfe00634..6751b94ce6c79fb121f744710c85bd59e5128eaf 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp @@ -287,7 +287,7 @@ inline bool CMSCollector::should_abort_preclean() const { // scavenge is done or foreground GC wants to take over collection return _collectorState == AbortablePreclean && (_abort_preclean || _foregroundGCIsActive || - GenCollectedHeap::heap()->incremental_collection_will_fail()); + GenCollectedHeap::heap()->incremental_collection_will_fail(true /* consult_young */)); } inline size_t CMSCollector::get_eden_used() const { diff --git a/src/share/vm/memory/collectorPolicy.cpp b/src/share/vm/memory/collectorPolicy.cpp index 73489abc375ad250d9fabea917c5ea964dcfea14..c609da68fec1f2ba0750240342323fb2cb6ace35 100644 --- a/src/share/vm/memory/collectorPolicy.cpp +++ b/src/share/vm/memory/collectorPolicy.cpp @@ -685,7 +685,7 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, result = expand_heap_and_allocate(size, is_tlab); } return result; // could be null if we are out of space - } else if (!gch->incremental_collection_will_fail()) { + } else if (!gch->incremental_collection_will_fail(false /* don't consult_young */)) { // Do an incremental collection. gch->do_collection(false /* full */, false /* clear_all_soft_refs */, @@ -693,6 +693,9 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size, is_tlab /* is_tlab */, number_of_generations() - 1 /* max_level */); } else { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print(" :: Trying full because partial may fail :: "); + } // Try a full collection; see delta for bug id 6266275 // for the original code and why this has been simplified // with from-space allocation criteria modified and diff --git a/src/share/vm/memory/defNewGeneration.cpp b/src/share/vm/memory/defNewGeneration.cpp index 60b27a5fb90c5409dda4746bb5747d7324089740..746119ada93c59d0b52e2b35fff714193acad685 100644 --- a/src/share/vm/memory/defNewGeneration.cpp +++ b/src/share/vm/memory/defNewGeneration.cpp @@ -483,16 +483,17 @@ void DefNewGeneration::space_iterate(SpaceClosure* blk, // so we try to allocate the from-space, too. HeapWord* DefNewGeneration::allocate_from_space(size_t size) { HeapWord* result = NULL; - if (PrintGC && Verbose) { + if (Verbose && PrintGCDetails) { gclog_or_tty->print("DefNewGeneration::allocate_from_space(%u):" - " will_fail: %s" - " heap_lock: %s" - " free: " SIZE_FORMAT, - size, - GenCollectedHeap::heap()->incremental_collection_will_fail() ? "true" : "false", - Heap_lock->is_locked() ? "locked" : "unlocked", - from()->free()); - } + " will_fail: %s" + " heap_lock: %s" + " free: " SIZE_FORMAT, + size, + GenCollectedHeap::heap()->incremental_collection_will_fail(false /* don't consult_young */) ? + "true" : "false", + Heap_lock->is_locked() ? "locked" : "unlocked", + from()->free()); + } if (should_allocate_from_space() || GC_locker::is_active_and_needs_gc()) { if (Heap_lock->owned_by_self() || (SafepointSynchronize::is_at_safepoint() && @@ -534,6 +535,9 @@ void DefNewGeneration::collect(bool full, // from this generation, pass on collection; let the next generation // do it. if (!collection_attempt_is_safe()) { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print(" :: Collection attempt not safe :: "); + } gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one return; } @@ -821,6 +825,9 @@ void DefNewGeneration::reset_scratch() { bool DefNewGeneration::collection_attempt_is_safe() { if (!to()->is_empty()) { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print(" :: to is not empty :: "); + } return false; } if (_next_gen == NULL) { @@ -843,10 +850,18 @@ void DefNewGeneration::gc_epilogue(bool full) { GenCollectedHeap* gch = GenCollectedHeap::heap(); if (full) { DEBUG_ONLY(seen_incremental_collection_failed = false;) - if (!collection_attempt_is_safe()) { + if (!collection_attempt_is_safe() && !_eden_space->is_empty()) { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print("DefNewEpilogue: cause(%s), full, not safe, set_failed, set_alloc_from, clear_seen", + GCCause::to_string(gch->gc_cause())); + } gch->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state set_should_allocate_from_space(); // we seem to be running out of space } else { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print("DefNewEpilogue: cause(%s), full, safe, clear_failed, clear_alloc_from, clear_seen", + GCCause::to_string(gch->gc_cause())); + } gch->clear_incremental_collection_failed(); // We just did a full collection clear_should_allocate_from_space(); // if set } @@ -860,11 +875,20 @@ void DefNewGeneration::gc_epilogue(bool full) { // a full collection in between. if (!seen_incremental_collection_failed && gch->incremental_collection_failed()) { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print("DefNewEpilogue: cause(%s), not full, not_seen_failed, failed, set_seen_failed", + GCCause::to_string(gch->gc_cause())); + } seen_incremental_collection_failed = true; } else if (seen_incremental_collection_failed) { - assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed(), + if (Verbose && PrintGCDetails) { + gclog_or_tty->print("DefNewEpilogue: cause(%s), not full, seen_failed, will_clear_seen_failed", + GCCause::to_string(gch->gc_cause())); + } + assert(gch->gc_cause() == GCCause::_scavenge_alot || + (gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) || + !gch->incremental_collection_failed(), "Twice in a row"); - seen_incremental_collection_failed = false; } #endif // ASSERT diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp index ded35d0f4a71658c7b80d00d16e93cac523793c2..7f906e4ae983da69b9cfbcfdd9b99c6e17b9600b 100644 --- a/src/share/vm/memory/genCollectedHeap.cpp +++ b/src/share/vm/memory/genCollectedHeap.cpp @@ -935,7 +935,7 @@ void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) { void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, int max_level) { int local_max_level; - if (!incremental_collection_will_fail() && + if (!incremental_collection_will_fail(false /* don't consult_young */) && gc_cause() == GCCause::_gc_locker) { local_max_level = 0; } else { @@ -951,7 +951,7 @@ void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, // A scavenge may not have been attempted, or may have // been attempted and failed, because the old gen was too full if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker && - incremental_collection_will_fail()) { + incremental_collection_will_fail(false /* don't consult_young */)) { if (PrintGCDetails) { gclog_or_tty->print_cr("GC locker: Trying a full collection " "because scavenge failed"); diff --git a/src/share/vm/memory/genCollectedHeap.hpp b/src/share/vm/memory/genCollectedHeap.hpp index cc0d0b8bfb2d5c6e913c52c3dc83201c5df0aa9d..de8070b81c75a955ee3504aa3fbe77c362627d2a 100644 --- a/src/share/vm/memory/genCollectedHeap.hpp +++ b/src/share/vm/memory/genCollectedHeap.hpp @@ -477,13 +477,17 @@ public: bool no_allocs_since_save_marks(int level); // Returns true if an incremental collection is likely to fail. - bool incremental_collection_will_fail() { + // We optionally consult the young gen, if asked to do so; + // otherwise we base our answer on whether the previous incremental + // collection attempt failed with no corrective action as of yet. + bool incremental_collection_will_fail(bool consult_young) { // Assumes a 2-generation system; the first disjunct remembers if an // incremental collection failed, even when we thought (second disjunct) // that it would not. assert(heap()->collector_policy()->is_two_generation_policy(), "the following definition may not be suitable for an n(>2)-generation system"); - return incremental_collection_failed() || !get_gen(0)->collection_attempt_is_safe(); + return incremental_collection_failed() || + (consult_young && !get_gen(0)->collection_attempt_is_safe()); } // If a generation bails out of an incremental collection,