hotspot/src/share/vm/memory/defNewGeneration.cpp
changeset 971 f0b20be4165d
parent 360 21d113ecbf6a
child 977 b90650e2a9f7
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp	Fri Jun 27 19:12:11 2008 -0700
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp	Wed Jul 09 15:08:55 2008 -0700
@@ -172,15 +172,25 @@
   _to_counters = new CSpaceCounters("s1", 2, _max_survivor_size, _to_space,
                                     _gen_counters);
 
-  compute_space_boundaries(0);
+  compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle);
   update_counters();
   _next_gen = NULL;
   _tenuring_threshold = MaxTenuringThreshold;
   _pretenure_size_threshold_words = PretenureSizeThreshold >> LogHeapWordSize;
 }
 
-void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size) {
-  uintx alignment = GenCollectedHeap::heap()->collector_policy()->min_alignment();
+void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size,
+                                                bool clear_space,
+                                                bool mangle_space) {
+  uintx alignment =
+    GenCollectedHeap::heap()->collector_policy()->min_alignment();
+
+  // If the spaces are being cleared (only done at heap initialization
+  // currently), the survivor spaces need not be empty.
+  // Otherwise, no care is taken for used areas in the survivor spaces
+  // so check.
+  assert(clear_space || (to()->is_empty() && from()->is_empty()),
+    "Initialization of the survivor spaces assumes these are empty");
 
   // Compute sizes
   uintx size = _virtual_space.committed_size();
@@ -214,16 +224,41 @@
   MemRegion fromMR((HeapWord*)from_start, (HeapWord*)to_start);
   MemRegion toMR  ((HeapWord*)to_start, (HeapWord*)to_end);
 
-  eden()->initialize(edenMR, (minimum_eden_size == 0));
-  // If minumum_eden_size != 0, we will not have cleared any
+  // A minimum eden size implies that there is a part of eden that
+  // is being used and that affects the initialization of any
+  // newly formed eden.
+  bool live_in_eden = minimum_eden_size > 0;
+
+  // If not clearing the spaces, do some checking to verify that
+  // the space are already mangled.
+  if (!clear_space) {
+    // Must check mangling before the spaces are reshaped.  Otherwise,
+    // the bottom or end of one space may have moved into another
+    // a failure of the check may not correctly indicate which space
+    // is not properly mangled.
+    if (ZapUnusedHeapArea) {
+      HeapWord* limit = (HeapWord*) _virtual_space.high();
+      eden()->check_mangled_unused_area(limit);
+      from()->check_mangled_unused_area(limit);
+        to()->check_mangled_unused_area(limit);
+    }
+  }
+
+  // Reset the spaces for their new regions.
+  eden()->initialize(edenMR,
+                     clear_space && !live_in_eden,
+                     SpaceDecorator::Mangle);
+  // If clear_space and live_in_eden, we will not have cleared any
   // portion of eden above its top. This can cause newly
   // expanded space not to be mangled if using ZapUnusedHeapArea.
   // We explicitly do such mangling here.
-  if (ZapUnusedHeapArea && (minimum_eden_size != 0)) {
+  if (ZapUnusedHeapArea && clear_space && live_in_eden && mangle_space) {
     eden()->mangle_unused_area();
   }
-  from()->initialize(fromMR, true);
-    to()->initialize(toMR  , true);
+  from()->initialize(fromMR, clear_space, mangle_space);
+  to()->initialize(toMR, clear_space, mangle_space);
+
+  // Set next compaction spaces.
   eden()->set_next_compaction_space(from());
   // The to-space is normally empty before a compaction so need
   // not be considered.  The exception is during promotion
@@ -250,7 +285,16 @@
 
 bool DefNewGeneration::expand(size_t bytes) {
   MutexLocker x(ExpandHeap_lock);
+  HeapWord* prev_high = (HeapWord*) _virtual_space.high();
   bool success = _virtual_space.expand_by(bytes);
+  if (success && ZapUnusedHeapArea) {
+    // Mangle newly committed space immediately because it
+    // can be done here more simply that after the new
+    // spaces have been computed.
+    HeapWord* new_high = (HeapWord*) _virtual_space.high();
+    MemRegion mangle_region(prev_high, new_high);
+    SpaceMangler::mangle_region(mangle_region);
+  }
 
   // Do not attempt an expand-to-the reserve size.  The
   // request should properly observe the maximum size of
@@ -262,7 +306,8 @@
   // value.
   if (GC_locker::is_active()) {
     if (PrintGC && Verbose) {
-      gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
+      gclog_or_tty->print_cr("Garbage collection disabled, "
+        "expanded heap instead");
     }
   }
 
@@ -326,16 +371,24 @@
     changed = true;
   }
   if (changed) {
-    compute_space_boundaries(eden()->used());
-    MemRegion cmr((HeapWord*)_virtual_space.low(), (HeapWord*)_virtual_space.high());
+    // The spaces have already been mangled at this point but
+    // may not have been cleared (set top = bottom) and should be.
+    // Mangling was done when the heap was being expanded.
+    compute_space_boundaries(eden()->used(),
+                             SpaceDecorator::Clear,
+                             SpaceDecorator::DontMangle);
+    MemRegion cmr((HeapWord*)_virtual_space.low(),
+                  (HeapWord*)_virtual_space.high());
     Universe::heap()->barrier_set()->resize_covered_region(cmr);
     if (Verbose && PrintGC) {
       size_t new_size_after  = _virtual_space.committed_size();
       size_t eden_size_after = eden()->capacity();
       size_t survivor_size_after = from()->capacity();
-      gclog_or_tty->print("New generation size " SIZE_FORMAT "K->" SIZE_FORMAT "K [eden="
+      gclog_or_tty->print("New generation size " SIZE_FORMAT "K->"
+        SIZE_FORMAT "K [eden="
         SIZE_FORMAT "K,survivor=" SIZE_FORMAT "K]",
-        new_size_before/K, new_size_after/K, eden_size_after/K, survivor_size_after/K);
+        new_size_before/K, new_size_after/K,
+        eden_size_after/K, survivor_size_after/K);
       if (WizardMode) {
         gclog_or_tty->print("[allowed " SIZE_FORMAT "K extra for %d threads]",
           thread_increase_size/K, threads_count);
@@ -480,7 +533,7 @@
   ScanWeakRefClosure scan_weak_ref(this);
 
   age_table()->clear();
-  to()->clear();
+  to()->clear(SpaceDecorator::Mangle);
 
   gch->rem_set()->prepare_for_younger_refs_iterate(false);
 
@@ -525,8 +578,18 @@
     soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers, NULL);
   if (!promotion_failed()) {
     // Swap the survivor spaces.
-    eden()->clear();
-    from()->clear();
+    eden()->clear(SpaceDecorator::Mangle);
+    from()->clear(SpaceDecorator::Mangle);
+    if (ZapUnusedHeapArea) {
+      // This is now done here because of the piece-meal mangling which
+      // can check for valid mangling at intermediate points in the
+      // collection(s).  When a minor collection fails to collect
+      // sufficient space resizing of the young generation can occur
+      // an redistribute the spaces in the young generation.  Mangle
+      // here so that unzapped regions don't get distributed to
+      // other spaces.
+      to()->mangle_unused_area();
+    }
     swap_spaces();
 
     assert(to()->is_empty(), "to space should be empty now");
@@ -753,6 +816,15 @@
   }
 }
 
+void DefNewGeneration::reset_scratch() {
+  // If contributing scratch in to_space, mangle all of
+  // to_space if ZapUnusedHeapArea.  This is needed because
+  // top is not maintained while using to-space as scratch.
+  if (ZapUnusedHeapArea) {
+    to()->mangle_unused_area_complete();
+  }
+}
+
 bool DefNewGeneration::collection_attempt_is_safe() {
   if (!to()->is_empty()) {
     return false;
@@ -806,11 +878,25 @@
     }
   }
 
+  if (ZapUnusedHeapArea) {
+    eden()->check_mangled_unused_area_complete();
+    from()->check_mangled_unused_area_complete();
+    to()->check_mangled_unused_area_complete();
+  }
+
   // update the generation and space performance counters
   update_counters();
   gch->collector_policy()->counters()->update_counters();
 }
 
+void DefNewGeneration::record_spaces_top() {
+  assert(ZapUnusedHeapArea, "Not mangling unused space");
+  eden()->set_top_for_allocations();
+  to()->set_top_for_allocations();
+  from()->set_top_for_allocations();
+}
+
+
 void DefNewGeneration::update_counters() {
   if (UsePerfData) {
     _eden_counters->update_all();