diff src/share/vm/memory/space.hpp @ 356:1ee8caae33af

Merge
author tonyp
date Thu, 21 Aug 2008 23:36:31 -0400
parents 60fb9c4db4e6 850fdf70db2b
children 122d10c82f3f
line wrap: on
line diff
--- a/src/share/vm/memory/space.hpp	Wed Aug 06 11:57:31 2008 -0400
+++ b/src/share/vm/memory/space.hpp	Thu Aug 21 23:36:31 2008 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 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
@@ -136,20 +136,18 @@
   // any purpose.  The "mr" arguments gives the bounds of the space, and
   // the "clear_space" argument should be true unless the memory in "mr" is
   // known to be zeroed.
-  virtual void initialize(MemRegion mr, bool clear_space);
-
-  // Sets the bounds (bottom and end) of the current space to those of "mr."
-  void set_bounds(MemRegion mr);
+  virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space);
 
   // The "clear" method must be called on a region that may have
   // had allocation performed in it, but is now to be considered empty.
-  virtual void clear();
+  virtual void clear(bool mangle_space);
 
   // For detecting GC bugs.  Should only be called at GC boundaries, since
   // some unused space may be used as scratch space during GC's.
   // Default implementation does nothing. We also call this when expanding
   // a space to satisfy an allocation request. See bug #4668531
   virtual void mangle_unused_area() {}
+  virtual void mangle_unused_area_complete() {}
   virtual void mangle_region(MemRegion mr) {}
 
   // Testers
@@ -376,8 +374,8 @@
   CompactibleSpace() :
    _compaction_top(NULL), _next_compaction_space(NULL) {}
 
-  virtual void initialize(MemRegion mr, bool clear_space);
-  virtual void clear();
+  virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space);
+  virtual void clear(bool mangle_space);
 
   // Used temporarily during a compaction phase to hold the value
   // top should have when compaction is complete.
@@ -661,100 +659,102 @@
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));     \
       debug_only(prev_q = q);                                                   \
       q += size;                                                                \
-    } else {                                                                        \
-      /* q is not a live object, so its mark should point at the next                \
-       * live object */                                                                \
-      debug_only(prev_q = q);                                                        \
-      q = (HeapWord*) oop(q)->mark()->decode_pointer();                                \
-      assert(q > prev_q, "we should be moving forward through memory");                \
-    }                                                                                \
-  }                                                                                \
+    } else {                                                                    \
+      /* q is not a live object, so its mark should point at the next           \
+       * live object */                                                         \
+      debug_only(prev_q = q);                                                   \
+      q = (HeapWord*) oop(q)->mark()->decode_pointer();                         \
+      assert(q > prev_q, "we should be moving forward through memory");         \
+    }                                                                           \
+  }                                                                             \
                                                                                 \
-  assert(q == t, "just checking");                                                \
+  assert(q == t, "just checking");                                              \
 }
 
-#define SCAN_AND_COMPACT(obj_size) {                                                \
+#define SCAN_AND_COMPACT(obj_size) {                                            \
   /* Copy all live objects to their new location                                \
-   * Used by MarkSweep::mark_sweep_phase4() */                                        \
+   * Used by MarkSweep::mark_sweep_phase4() */                                  \
                                                                                 \
-  HeapWord*       q = bottom();                                                        \
-  HeapWord* const t = _end_of_live;                                                \
-  debug_only(HeapWord* prev_q = NULL);                                                \
+  HeapWord*       q = bottom();                                                 \
+  HeapWord* const t = _end_of_live;                                             \
+  debug_only(HeapWord* prev_q = NULL);                                          \
                                                                                 \
