diff src/share/vm/memory/space.hpp @ 342:37f87013dfd8

6711316: Open source the Garbage-First garbage collector Summary: First mercurial integration of the code for the Garbage-First garbage collector. Reviewed-by: apetrusenko, iveresov, jmasa, sgoldman, tonyp, ysr
author ysr
date Thu, 05 Jun 2008 15:57:56 -0700
parents ba764ed4b6f2
children 60fb9c4db4e6
line wrap: on
line diff
--- a/src/share/vm/memory/space.hpp	Wed Jun 04 13:51:09 2008 -0700
+++ b/src/share/vm/memory/space.hpp	Thu Jun 05 15:57:56 2008 -0700
@@ -105,7 +105,7 @@
   virtual void set_bottom(HeapWord* value) { _bottom = value; }
   virtual void set_end(HeapWord* value)    { _end = value; }
 
-  HeapWord* saved_mark_word() const  { return _saved_mark_word; }
+  virtual HeapWord* saved_mark_word() const  { return _saved_mark_word; }
   void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; }
 
   MemRegionClosure* preconsumptionDirtyCardClosure() const {
@@ -131,8 +131,18 @@
     return MemRegion(bottom(), saved_mark_word());
   }
 
-  // Initialization
+  // Initialization.
+  // "initialize" should be called once on a space, before it is used for
+  // 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);
+
+  // 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();
 
   // For detecting GC bugs.  Should only be called at GC boundaries, since
@@ -216,7 +226,13 @@
   // "block" that contains "p".  We say "block" instead of "object" since
   // some heaps may not pack objects densely; a chunk may either be an
   // object or a non-object.  If "p" is not in the space, return NULL.
-  virtual HeapWord* block_start(const void* p) const = 0;
+  virtual HeapWord* block_start_const(const void* p) const = 0;
+
+  // The non-const version may have benevolent side effects on the data
+  // structure supporting these calls, possibly speeding up future calls.
+  // The default implementation, however, is simply to call the const
+  // version.
+  inline virtual HeapWord* block_start(const void* p);
 
   // Requires "addr" to be the start of a chunk, and returns its size.
   // "addr + size" is required to be the start of a new chunk, or the end
@@ -282,12 +298,13 @@
   CardTableModRefBS::PrecisionStyle _precision;
   HeapWord* _boundary;          // If non-NULL, process only non-NULL oops
                                 // pointing below boundary.
-  HeapWord* _min_done;                // ObjHeadPreciseArray precision requires
+  HeapWord* _min_done;          // ObjHeadPreciseArray precision requires
                                 // a downwards traversal; this is the
                                 // lowest location already done (or,
                                 // alternatively, the lowest address that
                                 // shouldn't be done again.  NULL means infinity.)
   NOT_PRODUCT(HeapWord* _last_bottom;)
+  NOT_PRODUCT(HeapWord* _last_explicit_min_done;)
 
   // Get the actual top of the area on which the closure will
   // operate, given where the top is assumed to be (the end of the
@@ -311,13 +328,15 @@
                         HeapWord* boundary) :
     _sp(sp), _cl(cl), _precision(precision), _boundary(boundary),
     _min_done(NULL) {
-    NOT_PRODUCT(_last_bottom = NULL;)
+    NOT_PRODUCT(_last_bottom = NULL);
+    NOT_PRODUCT(_last_explicit_min_done = NULL);
   }
 
   void do_MemRegion(MemRegion mr);
 
   void set_min_done(HeapWord* min_done) {
     _min_done = min_done;
+    NOT_PRODUCT(_last_explicit_min_done = _min_done);
   }
 #ifndef PRODUCT
   void set_last_bottom(HeapWord* last_bottom) {
@@ -355,6 +374,7 @@
 
 public:
   virtual void initialize(MemRegion mr, bool clear_space);
+  virtual void clear();
 
   // Used temporarily during a compaction phase to hold the value
   // top should have when compaction is complete.
@@ -511,7 +531,7 @@
       /* prefetch beyond q */                                                \
       Prefetch::write(q, interval);                                          \
       /* size_t size = oop(q)->size();  changing this for cms for perm gen */\
-      size_t size = block_size(q);                                             \
+      size_t size = block_size(q);                                           \
       compact_top = cp->space->forward(oop(q), size, cp, compact_top);       \
       q += size;                                                             \
       end_of_live = q;                                                       \
@@ -575,68 +595,68 @@
   cp->space->set_compaction_top(compact_top);                                \
 }
 
-#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) {                                \
-  /* adjust all the interior pointers to point at the new locations of objects        \
-   * Used by MarkSweep::mark_sweep_phase3() */                                        \
+#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) {                             \
+  /* adjust all the interior pointers to point at the new locations of objects  \
+   * Used by MarkSweep::mark_sweep_phase3() */                                  \
                                                                                 \
-  HeapWord* q = bottom();                                                        \
-  HeapWord* t = _end_of_live;  /* Established by "prepare_for_compaction". */        \
+  HeapWord* q = bottom();                                                       \
+  HeapWord* t = _end_of_live;  /* Established by "prepare_for_compaction". */   \
                                                                                 \
-  assert(_first_dead <= _end_of_live, "Stands to reason, no?");                        \
+  assert(_first_dead <= _end_of_live, "Stands to reason, no?");                 \
                                                                                 \
