changeset 1685:0bfd3fb24150

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
author jmasa
date Tue, 13 Apr 2010 13:52:10 -0700
parents 6b73e879f1c2
children 7666957bc44d
files src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp src/share/vm/gc_implementation/g1/g1MarkSweep.cpp src/share/vm/gc_implementation/includeDB_gc_parallelScavenge src/share/vm/gc_implementation/includeDB_gc_serial src/share/vm/gc_implementation/parNew/parNewGeneration.cpp src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp src/share/vm/gc_implementation/shared/vmGCOperations.hpp src/share/vm/gc_interface/collectedHeap.hpp src/share/vm/memory/collectorPolicy.cpp src/share/vm/memory/collectorPolicy.hpp src/share/vm/memory/defNewGeneration.cpp src/share/vm/memory/genCollectedHeap.cpp src/share/vm/memory/genMarkSweep.cpp
diffstat 26 files changed, 544 insertions(+), 365 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/includeDB_gc_serial	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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();
+  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);
+    GCCauseSetter gccs(heap, GCCause::_adaptive_size_policy);
+    CollectorPolicy* cp = heap->collector_policy();
+    const bool clear_all_softrefs = cp->should_clear_all_soft_refs();
 
-    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(full_follows_scavenge);
-
-      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/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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;
+  bool gc_overhead_limit_exceeded() {
+    return _gc_overhead_limit_exceeded;
   }
-  void set_gc_time_limit_exceeded(bool v) {
-    _gc_time_limit_exceeded = v;
-  }
-  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/src/share/vm/gc_implementation/shared/vmGCOperations.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/gc_interface/collectedHeap.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/memory/collectorPolicy.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/memory/collectorPolicy.hpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/memory/defNewGeneration.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/memory/genCollectedHeap.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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/src/share/vm/memory/genMarkSweep.cpp	Fri Apr 09 13:08:34 2010 -0400
+++ b/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.