-  if (q < t && _first_dead > q &&                                                \
+  if (q < t && _first_dead > q &&                                               \
       !oop(q)->is_gc_marked()) {                                                \
-    debug_only(                                                                        \
+    debug_only(                                                                 \
     /* we have a chunk of the space which hasn't moved and we've reinitialized  \
      * the mark word during the previous pass, so we can't use is_gc_marked for \
      * the traversal. */                                                        \
-    HeapWord* const end = _first_dead;                                                \
-                                                                                      \
-    while (q < end) {                                                                \
+    HeapWord* const end = _first_dead;                                          \
+                                                                                \
+    while (q < end) {                                                           \
       size_t size = obj_size(q);                                                \
       assert(!oop(q)->is_gc_marked(),                                           \
              "should be unmarked (special dense prefix handling)");             \
-      VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q));        \
-      debug_only(prev_q = q);                                                        \
+      VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q));       \
+      debug_only(prev_q = q);                                                   \
       q += size;                                                                \
-    }                                                                                \
-    )  /* debug_only */                                                                \
-                                                                                      \
-    if (_first_dead == t) {                                                        \
-      q = t;                                                                        \
-    } else {                                                                        \
-      /* $$$ Funky */                                                                 \
-      q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer();                \
-    }                                                                                \
-  }                                                                                \
+    }                                                                           \
+    )  /* debug_only */                                                         \
+                                                                                \
+    if (_first_dead == t) {                                                     \
+      q = t;                                                                    \
+    } else {                                                                    \
+      /* $$$ Funky */                                                           \
+      q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer();               \
+    }                                                                           \
+  }                                                                             \
                                                                                 \
-  const intx scan_interval = PrefetchScanIntervalInBytes;                        \
-  const intx copy_interval = PrefetchCopyIntervalInBytes;                        \
-  while (q < t) {                                                                \
-    if (!oop(q)->is_gc_marked()) {                                                \
-      /* mark is pointer to next marked oop */                                        \
-      debug_only(prev_q = q);                                                        \
-      q = (HeapWord*) oop(q)->mark()->decode_pointer();                                \
-      assert(q > prev_q, "we should be moving forward through memory");                \
-    } else {                                                                        \
-      /* prefetch beyond q */                                                        \
+  const intx scan_interval = PrefetchScanIntervalInBytes;                       \
+  const intx copy_interval = PrefetchCopyIntervalInBytes;                       \
+  while (q < t) {                                                               \
+    if (!oop(q)->is_gc_marked()) {                                              \
+      /* mark is pointer to next marked oop */                                  \
+      debug_only(prev_q = q);                                                   \
+      q = (HeapWord*) oop(q)->mark()->decode_pointer();                         \
+      assert(q > prev_q, "we should be moving forward through memory");         \
+    } else {                                                                    \
+      /* prefetch beyond q */                                                   \
       Prefetch::read(q, scan_interval);                                         \
                                                                                 \
       /* size and destination */                                                \
       size_t size = obj_size(q);                                                \
       HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee();                \
                                                                                 \
-      /* prefetch beyond compaction_top */                                        \
+      /* prefetch beyond compaction_top */                                      \
       Prefetch::write(compaction_top, copy_interval);                           \
                                                                                 \
-      /* copy object and reinit its mark */                                        \
+      /* copy object and reinit its mark */                                     \
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size,            \
                                                             compaction_top));   \
-      assert(q != compaction_top, "everything in this pass should be moving");        \
-      Copy::aligned_conjoint_words(q, compaction_top, size);                        \
-      oop(compaction_top)->init_mark();                                                \
-      assert(oop(compaction_top)->klass() != NULL, "should have a class");        \
+      assert(q != compaction_top, "everything in this pass should be moving");  \
+      Copy::aligned_conjoint_words(q, compaction_top, size);                    \
+      oop(compaction_top)->init_mark();                                         \
+      assert(oop(compaction_top)->klass() != NULL, "should have a class");      \
                                                                                 \
-      debug_only(prev_q = q);                                                        \
+      debug_only(prev_q = q);                                                   \
       q += size;                                                                \
-    }                                                                                \
-  }                                                                                \
+    }                                                                           \
+  }                                                                             \
                                                                                 \
   /* Let's remember if we were empty before we did the compaction. */           \
   bool was_empty = used_region().is_empty();                                    \
   /* Reset space after compaction is complete */                                \
