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
--- 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();
--- 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
--- 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
--- 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
--- 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;
--- 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
--- 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
--- 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,
--- 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();
}
--- 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; }
--- 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);
}
--- 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.
--- 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();
}
}
--- 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);
--- 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) {
--- 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) {
--- 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
--- 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 {
--- 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
--- 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();
--- 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;
--- 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
--- 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
--- 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);
}
--- 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 {
--- 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.