-  if (q < t && _first_dead > q &&                                                \
+  if (q < t && _first_dead > q &&                                               \
       !oop(q)->is_gc_marked()) {                                                \
     /* 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. */                                        \
+     * use is_gc_marked for the traversal. */                                   \
     HeapWord* end = _first_dead;                                                \
                                                                                 \
-    while (q < end) {                                                                \
-      /* I originally tried to conjoin "block_start(q) == q" to the                \
-       * assertion below, but that doesn't work, because you can't                \
-       * accurately traverse previous objects to get to the current one                \
-       * after their pointers (including pointers into permGen) have been        \
-       * updated, until the actual compaction is done.  dld, 4/00 */                \
-      assert(block_is_obj(q),                                                        \
-             "should be at block boundaries, and should be looking at objs");        \
+    while (q < end) {                                                           \
+      /* I originally tried to conjoin "block_start(q) == q" to the             \
+       * assertion below, but that doesn't work, because you can't              \
+       * accurately traverse previous objects to get to the current one         \
+       * after their pointers (including pointers into permGen) have been       \
+       * updated, until the actual compaction is done.  dld, 4/00 */            \
+      assert(block_is_obj(q),                                                   \
+             "should be at block boundaries, and should be looking at objs");   \
                                                                                 \
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));     \
                                                                                 \
-      /* point all the oops to the new location */                                \
-      size_t size = oop(q)->adjust_pointers();                                        \
-      size = adjust_obj_size(size);                                                \
+      /* point all the oops to the new location */                              \
+      size_t size = oop(q)->adjust_pointers();                                  \
+      size = adjust_obj_size(size);                                             \
                                                                                 \
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());           \
-                                                                                      \
+                                                                                \
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));     \
-                                                                                      \
+                                                                                \
       q += size;                                                                \
-    }                                                                                \
+    }                                                                           \
                                                                                 \
-    if (_first_dead == t) {                                                        \
-      q = t;                                                                        \
-    } else {                                                                        \
-      /* $$$ This is funky.  Using this to read the previously written                \
-       * LiveRange.  See also use below. */                                        \
+    if (_first_dead == t) {                                                     \
+      q = t;                                                                    \
+    } else {                                                                    \
+      /* $$$ This is funky.  Using this to read the previously written          \
+       * LiveRange.  See also use below. */                                     \
       q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer();                \
-    }                                                                                \
-  }                                                                                \
+    }                                                                           \
+  }                                                                             \
                                                                                 \
   const intx interval = PrefetchScanIntervalInBytes;                            \
                                                                                 \
-  debug_only(HeapWord* prev_q = NULL);                                                \
-  while (q < t) {                                                                \
-    /* prefetch beyond q */                                                        \
+  debug_only(HeapWord* prev_q = NULL);                                          \
+  while (q < t) {                                                               \
+    /* prefetch beyond q */                                                     \
     Prefetch::write(q, interval);                                               \
-    if (oop(q)->is_gc_marked()) {                                                \
-      /* q is alive */                                                                \
+    if (oop(q)->is_gc_marked()) {                                               \
+      /* q is alive */                                                          \
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));     \
-      /* point all the oops to the new location */                                \
-      size_t size = oop(q)->adjust_pointers();                                        \
-      size = adjust_obj_size(size);                                                \
-      VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());                \
+      /* point all the oops to the new location */                              \
+      size_t size = oop(q)->adjust_pointers();                                  \
+      size = adjust_obj_size(size);                                             \
+      VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());           \
       VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));     \
-      debug_only(prev_q = q);                                                        \
+      debug_only(prev_q = q);                                                   \
       q += size;                                                                \
     } else {                                                                        \
       /* q is not a live object, so its mark should point at the next                \
@@ -716,6 +736,8 @@
     }                                                                                \
   }                                                                                \
                                                                                 \
+  /* 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();                                                        \
   /* We do this clear, below, since it has overloaded meanings for some */      \
@@ -723,8 +745,8 @@
   /* 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 (is_empty()) {                                                             \
-    clear();                                                                    \
+  if (used_region().is_empty()) {                                               \
+    if (!was_empty) clear();                                                    \
   } else {                                                                      \
     if (ZapUnusedHeapArea) mangle_unused_area();                                \
   }                                                                             \
@@ -750,8 +772,8 @@
   HeapWord* top() const            { return _top;    }
   void set_top(HeapWord* value)    { _top = value; }
 
-  void set_saved_mark()       { _saved_mark_word = top();    }
-  void reset_saved_mark()     { _saved_mark_word = bottom(); }
+  virtual void set_saved_mark()    { _saved_mark_word = top();    }
+  void reset_saved_mark()          { _saved_mark_word = bottom(); }
 
   virtual void clear();
 
@@ -843,7 +865,7 @@
   virtual void object_iterate_from(WaterMark mark, ObjectClosure* blk);
 
   // Very inefficient implementation.
-  virtual HeapWord* block_start(const void* p) const;
+  virtual HeapWord* block_start_const(const void* p) const;
   size_t block_size(const HeapWord* p) const;
   // If a block is in the allocated area, it is an object.
   bool block_is_obj(const HeapWord* p) const { return p < top(); }
@@ -1000,9 +1022,10 @@
   void set_bottom(HeapWord* value);
   void set_end(HeapWord* value);
 
+  virtual void initialize(MemRegion mr, bool clear_space);
   void clear();
 
-  inline HeapWord* block_start(const void* p) const;
+  inline HeapWord* block_start_const(const void* p) const;
 
   // Add offset table update.
   virtual inline HeapWord* allocate(size_t word_size);