-  reset_after_compaction();                                                        \
+  reset_after_compaction();                                                     \
   /* We do this clear, below, since it has overloaded meanings for some */      \
   /* space subtypes.  For example, OffsetTableContigSpace's that were   */      \
   /* compacted into will have had their offset table thresholds updated */      \
   /* continuously, but those that weren't need to have their thresholds */      \
   /* re-initialized.  Also mangles unused area for debugging.           */      \
   if (used_region().is_empty()) {                                               \
-    if (!was_empty) clear();                                                    \
+    if (!was_empty) clear(SpaceDecorator::Mangle);                              \
   } else {                                                                      \
     if (ZapUnusedHeapArea) mangle_unused_area();                                \
   }                                                                             \
 }
 
+class GenSpaceMangler;
+
 // A space in which the free area is contiguous.  It therefore supports
 // faster allocation, and compaction.
 class ContiguousSpace: public CompactibleSpace {
@@ -763,17 +763,21 @@
  protected:
   HeapWord* _top;
   HeapWord* _concurrent_iteration_safe_limit;
+  // A helper for mangling the unused area of the space in debug builds.
+  GenSpaceMangler* _mangler;
+
+  GenSpaceMangler* mangler() { return _mangler; }
 
   // Allocation helpers (return NULL if full).
   inline HeapWord* allocate_impl(size_t word_size, HeapWord* end_value);
   inline HeapWord* par_allocate_impl(size_t word_size, HeapWord* end_value);
 
  public:
-  ContiguousSpace() :
-    _top(NULL),
-    _concurrent_iteration_safe_limit(NULL) {}
+  ContiguousSpace();
+  ~ContiguousSpace();
 
-  virtual void initialize(MemRegion mr, bool clear_space);
+  virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space);
+  virtual void clear(bool mangle_space);
 
   // Accessors
   HeapWord* top() const            { return _top;    }
@@ -782,15 +786,32 @@
   virtual void set_saved_mark()    { _saved_mark_word = top();    }
   void reset_saved_mark()          { _saved_mark_word = bottom(); }
 
-  virtual void clear();
-
   WaterMark bottom_mark()     { return WaterMark(this, bottom()); }
   WaterMark top_mark()        { return WaterMark(this, top()); }
   WaterMark saved_mark()      { return WaterMark(this, saved_mark_word()); }
   bool saved_mark_at_top() const { return saved_mark_word() == top(); }
 
-  void mangle_unused_area();
-  void mangle_region(MemRegion mr);
+  // In debug mode mangle (write it with a particular bit
+  // pattern) the unused part of a space.
+
+  // Used to save the an address in a space for later use during mangling.
+  void set_top_for_allocations(HeapWord* v) PRODUCT_RETURN;
+  // Used to save the space's current top for later use during mangling.
+  void set_top_for_allocations() PRODUCT_RETURN;
+
+  // Mangle regions in the space from the current top up to the
+  // previously mangled part of the space.
+  void mangle_unused_area() PRODUCT_RETURN;
+  // Mangle [top, end)
+  void mangle_unused_area_complete() PRODUCT_RETURN;
+  // Mangle the given MemRegion.
+  void mangle_region(MemRegion mr) PRODUCT_RETURN;
+
+  // Do some sparse checking on the area that should have been mangled.
+  void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN;
+  // Check the complete area that should have been mangled.
+  // This code may be NULL depending on the macro DEBUG_MANGLING.
+  void check_mangled_unused_area_complete() PRODUCT_RETURN;
 
   // Size computations: sizes in bytes.
   size_t capacity() const        { return byte_size(bottom(), end()); }
@@ -986,7 +1007,7 @@
   void set_soft_end(HeapWord* value) { _soft_end = value; }
 
   // Override.
-  void clear();
+  void clear(bool mangle_space);
 
   // Set both the 'hard' and 'soft' limits (_end and _soft_end).
   void set_end(HeapWord* value) {
@@ -1030,8 +1051,7 @@
   void set_bottom(HeapWord* value);
   void set_end(HeapWord* value);
 
-  virtual void initialize(MemRegion mr, bool clear_space);
-  void clear();
+  void clear(bool mangle_space);
 
   inline HeapWord* block_start_const(const void* p) const;