# HG changeset patch # User jmasa # Date 1271191930 25200 # Node ID 95a5c4b8927333323cc9c15e93ab1d4b12b279fa # Parent 431efce7a0af2f402be50ecff4edaf0d082f7c12 6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit. Summary: Ensure a full GC that clears SoftReferences before throwing an out-of-memory Reviewed-by: ysr, jcoomes diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,11 +32,10 @@ ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return this; } void initialize_gc_policy_counters(); -#if 1 + virtual void initialize_size_policy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size); -#endif // Returns true if the incremental mode is enabled. virtual bool has_soft_ended_eden(); diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1815,8 +1815,19 @@ do_compaction_work(clear_all_soft_refs); // Has the GC time limit been exceeded? - check_gc_time_limit(); - + DefNewGeneration* young_gen = _young_gen->as_DefNewGeneration(); + size_t max_eden_size = young_gen->max_capacity() - + young_gen->to()->capacity() - + young_gen->from()->capacity(); + GenCollectedHeap* gch = GenCollectedHeap::heap(); + GCCause::Cause gc_cause = gch->gc_cause(); + size_policy()->check_gc_overhead_limit(_young_gen->used(), + young_gen->eden()->used(), + _cmsGen->max_capacity(), + max_eden_size, + full, + gc_cause, + gch->collector_policy()); } else { do_mark_sweep_work(clear_all_soft_refs, first_state, should_start_over); @@ -1828,55 +1839,6 @@ return; } -void CMSCollector::check_gc_time_limit() { - - // Ignore explicit GC's. Exiting here does not set the flag and - // does not reset the count. Updating of the averages for system - // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC. - GCCause::Cause gc_cause = GenCollectedHeap::heap()->gc_cause(); - if (GCCause::is_user_requested_gc(gc_cause) || - GCCause::is_serviceability_requested_gc(gc_cause)) { - return; - } - - // Calculate the fraction of the CMS generation was freed during - // the last collection. - // Only consider the STW compacting cost for now. - // - // Note that the gc time limit test only works for the collections - // of the young gen + tenured gen and not for collections of the - // permanent gen. That is because the calculation of the space - // freed by the collection is the free space in the young gen + - // tenured gen. - - double fraction_free = - ((double)_cmsGen->free())/((double)_cmsGen->max_capacity()); - if ((100.0 * size_policy()->compacting_gc_cost()) > - ((double) GCTimeLimit) && - ((fraction_free * 100) < GCHeapFreeLimit)) { - size_policy()->inc_gc_time_limit_count(); - if (UseGCOverheadLimit && - (size_policy()->gc_time_limit_count() > - AdaptiveSizePolicyGCTimeLimitThreshold)) { - size_policy()->set_gc_time_limit_exceeded(true); - // Avoid consecutive OOM due to the gc time limit by resetting - // the counter. - size_policy()->reset_gc_time_limit_count(); - if (PrintGCDetails) { - gclog_or_tty->print_cr(" GC is exceeding overhead limit " - "of %d%%", GCTimeLimit); - } - } else { - if (PrintGCDetails) { - gclog_or_tty->print_cr(" GC would exceed overhead limit " - "of %d%%", GCTimeLimit); - } - } - } else { - size_policy()->reset_gc_time_limit_count(); - } -} - // Resize the perm generation and the tenured generation // after obtaining the free list locks for the // two generations. @@ -6182,6 +6144,11 @@ } curAddr = chunk.end(); } + // A successful mostly concurrent collection has been done. + // Because only the full (i.e., concurrent mode failure) collections + // are being measured for gc overhead limits, clean the "near" flag + // and count. + sp->reset_gc_overhead_limit_count(); _collectorState = Idling; } else { // already have the lock diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -570,10 +570,6 @@ ConcurrentMarkSweepPolicy* _collector_policy; ConcurrentMarkSweepPolicy* collector_policy() { return _collector_policy; } - // Check whether the gc time limit has been - // exceeded and set the size policy flag - // appropriately. - void check_gc_time_limit(); // XXX Move these to CMSStats ??? FIX ME !!! elapsedTimer _inter_sweep_timer; // time between sweeps elapsedTimer _intra_sweep_timer; // time _in_ sweeps diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -920,13 +920,19 @@ assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread"); + const bool do_clear_all_soft_refs = clear_all_soft_refs || + collector_policy()->should_clear_all_soft_refs(); + + ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); + { IsGCActiveMark x; // Timing gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - TraceTime t(full ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty); + TraceTime t(full ? "Full GC (System.gc())" : "Full GC", + PrintGC, true, gclog_or_tty); TraceMemoryManagerStats tms(true /* fullGC */); @@ -985,12 +991,12 @@ ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL); ref_processor()->enable_discovery(); - ref_processor()->setup_policy(clear_all_soft_refs); + ref_processor()->setup_policy(do_clear_all_soft_refs); // Do collection work { HandleMark hm; // Discard invalid handles created during gc - G1MarkSweep::invoke_at_safepoint(ref_processor(), clear_all_soft_refs); + G1MarkSweep::invoke_at_safepoint(ref_processor(), do_clear_all_soft_refs); } // Because freeing humongous regions may have added some unclean // regions, it is necessary to tear down again before rebuilding. @@ -1208,6 +1214,9 @@ return result; } + assert(!collector_policy()->should_clear_all_soft_refs(), + "Flag should have been handled and cleared prior to this point"); + // What else? We might try synchronous finalization later. If the total // space available is large enough for the allocation, then a more // complete compaction phase than we've tried so far might be diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,12 @@ bool clear_all_softrefs) { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); + SharedHeap* sh = SharedHeap::heap(); +#ifdef ASSERT + if (sh->collector_policy()->should_clear_all_soft_refs()) { + assert(clear_all_softrefs, "Policy should have been checked earler"); + } +#endif // hook up weak ref data so it can be used during Mark-Sweep assert(GenMarkSweep::ref_processor() == NULL, "no stomping"); assert(rp != NULL, "should be non-NULL"); @@ -44,7 +50,6 @@ // Increment the invocation count for the permanent generation, since it is // implicitly collected whenever we do a full mark sweep collection. - SharedHeap* sh = SharedHeap::heap(); sh->perm_gen()->stat_record()->invocations++; bool marked_for_unloading = false; diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ // -// Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. +// Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -161,8 +161,10 @@ parMarkBitMap.hpp bitMap.inline.hpp parMarkBitMap.hpp psVirtualspace.hpp +psAdaptiveSizePolicy.cpp collectorPolicy.hpp psAdaptiveSizePolicy.cpp gcPolicyCounters.hpp psAdaptiveSizePolicy.cpp gcCause.hpp +psAdaptiveSizePolicy.cpp generationSizer.hpp psAdaptiveSizePolicy.cpp psAdaptiveSizePolicy.hpp psAdaptiveSizePolicy.cpp psGCAdaptivePolicyCounters.hpp psAdaptiveSizePolicy.cpp psScavenge.hpp @@ -215,6 +217,7 @@ psMarkSweep.cpp fprofiler.hpp psMarkSweep.cpp gcCause.hpp psMarkSweep.cpp gcLocker.inline.hpp +psMarkSweep.cpp generationSizer.hpp psMarkSweep.cpp isGCActiveMark.hpp psMarkSweep.cpp oop.inline.hpp psMarkSweep.cpp memoryService.hpp @@ -256,6 +259,7 @@ psParallelCompact.cpp gcCause.hpp psParallelCompact.cpp gcLocker.inline.hpp psParallelCompact.cpp gcTaskManager.hpp +psParallelCompact.cpp generationSizer.hpp psParallelCompact.cpp isGCActiveMark.hpp psParallelCompact.cpp management.hpp psParallelCompact.cpp memoryService.hpp @@ -344,10 +348,12 @@ psScavenge.cpp psAdaptiveSizePolicy.hpp psScavenge.cpp biasedLocking.hpp psScavenge.cpp cardTableExtension.hpp +psScavenge.cpp collectorPolicy.hpp psScavenge.cpp fprofiler.hpp psScavenge.cpp gcCause.hpp psScavenge.cpp gcLocker.inline.hpp psScavenge.cpp gcTaskManager.hpp +psScavenge.cpp generationSizer.hpp psScavenge.cpp handles.inline.hpp psScavenge.cpp isGCActiveMark.hpp psScavenge.cpp oop.inline.hpp diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/includeDB_gc_serial --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_serial Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_serial Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ // -// Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. +// Copyright 2007-2010 Sun Microsystems, Inc. All Rights Reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ adaptiveSizePolicy.hpp universe.hpp adaptiveSizePolicy.cpp adaptiveSizePolicy.hpp +adaptiveSizePolicy.cpp collectorPolicy.hpp adaptiveSizePolicy.cpp gcCause.hpp adaptiveSizePolicy.cpp ostream.hpp adaptiveSizePolicy.cpp timer.hpp diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -892,6 +892,10 @@ } swap_spaces(); + // A successful scavenge should restart the GC time limit count which is + // for full GC's. + size_policy->reset_gc_overhead_limit_count(); + assert(to()->is_empty(), "to space should be empty now"); } else { assert(HandlePromotionFailure, diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,15 +54,16 @@ CollectedHeap::pre_initialize(); // Cannot be initialized until after the flags are parsed - GenerationSizer flag_parser; + // GenerationSizer flag_parser; + _collector_policy = new GenerationSizer(); - size_t yg_min_size = flag_parser.min_young_gen_size(); - size_t yg_max_size = flag_parser.max_young_gen_size(); - size_t og_min_size = flag_parser.min_old_gen_size(); - size_t og_max_size = flag_parser.max_old_gen_size(); + size_t yg_min_size = _collector_policy->min_young_gen_size(); + size_t yg_max_size = _collector_policy->max_young_gen_size(); + size_t og_min_size = _collector_policy->min_old_gen_size(); + size_t og_max_size = _collector_policy->max_old_gen_size(); // Why isn't there a min_perm_gen_size()? - size_t pg_min_size = flag_parser.perm_gen_size(); - size_t pg_max_size = flag_parser.max_perm_gen_size(); + size_t pg_min_size = _collector_policy->perm_gen_size(); + size_t pg_max_size = _collector_policy->max_perm_gen_size(); trace_gen_sizes("ps heap raw", pg_min_size, pg_max_size, @@ -89,12 +90,14 @@ // move to the common code. yg_min_size = align_size_up(yg_min_size, yg_align); yg_max_size = align_size_up(yg_max_size, yg_align); - size_t yg_cur_size = align_size_up(flag_parser.young_gen_size(), yg_align); + size_t yg_cur_size = + align_size_up(_collector_policy->young_gen_size(), yg_align); yg_cur_size = MAX2(yg_cur_size, yg_min_size); og_min_size = align_size_up(og_min_size, og_align); og_max_size = align_size_up(og_max_size, og_align); - size_t og_cur_size = align_size_up(flag_parser.old_gen_size(), og_align); + size_t og_cur_size = + align_size_up(_collector_policy->old_gen_size(), og_align); og_cur_size = MAX2(og_cur_size, og_min_size); pg_min_size = align_size_up(pg_min_size, pg_align); @@ -355,6 +358,11 @@ assert(Thread::current() != (Thread*)VMThread::vm_thread(), "should not be in vm thread"); assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock"); + // In general gc_overhead_limit_was_exceeded should be false so + // set it so here and reset it to true only if the gc time + // limit is being exceeded as checked below. + *gc_overhead_limit_was_exceeded = false; + HeapWord* result = young_gen()->allocate(size, is_tlab); uint loop_count = 0; @@ -428,24 +436,6 @@ if (result == NULL) { - // Exit the loop if if the gc time limit has been exceeded. - // The allocation must have failed above (result must be NULL), - // and the most recent collection must have exceeded the - // gc time limit. Exit the loop so that an out-of-memory - // will be thrown (returning a NULL will do that), but - // clear gc_time_limit_exceeded so that the next collection - // will succeeded if the applications decides to handle the - // out-of-memory and tries to go on. - *gc_overhead_limit_was_exceeded = size_policy()->gc_time_limit_exceeded(); - if (size_policy()->gc_time_limit_exceeded()) { - size_policy()->set_gc_time_limit_exceeded(false); - if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("ParallelScavengeHeap::mem_allocate: " - "return NULL because gc_time_limit_exceeded is set"); - } - return NULL; - } - // Generate a VM operation VM_ParallelGCFailedAllocation op(size, is_tlab, gc_count); VMThread::execute(&op); @@ -463,16 +453,34 @@ assert(op.result() == NULL, "must be NULL if gc_locked() is true"); continue; // retry and/or stall as necessary } - // If a NULL result is being returned, an out-of-memory - // will be thrown now. Clear the gc_time_limit_exceeded - // flag to avoid the following situation. - // gc_time_limit_exceeded is set during a collection - // the collection fails to return enough space and an OOM is thrown - // the next GC is skipped because the gc_time_limit_exceeded - // flag is set and another OOM is thrown - if (op.result() == NULL) { - size_policy()->set_gc_time_limit_exceeded(false); + + // Exit the loop if the gc time limit has been exceeded. + // The allocation must have failed above ("result" guarding + // this path is NULL) and the most recent collection has exceeded the + // gc overhead limit (although enough may have been collected to + // satisfy the allocation). Exit the loop so that an out-of-memory + // will be thrown (return a NULL ignoring the contents of + // op.result()), + // but clear gc_overhead_limit_exceeded so that the next collection + // starts with a clean slate (i.e., forgets about previous overhead + // excesses). Fill op.result() with a filler object so that the + // heap remains parsable. + const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded(); + const bool softrefs_clear = collector_policy()->all_soft_refs_clear(); + assert(!limit_exceeded || softrefs_clear, "Should have been cleared"); + if (limit_exceeded && softrefs_clear) { + *gc_overhead_limit_was_exceeded = true; + size_policy()->set_gc_overhead_limit_exceeded(false); + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr("ParallelScavengeHeap::mem_allocate: " + "return NULL because gc_overhead_limit_exceeded is set"); + } + if (op.result() != NULL) { + CollectedHeap::fill_with_object(op.result(), size); + } + return NULL; } + return op.result(); } } @@ -613,14 +621,15 @@ // and the most recent collection must have exceeded the // gc time limit. Exit the loop so that an out-of-memory // will be thrown (returning a NULL will do that), but - // clear gc_time_limit_exceeded so that the next collection + // clear gc_overhead_limit_exceeded so that the next collection // will succeeded if the applications decides to handle the // out-of-memory and tries to go on. - if (size_policy()->gc_time_limit_exceeded()) { - size_policy()->set_gc_time_limit_exceeded(false); + const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded(); + if (limit_exceeded) { + size_policy()->set_gc_overhead_limit_exceeded(false); if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("ParallelScavengeHeap::permanent_mem_allocate: " - "return NULL because gc_time_limit_exceeded is set"); + gclog_or_tty->print_cr("ParallelScavengeHeap::permanent_mem_allocate:" + " return NULL because gc_overhead_limit_exceeded is set"); } assert(result == NULL, "Allocation did not fail"); return NULL; @@ -643,14 +652,15 @@ continue; // retry and/or stall as necessary } // If a NULL results is being returned, an out-of-memory - // will be thrown now. Clear the gc_time_limit_exceeded + // will be thrown now. Clear the gc_overhead_limit_exceeded // flag to avoid the following situation. - // gc_time_limit_exceeded is set during a collection + // gc_overhead_limit_exceeded is set during a collection // the collection fails to return enough space and an OOM is thrown - // the next GC is skipped because the gc_time_limit_exceeded - // flag is set and another OOM is thrown + // a subsequent GC prematurely throws an out-of-memory because + // the gc_overhead_limit_exceeded counts did not start + // again from 0. if (op.result() == NULL) { - size_policy()->set_gc_time_limit_exceeded(false); + size_policy()->reset_gc_overhead_limit_count(); } return op.result(); } diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ class AdjoiningGenerations; class GCTaskManager; class PSAdaptiveSizePolicy; +class GenerationSizer; +class CollectorPolicy; class ParallelScavengeHeap : public CollectedHeap { friend class VMStructs; @@ -43,6 +45,8 @@ size_t _young_gen_alignment; size_t _old_gen_alignment; + GenerationSizer* _collector_policy; + inline size_t set_alignment(size_t& var, size_t val); // Collection of generations that are adjacent in the @@ -72,6 +76,9 @@ return CollectedHeap::ParallelScavengeHeap; } +CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; } + // GenerationSizer* collector_policy() const { return _collector_policy; } + static PSYoungGen* young_gen() { return _young_gen; } static PSOldGen* old_gen() { return _old_gen; } static PSPermGen* perm_gen() { return _perm_gen; } diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,18 +184,19 @@ set_change_young_gen_for_maj_pauses(0); } - // If this is not a full GC, only test and modify the young generation. -void PSAdaptiveSizePolicy::compute_generation_free_space(size_t young_live, - size_t eden_live, - size_t old_live, - size_t perm_live, - size_t cur_eden, - size_t max_old_gen_size, - size_t max_eden_size, - bool is_full_gc, - GCCause::Cause gc_cause) { +void PSAdaptiveSizePolicy::compute_generation_free_space( + size_t young_live, + size_t eden_live, + size_t old_live, + size_t perm_live, + size_t cur_eden, + size_t max_old_gen_size, + size_t max_eden_size, + bool is_full_gc, + GCCause::Cause gc_cause, + CollectorPolicy* collector_policy) { // Update statistics // Time statistics are updated as we go, update footprint stats here @@ -380,91 +381,16 @@ // Is too much time being spent in GC? // Is the heap trying to grow beyond it's limits? - const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average()); + const size_t free_in_old_gen = + (size_t)(max_old_gen_size - avg_old_live()->average()); if (desired_promo_size > free_in_old_gen && desired_eden_size > eden_limit) { - - // eden_limit is the upper limit on the size of eden based on - // the maximum size of the young generation and the sizes - // of the survivor space. - // The question being asked is whether the gc costs are high - // and the space being recovered by a collection is low. - // free_in_young_gen is the free space in the young generation - // after a collection and promo_live is the free space in the old - // generation after a collection. - // - // Use the minimum of the current value of the live in the - // young gen or the average of the live in the young gen. - // If the current value drops quickly, that should be taken - // into account (i.e., don't trigger if the amount of free - // space has suddenly jumped up). If the current is much - // higher than the average, use the average since it represents - // the longer term behavor. - const size_t live_in_eden = MIN2(eden_live, (size_t) avg_eden_live()->average()); - const size_t free_in_eden = eden_limit > live_in_eden ? - eden_limit - live_in_eden : 0; - const size_t total_free_limit = free_in_old_gen + free_in_eden; - const size_t total_mem = max_old_gen_size + max_eden_size; - const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0); - if (PrintAdaptiveSizePolicy && (Verbose || - (total_free_limit < (size_t) mem_free_limit))) { - gclog_or_tty->print_cr( - "PSAdaptiveSizePolicy::compute_generation_free_space limits:" - " promo_limit: " SIZE_FORMAT - " eden_limit: " SIZE_FORMAT - " total_free_limit: " SIZE_FORMAT - " max_old_gen_size: " SIZE_FORMAT - " max_eden_size: " SIZE_FORMAT - " mem_free_limit: " SIZE_FORMAT, - promo_limit, eden_limit, total_free_limit, - max_old_gen_size, max_eden_size, - (size_t) mem_free_limit); - } - - if (is_full_gc) { - if (gc_cost() > gc_cost_limit && - total_free_limit < (size_t) mem_free_limit) { - // Collections, on average, are taking too much time, and - // gc_cost() > gc_cost_limit - // we have too little space available after a full gc. - // total_free_limit < mem_free_limit - // where - // total_free_limit is the free space available in - // both generations - // total_mem is the total space available for allocation - // in both generations (survivor spaces are not included - // just as they are not included in eden_limit). - // mem_free_limit is a fraction of total_mem judged to be an - // acceptable amount that is still unused. - // The heap can ask for the value of this variable when deciding - // whether to thrown an OutOfMemory error. - // Note that the gc time limit test only works for the collections - // of the young gen + tenured gen and not for collections of the - // permanent gen. That is because the calculation of the space - // freed by the collection is the free space in the young gen + - // tenured gen. - // Ignore explicit GC's. Ignoring explicit GC's at this level - // is the equivalent of the GC did not happen as far as the - // overhead calculation is concerted (i.e., the flag is not set - // and the count is not affected). Also the average will not - // have been updated unless UseAdaptiveSizePolicyWithSystemGC is on. - if (!GCCause::is_user_requested_gc(gc_cause) && - !GCCause::is_serviceability_requested_gc(gc_cause)) { - inc_gc_time_limit_count(); - if (UseGCOverheadLimit && - (gc_time_limit_count() > AdaptiveSizePolicyGCTimeLimitThreshold)){ - // All conditions have been met for throwing an out-of-memory - _gc_time_limit_exceeded = true; - // Avoid consecutive OOM due to the gc time limit by resetting - // the counter. - reset_gc_time_limit_count(); - } - _print_gc_time_limit_would_be_exceeded = true; - } - } else { - // Did not exceed overhead limits - reset_gc_time_limit_count(); - } - } + check_gc_overhead_limit(young_live, + eden_live, + max_old_gen_size, + max_eden_size, + is_full_gc, + gc_cause, + collector_policy); } diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ // Forward decls class elapsedTimer; +class GenerationSizer; class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { friend class PSGCAdaptivePolicyCounters; @@ -340,7 +341,8 @@ size_t max_old_gen_size, size_t max_eden_size, bool is_full_gc, - GCCause::Cause gc_cause); + GCCause::Cause gc_cause, + CollectorPolicy* collector_policy); // Calculates new survivor space size; returns a new tenuring threshold // value. Stores new survivor size in _survivor_size. diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,11 +117,13 @@ PerfData::U_Bytes, (jlong) ps_size_policy()->avg_base_footprint()->average(), CHECK); cname = PerfDataManager::counter_name(name_space(), "gcTimeLimitExceeded"); - _gc_time_limit_exceeded = PerfDataManager::create_variable(SUN_GC, cname, - PerfData::U_Events, ps_size_policy()->gc_time_limit_exceeded(), CHECK); + _gc_overhead_limit_exceeded_counter = + PerfDataManager::create_variable(SUN_GC, cname, + PerfData::U_Events, ps_size_policy()->gc_overhead_limit_exceeded(), CHECK); cname = PerfDataManager::counter_name(name_space(), "liveAtLastFullGc"); - _live_at_last_full_gc = PerfDataManager::create_variable(SUN_GC, cname, + _live_at_last_full_gc_counter = + PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, ps_size_policy()->live_at_last_full_gc(), CHECK); cname = PerfDataManager::counter_name(name_space(), "majorPauseOldSlope"); @@ -189,6 +191,8 @@ update_minor_pause_old_slope(); update_major_pause_young_slope(); update_minor_collection_slope_counter(); + update_gc_overhead_limit_exceeded_counter(); + update_live_at_last_full_gc_counter(); } } diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,8 +44,8 @@ PerfVariable* _live_space; PerfVariable* _free_space; PerfVariable* _avg_base_footprint; - PerfVariable* _gc_time_limit_exceeded; - PerfVariable* _live_at_last_full_gc; + PerfVariable* _gc_overhead_limit_exceeded_counter; + PerfVariable* _live_at_last_full_gc_counter; PerfVariable* _old_capacity; PerfVariable* _boundary_moved; @@ -169,6 +169,14 @@ (jlong)(ps_size_policy()->major_pause_young_slope() * 1000) ); } + inline void update_gc_overhead_limit_exceeded_counter() { + _gc_overhead_limit_exceeded_counter->set_value( + (jlong) ps_size_policy()->gc_overhead_limit_exceeded()); + } + inline void update_live_at_last_full_gc_counter() { + _live_at_last_full_gc_counter->set_value( + (jlong)(ps_size_policy()->live_at_last_full_gc())); + } inline void update_scavenge_skipped(int cause) { _scavenge_skipped->set_value(cause); diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,12 @@ // // Note that this method should only be called from the vm_thread while // at a safepoint! +// +// Note that the all_soft_refs_clear flag in the collector policy +// may be true because this method can be called without intervening +// activity. For example when the heap space is tight and full measure +// are being taken to free space. + void PSMarkSweep::invoke(bool maximum_heap_compaction) { assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread"); @@ -54,24 +60,18 @@ ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); GCCause::Cause gc_cause = heap->gc_cause(); PSAdaptiveSizePolicy* policy = heap->size_policy(); + IsGCActiveMark mark; - // Before each allocation/collection attempt, find out from the - // policy object if GCs are, on the whole, taking too long. If so, - // bail out without attempting a collection. The exceptions are - // for explicitly requested GC's. - if (!policy->gc_time_limit_exceeded() || - GCCause::is_user_requested_gc(gc_cause) || - GCCause::is_serviceability_requested_gc(gc_cause)) { - IsGCActiveMark mark; + if (ScavengeBeforeFullGC) { + PSScavenge::invoke_no_policy(); + } - if (ScavengeBeforeFullGC) { - PSScavenge::invoke_no_policy(); - } + const bool clear_all_soft_refs = + heap->collector_policy()->should_clear_all_soft_refs(); - int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount; - IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count); - PSMarkSweep::invoke_no_policy(maximum_heap_compaction); - } + int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount; + IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count); + PSMarkSweep::invoke_no_policy(clear_all_soft_refs || maximum_heap_compaction); } // This method contains no policy. You should probably @@ -89,6 +89,10 @@ assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); PSAdaptiveSizePolicy* size_policy = heap->size_policy(); + // The scope of casr should end after code that can change + // CollectorPolicy::_should_clear_all_soft_refs. + ClearedAllSoftRefs casr(clear_all_softrefs, heap->collector_policy()); + PSYoungGen* young_gen = heap->young_gen(); PSOldGen* old_gen = heap->old_gen(); PSPermGen* perm_gen = heap->perm_gen(); @@ -275,7 +279,8 @@ old_gen->max_gen_size(), max_eden_size, true /* full gc*/, - gc_cause); + gc_cause, + heap->collector_policy()); heap->resize_old_gen(size_policy->calculated_old_free_size_in_bytes()); @@ -326,19 +331,6 @@ // Track memory usage and detect low memory MemoryService::track_memory_usage(); heap->update_counters(); - - if (PrintGCDetails) { - if (size_policy->print_gc_time_limit_would_be_exceeded()) { - if (size_policy->gc_time_limit_exceeded()) { - gclog_or_tty->print_cr(" GC time is exceeding GCTimeLimit " - "of %d%%", GCTimeLimit); - } else { - gclog_or_tty->print_cr(" GC time would exceed GCTimeLimit " - "of %d%%", GCTimeLimit); - } - } - size_policy->set_print_gc_time_limit_would_be_exceeded(false); - } } if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) { diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1923,31 +1923,32 @@ // // Note that this method should only be called from the vm_thread while at a // safepoint. +// +// Note that the all_soft_refs_clear flag in the collector policy +// may be true because this method can be called without intervening +// activity. For example when the heap space is tight and full measure +// are being taken to free space. void PSParallelCompact::invoke(bool maximum_heap_compaction) { assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread"); + ParallelScavengeHeap* heap = gc_heap(); GCCause::Cause gc_cause = heap->gc_cause(); assert(!heap->is_gc_active(), "not reentrant"); PSAdaptiveSizePolicy* policy = heap->size_policy(); - - // Before each allocation/collection attempt, find out from the - // policy object if GCs are, on the whole, taking too long. If so, - // bail out without attempting a collection. The exceptions are - // for explicitly requested GC's. - if (!policy->gc_time_limit_exceeded() || - GCCause::is_user_requested_gc(gc_cause) || - GCCause::is_serviceability_requested_gc(gc_cause)) { - IsGCActiveMark mark; - - if (ScavengeBeforeFullGC) { - PSScavenge::invoke_no_policy(); - } - - PSParallelCompact::invoke_no_policy(maximum_heap_compaction); + IsGCActiveMark mark; + + if (ScavengeBeforeFullGC) { + PSScavenge::invoke_no_policy(); } + + const bool clear_all_soft_refs = + heap->collector_policy()->should_clear_all_soft_refs(); + + PSParallelCompact::invoke_no_policy(clear_all_soft_refs || + maximum_heap_compaction); } bool ParallelCompactData::region_contains(size_t region_index, HeapWord* addr) { @@ -1976,6 +1977,11 @@ PSPermGen* perm_gen = heap->perm_gen(); PSAdaptiveSizePolicy* size_policy = heap->size_policy(); + // The scope of casr should end after code that can change + // CollectorPolicy::_should_clear_all_soft_refs. + ClearedAllSoftRefs casr(maximum_heap_compaction, + heap->collector_policy()); + if (ZapUnusedHeapArea) { // Save information needed to minimize mangling heap->record_gen_tops_before_GC(); @@ -2109,7 +2115,8 @@ old_gen->max_gen_size(), max_eden_size, true /* full gc*/, - gc_cause); + gc_cause, + heap->collector_policy()); heap->resize_old_gen( size_policy->calculated_old_free_size_in_bytes()); @@ -2157,19 +2164,6 @@ // Track memory usage and detect low memory MemoryService::track_memory_usage(); heap->update_counters(); - - if (PrintGCDetails) { - if (size_policy->print_gc_time_limit_would_be_exceeded()) { - if (size_policy->gc_time_limit_exceeded()) { - gclog_or_tty->print_cr(" GC time is exceeding GCTimeLimit " - "of %d%%", GCTimeLimit); - } else { - gclog_or_tty->print_cr(" GC time would exceed GCTimeLimit " - "of %d%%", GCTimeLimit); - } - } - size_policy->set_print_gc_time_limit_would_be_exceeded(false); - } } if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) { diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,8 +187,7 @@ // // Note that this method should only be called from the vm_thread while // at a safepoint! -void PSScavenge::invoke() -{ +void PSScavenge::invoke() { assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread"); assert(!Universe::heap()->is_gc_active(), "not reentrant"); @@ -197,29 +196,25 @@ assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); PSAdaptiveSizePolicy* policy = heap->size_policy(); + IsGCActiveMark mark; - // Before each allocation/collection attempt, find out from the - // policy object if GCs are, on the whole, taking too long. If so, - // bail out without attempting a collection. - if (!policy->gc_time_limit_exceeded()) { - IsGCActiveMark mark; + bool scavenge_was_done = PSScavenge::invoke_no_policy(); - bool scavenge_was_done = PSScavenge::invoke_no_policy(); - - PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters(); + PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters(); + if (UsePerfData) + counters->update_full_follows_scavenge(0); + if (!scavenge_was_done || + policy->should_full_GC(heap->old_gen()->free_in_bytes())) { if (UsePerfData) - counters->update_full_follows_scavenge(0); - if (!scavenge_was_done || - policy->should_full_GC(heap->old_gen()->free_in_bytes())) { - if (UsePerfData) - counters->update_full_follows_scavenge(full_follows_scavenge); + counters->update_full_follows_scavenge(full_follows_scavenge); + GCCauseSetter gccs(heap, GCCause::_adaptive_size_policy); + CollectorPolicy* cp = heap->collector_policy(); + const bool clear_all_softrefs = cp->should_clear_all_soft_refs(); - GCCauseSetter gccs(heap, GCCause::_adaptive_size_policy); - if (UseParallelOldGC) { - PSParallelCompact::invoke_no_policy(false); - } else { - PSMarkSweep::invoke_no_policy(false); - } + if (UseParallelOldGC) { + PSParallelCompact::invoke_no_policy(clear_all_softrefs); + } else { + PSMarkSweep::invoke_no_policy(clear_all_softrefs); } } } @@ -447,6 +442,9 @@ size_t promoted = old_gen->used_in_bytes() - old_gen_used_before; size_policy->update_averages(_survivor_overflow, survived, promoted); + // A successful scavenge should restart the GC time limit count which is + // for full GC's. + size_policy->reset_gc_overhead_limit_count(); if (UseAdaptiveSizePolicy) { // Calculate the new survivor size and tenuring threshold @@ -523,7 +521,8 @@ old_gen->max_gen_size(), max_eden_size, false /* full gc*/, - gc_cause); + gc_cause, + heap->collector_policy()); } // Resize the young generation at every collection diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,13 +44,15 @@ _survivor_size(init_survivor_size), _gc_pause_goal_sec(gc_pause_goal_sec), _throughput_goal(1.0 - double(1.0 / (1.0 + (double) gc_cost_ratio))), - _gc_time_limit_exceeded(false), - _print_gc_time_limit_would_be_exceeded(false), - _gc_time_limit_count(0), + _gc_overhead_limit_exceeded(false), + _print_gc_overhead_limit_would_be_exceeded(false), + _gc_overhead_limit_count(0), _latest_minor_mutator_interval_seconds(0), _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0), _young_gen_change_for_minor_throughput(0), _old_gen_change_for_major_throughput(0) { + assert(AdaptiveSizePolicyGCTimeLimitThreshold > 0, + "No opportunity to clear SoftReferences before GC overhead limit"); _avg_minor_pause = new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding); _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight); @@ -278,6 +280,147 @@ set_decide_at_full_gc(0); } +void AdaptiveSizePolicy::check_gc_overhead_limit( + size_t young_live, + size_t eden_live, + size_t max_old_gen_size, + size_t max_eden_size, + bool is_full_gc, + GCCause::Cause gc_cause, + CollectorPolicy* collector_policy) { + + // Ignore explicit GC's. Exiting here does not set the flag and + // does not reset the count. Updating of the averages for system + // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC. + if (GCCause::is_user_requested_gc(gc_cause) || + GCCause::is_serviceability_requested_gc(gc_cause)) { + return; + } + // eden_limit is the upper limit on the size of eden based on + // the maximum size of the young generation and the sizes + // of the survivor space. + // The question being asked is whether the gc costs are high + // and the space being recovered by a collection is low. + // free_in_young_gen is the free space in the young generation + // after a collection and promo_live is the free space in the old + // generation after a collection. + // + // Use the minimum of the current value of the live in the + // young gen or the average of the live in the young gen. + // If the current value drops quickly, that should be taken + // into account (i.e., don't trigger if the amount of free + // space has suddenly jumped up). If the current is much + // higher than the average, use the average since it represents + // the longer term behavor. + const size_t live_in_eden = + MIN2(eden_live, (size_t) avg_eden_live()->average()); + const size_t free_in_eden = max_eden_size > live_in_eden ? + max_eden_size - live_in_eden : 0; + const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average()); + const size_t total_free_limit = free_in_old_gen + free_in_eden; + const size_t total_mem = max_old_gen_size + max_eden_size; + const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0); + const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0); + const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0); + const double gc_cost_limit = GCTimeLimit/100.0; + size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average()); + // But don't force a promo size below the current promo size. Otherwise, + // the promo size will shrink for no good reason. + promo_limit = MAX2(promo_limit, _promo_size); + + + if (PrintAdaptiveSizePolicy && (Verbose || + (free_in_old_gen < (size_t) mem_free_old_limit && + free_in_eden < (size_t) mem_free_eden_limit))) { + gclog_or_tty->print_cr( + "PSAdaptiveSizePolicy::compute_generation_free_space limits:" + " promo_limit: " SIZE_FORMAT + " max_eden_size: " SIZE_FORMAT + " total_free_limit: " SIZE_FORMAT + " max_old_gen_size: " SIZE_FORMAT + " max_eden_size: " SIZE_FORMAT + " mem_free_limit: " SIZE_FORMAT, + promo_limit, max_eden_size, total_free_limit, + max_old_gen_size, max_eden_size, + (size_t) mem_free_limit); + } + + bool print_gc_overhead_limit_would_be_exceeded = false; + if (is_full_gc) { + if (gc_cost() > gc_cost_limit && + free_in_old_gen < (size_t) mem_free_old_limit && + free_in_eden < (size_t) mem_free_eden_limit) { + // Collections, on average, are taking too much time, and + // gc_cost() > gc_cost_limit + // we have too little space available after a full gc. + // total_free_limit < mem_free_limit + // where + // total_free_limit is the free space available in + // both generations + // total_mem is the total space available for allocation + // in both generations (survivor spaces are not included + // just as they are not included in eden_limit). + // mem_free_limit is a fraction of total_mem judged to be an + // acceptable amount that is still unused. + // The heap can ask for the value of this variable when deciding + // whether to thrown an OutOfMemory error. + // Note that the gc time limit test only works for the collections + // of the young gen + tenured gen and not for collections of the + // permanent gen. That is because the calculation of the space + // freed by the collection is the free space in the young gen + + // tenured gen. + // At this point the GC overhead limit is being exceeded. + inc_gc_overhead_limit_count(); + if (UseGCOverheadLimit) { + if (gc_overhead_limit_count() >= + AdaptiveSizePolicyGCTimeLimitThreshold){ + // All conditions have been met for throwing an out-of-memory + set_gc_overhead_limit_exceeded(true); + // Avoid consecutive OOM due to the gc time limit by resetting + // the counter. + reset_gc_overhead_limit_count(); + } else { + // The required consecutive collections which exceed the + // GC time limit may or may not have been reached. We + // are approaching that condition and so as not to + // throw an out-of-memory before all SoftRef's have been + // cleared, set _should_clear_all_soft_refs in CollectorPolicy. + // The clearing will be done on the next GC. + bool near_limit = gc_overhead_limit_near(); + if (near_limit) { + collector_policy->set_should_clear_all_soft_refs(true); + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr(" Nearing GC overhead limit, " + "will be clearing all SoftReference"); + } + } + } + } + // Set this even when the overhead limit will not + // cause an out-of-memory. Diagnostic message indicating + // that the overhead limit is being exceeded is sometimes + // printed. + print_gc_overhead_limit_would_be_exceeded = true; + + } else { + // Did not exceed overhead limits + reset_gc_overhead_limit_count(); + } + } + + if (UseGCOverheadLimit && PrintGCDetails && Verbose) { + if (gc_overhead_limit_exceeded()) { + gclog_or_tty->print_cr(" GC is exceeding overhead limit " + "of %d%%", GCTimeLimit); + reset_gc_overhead_limit_count(); + } else if (print_gc_overhead_limit_would_be_exceeded) { + assert(gc_overhead_limit_count() > 0, "Should not be printing"); + gclog_or_tty->print_cr(" GC would exceed overhead limit " + "of %d%% %d consecutive time(s)", + GCTimeLimit, gc_overhead_limit_count()); + } + } +} // Printing bool AdaptiveSizePolicy::print_adaptive_size_policy_on(outputStream* st) const { diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ // Forward decls class elapsedTimer; +class CollectorPolicy; class AdaptiveSizePolicy : public CHeapObj { friend class GCAdaptivePolicyCounters; @@ -75,13 +76,16 @@ // This is a hint for the heap: we've detected that gc times // are taking longer than GCTimeLimit allows. - bool _gc_time_limit_exceeded; - // Use for diagnostics only. If UseGCTimeLimit is false, + bool _gc_overhead_limit_exceeded; + // Use for diagnostics only. If UseGCOverheadLimit is false, // this variable is still set. - bool _print_gc_time_limit_would_be_exceeded; + bool _print_gc_overhead_limit_would_be_exceeded; // Count of consecutive GC that have exceeded the // GC time limit criterion. - uint _gc_time_limit_count; + uint _gc_overhead_limit_count; + // This flag signals that GCTimeLimit is being exceeded + // but may not have done so for the required number of consequetive + // collections. // Minor collection timers used to determine both // pause and interval times for collections. @@ -406,22 +410,21 @@ // Most heaps will choose to throw an OutOfMemoryError when // this occurs but it is up to the heap to request this information // of the policy - bool gc_time_limit_exceeded() { - return _gc_time_limit_exceeded; - } - void set_gc_time_limit_exceeded(bool v) { - _gc_time_limit_exceeded = v; + bool gc_overhead_limit_exceeded() { + return _gc_overhead_limit_exceeded; } - bool print_gc_time_limit_would_be_exceeded() { - return _print_gc_time_limit_would_be_exceeded; - } - void set_print_gc_time_limit_would_be_exceeded(bool v) { - _print_gc_time_limit_would_be_exceeded = v; + void set_gc_overhead_limit_exceeded(bool v) { + _gc_overhead_limit_exceeded = v; } - uint gc_time_limit_count() { return _gc_time_limit_count; } - void reset_gc_time_limit_count() { _gc_time_limit_count = 0; } - void inc_gc_time_limit_count() { _gc_time_limit_count++; } + // Tests conditions indicate the GC overhead limit is being approached. + bool gc_overhead_limit_near() { + return gc_overhead_limit_count() >= + (AdaptiveSizePolicyGCTimeLimitThreshold - 1); + } + uint gc_overhead_limit_count() { return _gc_overhead_limit_count; } + void reset_gc_overhead_limit_count() { _gc_overhead_limit_count = 0; } + void inc_gc_overhead_limit_count() { _gc_overhead_limit_count++; } // accessors for flags recording the decisions to resize the // generations to meet the pause goal. @@ -436,6 +439,16 @@ int decide_at_full_gc() { return _decide_at_full_gc; } void set_decide_at_full_gc(int v) { _decide_at_full_gc = v; } + // Check the conditions for an out-of-memory due to excessive GC time. + // Set _gc_overhead_limit_exceeded if all the conditions have been met. + void check_gc_overhead_limit(size_t young_live, + size_t eden_live, + size_t max_old_gen_size, + size_t max_eden_size, + bool is_full_gc, + GCCause::Cause gc_cause, + CollectorPolicy* collector_policy); + // Printing support virtual bool print_adaptive_size_policy_on(outputStream* st) const; bool print_adaptive_size_policy_on(outputStream* st, int diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,8 +89,19 @@ if (full) { _full_gc_count_before = full_gc_count_before; } + // In ParallelScavengeHeap::mem_allocate() collections can be + // executed within a loop and _all_soft_refs_clear can be set + // true after they have been cleared by a collection and another + // collection started so that _all_soft_refs_clear can be true + // when this collection is started. Don't assert that + // _all_soft_refs_clear have to be false here even though + // mutators have run. Soft refs will be cleared again in this + // collection. } - ~VM_GC_Operation() {} + ~VM_GC_Operation() { + CollectedHeap* ch = Universe::heap(); + ch->collector_policy()->set_all_soft_refs_clear(false); + } // Acquire the reference synchronization lock virtual bool doit_prologue(); diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ class ThreadClosure; class AdaptiveSizePolicy; class Thread; +class CollectorPolicy; // // CollectedHeap @@ -506,6 +507,9 @@ // Return the AdaptiveSizePolicy for the heap. virtual AdaptiveSizePolicy* size_policy() = 0; + // Return the CollectorPolicy for the heap + virtual CollectorPolicy* collector_policy() const = 0; + // Iterate over all the ref-containing fields of all objects, calling // "cl.do_oop" on each. This includes objects in permanent memory. virtual void oop_iterate(OopClosure* cl) = 0; diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/memory/collectorPolicy.cpp --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,6 +112,11 @@ } } +bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) { + bool result = _should_clear_all_soft_refs; + set_should_clear_all_soft_refs(false); + return result; +} GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap, int max_covered_regions) { @@ -126,6 +131,17 @@ } } +void CollectorPolicy::cleared_all_soft_refs() { + // If near gc overhear limit, continue to clear SoftRefs. SoftRefs may + // have been cleared in the last collection but if the gc overhear + // limit continues to be near, SoftRefs should still be cleared. + if (size_policy() != NULL) { + _should_clear_all_soft_refs = size_policy()->gc_overhead_limit_near(); + } + _all_soft_refs_clear = true; +} + + // GenCollectorPolicy methods. size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) { @@ -489,6 +505,12 @@ debug_only(gch->check_for_valid_allocation_state()); assert(gch->no_gc_in_progress(), "Allocation during gc not allowed"); + + // In general gc_overhead_limit_was_exceeded should be false so + // set it so here and reset it to true only if the gc time + // limit is being exceeded as checked below. + *gc_overhead_limit_was_exceeded = false; + HeapWord* result = NULL; // Loop until the allocation is satisified, @@ -524,12 +546,6 @@ return result; } - // There are NULL's returned for different circumstances below. - // In general gc_overhead_limit_was_exceeded should be false so - // set it so here and reset it to true only if the gc time - // limit is being exceeded as checked below. - *gc_overhead_limit_was_exceeded = false; - if (GC_locker::is_active_and_needs_gc()) { if (is_tlab) { return NULL; // Caller will retry allocating individual object @@ -568,18 +584,6 @@ gc_count_before = Universe::heap()->total_collections(); } - // Allocation has failed and a collection is about - // to be done. If the gc time limit was exceeded the - // last time a collection was done, return NULL so - // that an out-of-memory will be thrown. Clear - // gc_time_limit_exceeded so that subsequent attempts - // at a collection will be made. - if (size_policy()->gc_time_limit_exceeded()) { - *gc_overhead_limit_was_exceeded = true; - size_policy()->set_gc_time_limit_exceeded(false); - return NULL; - } - VM_GenCollectForAllocation op(size, is_tlab, gc_count_before); @@ -590,6 +594,24 @@ assert(result == NULL, "must be NULL if gc_locked() is true"); continue; // retry and/or stall as necessary } + + // Allocation has failed and a collection + // has been done. If the gc time limit was exceeded the + // this time, return NULL so that an out-of-memory + // will be thrown. Clear gc_overhead_limit_exceeded + // so that the overhead exceeded does not persist. + + const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded(); + const bool softrefs_clear = all_soft_refs_clear(); + assert(!limit_exceeded || softrefs_clear, "Should have been cleared"); + if (limit_exceeded && softrefs_clear) { + *gc_overhead_limit_was_exceeded = true; + size_policy()->set_gc_overhead_limit_exceeded(false); + if (op.result() != NULL) { + CollectedHeap::fill_with_object(op.result(), size); + } + return NULL; + } assert(result == NULL || gch->is_in_reserved(result), "result not in heap"); return result; @@ -688,6 +710,9 @@ return result; } + assert(!should_clear_all_soft_refs(), + "Flag should have been handled and cleared prior to this point"); + // What else? We might try synchronous finalization later. If the total // space available is large enough for the allocation, then a more // complete compaction phase than we've tried so far might be diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/memory/collectorPolicy.hpp --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,12 +69,28 @@ size_t _min_alignment; size_t _max_alignment; + // The sizing of the heap are controlled by a sizing policy. + AdaptiveSizePolicy* _size_policy; + + // Set to true when policy wants soft refs cleared. + // Reset to false by gc after it clears all soft refs. + bool _should_clear_all_soft_refs; + // Set to true by the GC if the just-completed gc cleared all + // softrefs. This is set to true whenever a gc clears all softrefs, and + // set to false each time gc returns to the mutator. For example, in the + // ParallelScavengeHeap case the latter would be done toward the end of + // mem_allocate() where it returns op.result() + bool _all_soft_refs_clear; + CollectorPolicy() : _min_alignment(1), _max_alignment(1), _initial_heap_byte_size(0), _max_heap_byte_size(0), - _min_heap_byte_size(0) + _min_heap_byte_size(0), + _size_policy(NULL), + _should_clear_all_soft_refs(false), + _all_soft_refs_clear(false) {} public: @@ -98,6 +114,19 @@ G1CollectorPolicyKind }; + AdaptiveSizePolicy* size_policy() { return _size_policy; } + bool should_clear_all_soft_refs() { return _should_clear_all_soft_refs; } + void set_should_clear_all_soft_refs(bool v) { _should_clear_all_soft_refs = v; } + // Returns the current value of _should_clear_all_soft_refs. + // _should_clear_all_soft_refs is set to false as a side effect. + bool use_should_clear_all_soft_refs(bool v); + bool all_soft_refs_clear() { return _all_soft_refs_clear; } + void set_all_soft_refs_clear(bool v) { _all_soft_refs_clear = v; } + + // Called by the GC after Soft Refs have been cleared to indicate + // that the request in _should_clear_all_soft_refs has been fulfilled. + void cleared_all_soft_refs(); + // Identification methods. virtual GenCollectorPolicy* as_generation_policy() { return NULL; } virtual TwoGenerationCollectorPolicy* as_two_generation_policy() { return NULL; } @@ -165,6 +194,22 @@ }; +class ClearedAllSoftRefs : public StackObj { + bool _clear_all_soft_refs; + CollectorPolicy* _collector_policy; + public: + ClearedAllSoftRefs(bool clear_all_soft_refs, + CollectorPolicy* collector_policy) : + _clear_all_soft_refs(clear_all_soft_refs), + _collector_policy(collector_policy) {} + + ~ClearedAllSoftRefs() { + if (_clear_all_soft_refs) { + _collector_policy->cleared_all_soft_refs(); + } + } +}; + class GenCollectorPolicy : public CollectorPolicy { protected: size_t _min_gen0_size; @@ -173,10 +218,6 @@ GenerationSpec **_generations; - // The sizing of the different generations in the heap are controlled - // by a sizing policy. - AdaptiveSizePolicy* _size_policy; - // Return true if an allocation should be attempted in the older // generation if it fails in the younger generation. Return // false, otherwise. @@ -236,14 +277,11 @@ virtual size_t large_typearray_limit(); // Adaptive size policy - AdaptiveSizePolicy* size_policy() { return _size_policy; } virtual void initialize_size_policy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size); - }; - // All of hotspot's current collectors are subtypes of this // class. Currently, these collectors all use the same gen[0], // but have different gen[1] types. If we add another subtype diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/memory/defNewGeneration.cpp --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -594,6 +594,10 @@ _tenuring_threshold = age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize); + // A successful scavenge should restart the GC time limit count which is + // for full GC's. + AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy(); + size_policy->reset_gc_overhead_limit_count(); if (PrintGC && !PrintGCDetails) { gch->print_heap_change(gch_prev_used); } diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/memory/genCollectedHeap.cpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -428,7 +428,8 @@ assert(my_thread->is_VM_thread() || my_thread->is_ConcurrentGC_thread(), "incorrect thread type capability"); - assert(Heap_lock->is_locked(), "the requesting thread should have the Heap_lock"); + assert(Heap_lock->is_locked(), + "the requesting thread should have the Heap_lock"); guarantee(!is_gc_active(), "collection is not reentrant"); assert(max_level < n_gens(), "sanity check"); @@ -436,6 +437,11 @@ return; // GC is disabled (e.g. JNI GetXXXCritical operation) } + const bool do_clear_all_soft_refs = clear_all_soft_refs || + collector_policy()->should_clear_all_soft_refs(); + + ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); + const size_t perm_prev_used = perm_gen()->used(); if (PrintHeapAtGC) { @@ -560,11 +566,11 @@ if (rp->discovery_is_atomic()) { rp->verify_no_references_recorded(); rp->enable_discovery(); - rp->setup_policy(clear_all_soft_refs); + rp->setup_policy(do_clear_all_soft_refs); } else { // collect() below will enable discovery as appropriate } - _gens[i]->collect(full, clear_all_soft_refs, size, is_tlab); + _gens[i]->collect(full, do_clear_all_soft_refs, size, is_tlab); if (!rp->enqueuing_is_done()) { rp->enqueue_discovered_references(); } else { diff -r 431efce7a0af -r 95a5c4b89273 hotspot/src/share/vm/memory/genMarkSweep.cpp --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Fri Apr 09 13:08:34 2010 -0400 +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Tue Apr 13 13:52:10 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,13 @@ bool clear_all_softrefs) { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); + GenCollectedHeap* gch = GenCollectedHeap::heap(); +#ifdef ASSERT + if (gch->collector_policy()->should_clear_all_soft_refs()) { + assert(clear_all_softrefs, "Policy should have been checked earlier"); + } +#endif + // hook up weak ref data so it can be used during Mark-Sweep assert(ref_processor() == NULL, "no stomping"); assert(rp != NULL, "should be non-NULL"); @@ -44,7 +51,6 @@ // Increment the invocation count for the permanent generation, since it is // implicitly collected whenever we do a full mark sweep collection. - GenCollectedHeap* gch = GenCollectedHeap::heap(); gch->perm_gen()->stat_record()->invocations++; // Capture heap size before collection for printing.