8130931: Refactor CardTableModRefBS[ForCTRS]
authorkbarrett
Wed, 22 Jul 2015 00:37:01 -0400
changeset 31964 d34ad1715d96
parent 31856 614d6786ba55
child 31965 1f50deed8864
8130931: Refactor CardTableModRefBS[ForCTRS] Summary: Remove friends and push CTRS-specific code down from base to derived Reviewed-by: tschatzl, mgerdin
hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp
hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp
hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp
hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp
hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp
hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp
hotspot/src/share/vm/gc/shared/cardTableRS.cpp
hotspot/src/share/vm/gc/shared/cardTableRS.hpp
hotspot/src/share/vm/shark/sharkBuilder.cpp
hotspot/src/share/vm/shark/sharkBuilder.hpp
--- a/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/parCardTableModRefBS.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -36,10 +36,11 @@
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
 
-void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
-                                                             OopsInGenClosure* cl,
-                                                             CardTableRS* ct,
-                                                             uint n_threads) {
+void CardTableModRefBSForCTRS::
+non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                     OopsInGenClosure* cl,
+                                     CardTableRS* ct,
+                                     uint n_threads) {
   assert(n_threads > 0, "expected n_threads > 0");
   assert(n_threads <= ParallelGCThreads,
          err_msg("n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads));
@@ -81,7 +82,7 @@
 }
 
 void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
 process_stride(Space* sp,
                MemRegion used,
                jint stride, int n_strides,
@@ -170,7 +171,7 @@
 #endif
 
 void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
 process_chunk_boundaries(Space* sp,
                          DirtyCardToOopClosure* dcto_cl,
                          MemRegion chunk_mr,
@@ -426,7 +427,7 @@
 #undef NOISY
 
 void
-CardTableModRefBS::
+CardTableModRefBSForCTRS::
 get_LNC_array_for_space(Space* sp,
                         jbyte**& lowest_non_clean,
                         uintptr_t& lowest_non_clean_base_chunk_index,
--- a/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/cardTableExtension.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -40,7 +40,6 @@
   PSYoungGen*         _young_gen;
   CardTableExtension* _card_table;
   HeapWord*           _unmarked_addr;
-  jbyte*              _unmarked_card;
 
  protected:
   template <class T> void do_oop_work(T* p) {
@@ -50,7 +49,6 @@
       // Don't overwrite the first missing card mark
       if (_unmarked_addr == NULL) {
         _unmarked_addr = (HeapWord*)p;
-        _unmarked_card = _card_table->byte_for(p);
       }
     }
   }
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -623,7 +623,7 @@
   {
     // DefNew needs to run with n_threads == 0, to make sure the serial
     // version of the card table scanning code is used.
-    // See: CardTableModRefBS::non_clean_card_iterate_possibly_parallel.
+    // See: CardTableModRefBSForCTRS::non_clean_card_iterate_possibly_parallel.
     StrongRootsScope srs(0);
 
     gch->gen_process_roots(&srs,
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -24,22 +24,12 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/cardTableModRefBS.inline.hpp"
-#include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/space.hpp"
 #include "gc/shared/space.inline.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/universe.hpp"
 #include "memory/virtualspace.hpp"
-#include "runtime/java.hpp"
-#include "runtime/mutexLocker.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/macros.hpp"
-#ifdef COMPILER1
-#include "c1/c1_LIR.hpp"
-#include "c1/c1_LIRGenerator.hpp"
-#endif
 
 // This kind of "BarrierSet" allows a "CollectedHeap" to detect and
 // enumerate ref fields that have been modified (since the last
@@ -68,12 +58,7 @@
   _committed(NULL),
   _cur_covered_regions(0),
   _byte_map(NULL),
-  byte_map_base(NULL),
-  // LNC functionality
-  _lowest_non_clean(NULL),
-  _lowest_non_clean_chunk_size(NULL),
-  _lowest_non_clean_base_chunk_index(NULL),
-  _last_LNC_resizing_collection(NULL)
+  byte_map_base(NULL)
 {
   assert((uintptr_t(_whole_heap.start())  & (card_size - 1))  == 0, "heap must start at card boundary");
   assert((uintptr_t(_whole_heap.end()) & (card_size - 1))  == 0, "heap must end at card boundary");
@@ -130,25 +115,6 @@
                             !ExecMem, "card table last card");
   *guard_card = last_card;
 
-  _lowest_non_clean =
-    NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
-  _lowest_non_clean_chunk_size =
-    NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
-  _lowest_non_clean_base_chunk_index =
-    NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
-  _last_LNC_resizing_collection =
-    NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
-  if (_lowest_non_clean == NULL
-      || _lowest_non_clean_chunk_size == NULL
-      || _lowest_non_clean_base_chunk_index == NULL
-      || _last_LNC_resizing_collection == NULL)
-    vm_exit_during_initialization("couldn't allocate an LNC array.");
-  for (int i = 0; i < _max_covered_regions; i++) {
-    _lowest_non_clean[i] = NULL;
-    _lowest_non_clean_chunk_size[i] = 0;
-    _last_LNC_resizing_collection[i] = -1;
-  }
-
   if (TraceCardTableModRefBS) {
     gclog_or_tty->print_cr("CardTableModRefBS::CardTableModRefBS: ");
     gclog_or_tty->print_cr("  "
@@ -171,22 +137,6 @@
     delete[] _committed;
     _committed = NULL;
   }
-  if (_lowest_non_clean) {
-    FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
-    _lowest_non_clean = NULL;
-  }
-  if (_lowest_non_clean_chunk_size) {
-    FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
-    _lowest_non_clean_chunk_size = NULL;
-  }
-  if (_lowest_non_clean_base_chunk_index) {
-    FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
-    _lowest_non_clean_base_chunk_index = NULL;
-  }
-  if (_last_LNC_resizing_collection) {
-    FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
-    _last_LNC_resizing_collection = NULL;
-  }
 }
 
 int CardTableModRefBS::find_covering_region_by_base(HeapWord* base) {
@@ -437,32 +387,6 @@
 }
 
 
-void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp,
-                                                                 MemRegion mr,
-                                                                 OopsInGenClosure* cl,
-                                                                 CardTableRS* ct,
-                                                                 uint n_threads) {
-  if (!mr.is_empty()) {
-    if (n_threads > 0) {
-#if INCLUDE_ALL_GCS
-      non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
-#else  // INCLUDE_ALL_GCS
-      fatal("Parallel gc not supported here.");
-#endif // INCLUDE_ALL_GCS
-    } else {
-      // clear_cl finds contiguous dirty ranges of cards to process and clear.
-
-      // This is the single-threaded version used by DefNew.
-      const bool parallel = false;
-
-      DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
-      ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
-
-      clear_cl.do_MemRegion(mr);
-    }
-  }
-}
-
 void CardTableModRefBS::dirty_MemRegion(MemRegion mr) {
   assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start(), "Unaligned start");
   assert((HeapWord*)align_size_up  ((uintptr_t)mr.end(),   HeapWordSize) == mr.end(),   "Unaligned end"  );
@@ -623,15 +547,3 @@
                p2i(_byte_map), p2i(_byte_map + _byte_map_size), p2i(byte_map_base));
 }
 
-bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
-  return
-    CardTableModRefBS::card_will_be_scanned(cv) ||
-    _rs->is_prev_nonclean_card_val(cv);
-};
-
-bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) {
-  return
-    cv != clean_card &&
-    (CardTableModRefBS::card_may_have_been_dirty(cv) ||
-     CardTableRS::youngergen_may_have_been_dirty(cv));
-};
--- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp	Wed Jul 22 00:37:01 2015 -0400
@@ -40,23 +40,9 @@
 // Closures used to scan dirty cards should take these
 // considerations into account.
 
-class Generation;
-class OopsInGenClosure;
-class DirtyCardToOopClosure;
-class ClearNoncleanCardWrapper;
-class CardTableRS;
-
 class CardTableModRefBS: public ModRefBarrierSet {
   // Some classes get to look at some private stuff.
-  friend class BytecodeInterpreter;
   friend class VMStructs;
-  friend class CardTableRS;
-  friend class CheckForUnmarkedOops; // Needs access to raw card bytes.
-  friend class SharkBuilder;
-#ifndef PRODUCT
-  // For debugging.
-  friend class GuaranteeNotModClosure;
-#endif
  protected:
 
   enum CardValues {
@@ -75,24 +61,6 @@
   // a word's worth (row) of clean card values
   static const intptr_t clean_card_row = (intptr_t)(-1);
 
-  // dirty and precleaned are equivalent wrt younger_refs_iter.
-  static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
-    return cv == dirty_card || cv == precleaned_card;
-  }
-
-  // Returns "true" iff the value "cv" will cause the card containing it
-  // to be scanned in the current traversal.  May be overridden by
-  // subtypes.
-  virtual bool card_will_be_scanned(jbyte cv) {
-    return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
-  }
-
-  // Returns "true" iff the value "cv" may have represented a dirty card at
-  // some point.
-  virtual bool card_may_have_been_dirty(jbyte cv) {
-    return card_is_dirty_wrt_gen_iter(cv);
-  }
-
   // The declaration order of these const fields is important; see the
   // constructor before changing.
   const MemRegion _whole_heap;       // the region covered by the card table
@@ -174,20 +142,6 @@
     return byte_for(p) + 1;
   }
 
-  // Iterate over the portion of the card-table which covers the given
-  // region mr in the given space and apply cl to any dirty sub-regions
-  // of mr. Clears the dirty cards as they are processed.
-  void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
-                                                OopsInGenClosure* cl, CardTableRS* ct,
-                                                uint n_threads);
-
- private:
-  // Work method used to implement non_clean_card_iterate_possibly_parallel()
-  // above in the parallel case.
-  void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
-                                            OopsInGenClosure* cl, CardTableRS* ct,
-                                            uint n_threads);
-
  protected:
   // Dirty the bytes corresponding to "mr" (not all of which must be
   // covered.)
@@ -197,65 +151,6 @@
   // all of which must be covered.)
   void clear_MemRegion(MemRegion mr);
 
-  // *** Support for parallel card scanning.
-
-  // This is an array, one element per covered region of the card table.
-  // Each entry is itself an array, with one element per chunk in the
-  // covered region.  Each entry of these arrays is the lowest non-clean
-  // card of the corresponding chunk containing part of an object from the
-  // previous chunk, or else NULL.
-  typedef jbyte*  CardPtr;
-  typedef CardPtr* CardArr;
-  CardArr* _lowest_non_clean;
-  size_t*  _lowest_non_clean_chunk_size;
-  uintptr_t* _lowest_non_clean_base_chunk_index;
-  int* _last_LNC_resizing_collection;
-
-  // Initializes "lowest_non_clean" to point to the array for the region
-  // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
-  // index of the corresponding to the first element of that array.
-  // Ensures that these arrays are of sufficient size, allocating if necessary.
-  // May be called by several threads concurrently.
-  void get_LNC_array_for_space(Space* sp,
-                               jbyte**& lowest_non_clean,
-                               uintptr_t& lowest_non_clean_base_chunk_index,
-                               size_t& lowest_non_clean_chunk_size);
-
-  // Returns the number of chunks necessary to cover "mr".
-  size_t chunks_to_cover(MemRegion mr) {
-    return (size_t)(addr_to_chunk_index(mr.last()) -
-                    addr_to_chunk_index(mr.start()) + 1);
-  }
-
-  // Returns the index of the chunk in a stride which
-  // covers the given address.
-  uintptr_t addr_to_chunk_index(const void* addr) {
-    uintptr_t card = (uintptr_t) byte_for(addr);
-    return card / ParGCCardsPerStrideChunk;
-  }
-
-  // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
-  // to the cards in the stride (of n_strides) within the given space.
-  void process_stride(Space* sp,
-                      MemRegion used,
-                      jint stride, int n_strides,
-                      OopsInGenClosure* cl,
-                      CardTableRS* ct,
-                      jbyte** lowest_non_clean,
-                      uintptr_t lowest_non_clean_base_chunk_index,
-                      size_t lowest_non_clean_chunk_size);
-
-  // Makes sure that chunk boundaries are handled appropriately, by
-  // adjusting the min_done of dcto_cl, and by using a special card-table
-  // value to indicate how min_done should be set.
-  void process_chunk_boundaries(Space* sp,
-                                DirtyCardToOopClosure* dcto_cl,
-                                MemRegion chunk_mr,
-                                MemRegion used,
-                                jbyte** lowest_non_clean,
-                                uintptr_t lowest_non_clean_base_chunk_index,
-                                size_t    lowest_non_clean_chunk_size);
-
 public:
   // Constants
   enum SomePublicConstants {
@@ -436,34 +331,5 @@
   static const BarrierSet::Name value = BarrierSet::CardTableModRef;
 };
 
-class CardTableRS;
-
-// A specialization for the CardTableRS gen rem set.
-class CardTableModRefBSForCTRS: public CardTableModRefBS {
-  CardTableRS* _rs;
-protected:
-  bool card_will_be_scanned(jbyte cv);
-  bool card_may_have_been_dirty(jbyte cv);
-public:
-  CardTableModRefBSForCTRS(MemRegion whole_heap) :
-    CardTableModRefBS(
-      whole_heap,
-      // Concrete tag should be BarrierSet::CardTableForRS.
-      // That will presently break things in a bunch of places though.
-      // The concrete tag is used as a dispatch key in many places, and
-      // CardTableForRS does not correctly dispatch in some of those
-      // uses. This will be addressed as part of a reorganization of the
-      // BarrierSet hierarchy.
-      BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS))
-    {}
-
-  void set_CTRS(CardTableRS* rs) { _rs = rs; }
-};
-
-template<>
-struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
-  static const BarrierSet::Name value = BarrierSet::CardTableForRS;
-};
-
 
 #endif // SHARE_VM_GC_SHARED_CARDTABLEMODREFBS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/cardTableModRefBS.inline.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "memory/allocation.inline.hpp"
+#include "gc/shared/space.inline.hpp"
+
+CardTableModRefBSForCTRS::CardTableModRefBSForCTRS(MemRegion whole_heap) :
+  CardTableModRefBS(
+    whole_heap,
+    // Concrete tag should be BarrierSet::CardTableForRS.
+    // That will presently break things in a bunch of places though.
+    // The concrete tag is used as a dispatch key in many places, and
+    // CardTableForRS does not correctly dispatch in some of those
+    // uses. This will be addressed as part of a reorganization of the
+    // BarrierSet hierarchy.
+    BarrierSet::FakeRtti(BarrierSet::CardTableModRef, 0).add_tag(BarrierSet::CardTableForRS)),
+  // LNC functionality
+  _lowest_non_clean(NULL),
+  _lowest_non_clean_chunk_size(NULL),
+  _lowest_non_clean_base_chunk_index(NULL),
+  _last_LNC_resizing_collection(NULL)
+{ }
+
+void CardTableModRefBSForCTRS::initialize() {
+  CardTableModRefBS::initialize();
+  _lowest_non_clean =
+    NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
+  _lowest_non_clean_chunk_size =
+    NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
+  _lowest_non_clean_base_chunk_index =
+    NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
+  _last_LNC_resizing_collection =
+    NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
+  if (_lowest_non_clean == NULL
+      || _lowest_non_clean_chunk_size == NULL
+      || _lowest_non_clean_base_chunk_index == NULL
+      || _last_LNC_resizing_collection == NULL)
+    vm_exit_during_initialization("couldn't allocate an LNC array.");
+  for (int i = 0; i < _max_covered_regions; i++) {
+    _lowest_non_clean[i] = NULL;
+    _lowest_non_clean_chunk_size[i] = 0;
+    _last_LNC_resizing_collection[i] = -1;
+  }
+}
+
+CardTableModRefBSForCTRS::~CardTableModRefBSForCTRS() {
+  if (_lowest_non_clean) {
+    FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
+    _lowest_non_clean = NULL;
+  }
+  if (_lowest_non_clean_chunk_size) {
+    FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
+    _lowest_non_clean_chunk_size = NULL;
+  }
+  if (_lowest_non_clean_base_chunk_index) {
+    FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
+    _lowest_non_clean_base_chunk_index = NULL;
+  }
+  if (_last_LNC_resizing_collection) {
+    FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
+    _last_LNC_resizing_collection = NULL;
+  }
+}
+
+bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
+  return
+    card_is_dirty_wrt_gen_iter(cv) ||
+    _rs->is_prev_nonclean_card_val(cv);
+}
+
+bool CardTableModRefBSForCTRS::card_may_have_been_dirty(jbyte cv) {
+  return
+    cv != clean_card &&
+    (card_is_dirty_wrt_gen_iter(cv) ||
+     CardTableRS::youngergen_may_have_been_dirty(cv));
+}
+
+void CardTableModRefBSForCTRS::non_clean_card_iterate_possibly_parallel(
+  Space* sp,
+  MemRegion mr,
+  OopsInGenClosure* cl,
+  CardTableRS* ct,
+  uint n_threads)
+{
+  if (!mr.is_empty()) {
+    if (n_threads > 0) {
+#if INCLUDE_ALL_GCS
+      non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
+#else  // INCLUDE_ALL_GCS
+      fatal("Parallel gc not supported here.");
+#endif // INCLUDE_ALL_GCS
+    } else {
+      // clear_cl finds contiguous dirty ranges of cards to process and clear.
+
+      // This is the single-threaded version used by DefNew.
+      const bool parallel = false;
+
+      DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(), cl->gen_boundary(), parallel);
+      ClearNoncleanCardWrapper clear_cl(dcto_cl, ct, parallel);
+
+      clear_cl.do_MemRegion(mr);
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBSForCTRS.hpp	Wed Jul 22 00:37:01 2015 -0400
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_CARDTABLEMODREFBSFORCTRS_HPP
+#define SHARE_VM_GC_SHARED_CARDTABLEMODREFBSFORCTRS_HPP
+
+#include "gc/shared/cardTableModRefBS.hpp"
+
+class CardTableRS;
+class DirtyCardToOopClosure;
+class OopsInGenClosure;
+
+// A specialization for the CardTableRS gen rem set.
+class CardTableModRefBSForCTRS: public CardTableModRefBS {
+  friend class CardTableRS;
+
+public:
+  CardTableModRefBSForCTRS(MemRegion whole_heap);
+  ~CardTableModRefBSForCTRS();
+
+  virtual void initialize();
+
+  void set_CTRS(CardTableRS* rs) { _rs = rs; }
+
+private:
+  CardTableRS* _rs;
+
+  // *** Support for parallel card scanning.
+
+  // dirty and precleaned are equivalent wrt younger_refs_iter.
+  static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
+    return cv == dirty_card || cv == precleaned_card;
+  }
+
+  // Returns "true" iff the value "cv" will cause the card containing it
+  // to be scanned in the current traversal.  May be overridden by
+  // subtypes.
+  bool card_will_be_scanned(jbyte cv);
+
+  // Returns "true" iff the value "cv" may have represented a dirty card at
+  // some point.
+  bool card_may_have_been_dirty(jbyte cv);
+
+  // Iterate over the portion of the card-table which covers the given
+  // region mr in the given space and apply cl to any dirty sub-regions
+  // of mr. Clears the dirty cards as they are processed.
+  void non_clean_card_iterate_possibly_parallel(Space* sp, MemRegion mr,
+                                                OopsInGenClosure* cl, CardTableRS* ct,
+                                                uint n_threads);
+
+  // Work method used to implement non_clean_card_iterate_possibly_parallel()
+  // above in the parallel case.
+  void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                            OopsInGenClosure* cl, CardTableRS* ct,
+                                            uint n_threads);
+
+  // This is an array, one element per covered region of the card table.
+  // Each entry is itself an array, with one element per chunk in the
+  // covered region.  Each entry of these arrays is the lowest non-clean
+  // card of the corresponding chunk containing part of an object from the
+  // previous chunk, or else NULL.
+  typedef jbyte*  CardPtr;
+  typedef CardPtr* CardArr;
+  CardArr* _lowest_non_clean;
+  size_t*  _lowest_non_clean_chunk_size;
+  uintptr_t* _lowest_non_clean_base_chunk_index;
+  int* _last_LNC_resizing_collection;
+
+  // Initializes "lowest_non_clean" to point to the array for the region
+  // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
+  // index of the corresponding to the first element of that array.
+  // Ensures that these arrays are of sufficient size, allocating if necessary.
+  // May be called by several threads concurrently.
+  void get_LNC_array_for_space(Space* sp,
+                               jbyte**& lowest_non_clean,
+                               uintptr_t& lowest_non_clean_base_chunk_index,
+                               size_t& lowest_non_clean_chunk_size);
+
+  // Returns the number of chunks necessary to cover "mr".
+  size_t chunks_to_cover(MemRegion mr) {
+    return (size_t)(addr_to_chunk_index(mr.last()) -
+                    addr_to_chunk_index(mr.start()) + 1);
+  }
+
+  // Returns the index of the chunk in a stride which
+  // covers the given address.
+  uintptr_t addr_to_chunk_index(const void* addr) {
+    uintptr_t card = (uintptr_t) byte_for(addr);
+    return card / ParGCCardsPerStrideChunk;
+  }
+
+  // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
+  // to the cards in the stride (of n_strides) within the given space.
+  void process_stride(Space* sp,
+                      MemRegion used,
+                      jint stride, int n_strides,
+                      OopsInGenClosure* cl,
+                      CardTableRS* ct,
+                      jbyte** lowest_non_clean,
+                      uintptr_t lowest_non_clean_base_chunk_index,
+                      size_t lowest_non_clean_chunk_size);
+
+  // Makes sure that chunk boundaries are handled appropriately, by
+  // adjusting the min_done of dcto_cl, and by using a special card-table
+  // value to indicate how min_done should be set.
+  void process_chunk_boundaries(Space* sp,
+                                DirtyCardToOopClosure* dcto_cl,
+                                MemRegion chunk_mr,
+                                MemRegion used,
+                                jbyte** lowest_non_clean,
+                                uintptr_t lowest_non_clean_base_chunk_index,
+                                size_t    lowest_non_clean_chunk_size);
+
+};
+
+template<>
+struct BarrierSet::GetName<CardTableModRefBSForCTRS> {
+  static const BarrierSet::Name value = BarrierSet::CardTableForRS;
+};
+
+#endif // include guard
+
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -240,7 +240,7 @@
 // cur-younger-gen                ==> cur_younger_gen
 // cur_youngergen_and_prev_nonclean_card ==> no change.
 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
-  jbyte* entry = ct_bs()->byte_for(field);
+  jbyte* entry = _ct_bs->byte_for(field);
   do {
     jbyte entry_val = *entry;
     // We put this first because it's probably the most common case.
@@ -398,10 +398,10 @@
   jbyte* cur_entry = byte_for(used.start());
   jbyte* limit = byte_after(used.last());
   while (cur_entry < limit) {
-    if (*cur_entry == CardTableModRefBS::clean_card) {
+    if (*cur_entry == clean_card_val()) {
       jbyte* first_dirty = cur_entry+1;
       while (first_dirty < limit &&
-             *first_dirty == CardTableModRefBS::clean_card) {
+             *first_dirty == clean_card_val()) {
         first_dirty++;
       }
       // If the first object is a regular object, and it has a
@@ -418,7 +418,7 @@
               !boundary_obj->is_typeArray()) {
             guarantee(cur_entry > byte_for(used.start()),
                       "else boundary would be boundary_block");
-            if (*byte_for(boundary_block) != CardTableModRefBS::clean_card) {
+            if (*byte_for(boundary_block) != clean_card_val()) {
               begin = boundary_block + s->block_size(boundary_block);
               start_block = begin;
             }
--- a/hotspot/src/share/vm/gc/shared/cardTableRS.hpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/cardTableRS.hpp	Wed Jul 22 00:37:01 2015 -0400
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_GC_SHARED_CARDTABLERS_HPP
 #define SHARE_VM_GC_SHARED_CARDTABLERS_HPP
 
-#include "gc/shared/cardTableModRefBS.hpp"
+#include "gc/shared/cardTableModRefBSForCTRS.hpp"
 #include "gc/shared/genRemSet.hpp"
 #include "memory/memRegion.hpp"
 
@@ -42,16 +42,16 @@
   friend class ClearNoncleanCardWrapper;
 
   static jbyte clean_card_val() {
-    return CardTableModRefBS::clean_card;
+    return CardTableModRefBSForCTRS::clean_card;
   }
 
   static intptr_t clean_card_row() {
-    return CardTableModRefBS::clean_card_row;
+    return CardTableModRefBSForCTRS::clean_card_row;
   }
 
   static bool
   card_is_dirty_wrt_gen_iter(jbyte cv) {
-    return CardTableModRefBS::card_is_dirty_wrt_gen_iter(cv);
+    return CardTableModRefBSForCTRS::card_is_dirty_wrt_gen_iter(cv);
   }
 
   CardTableModRefBSForCTRS* _ct_bs;
@@ -61,17 +61,17 @@
   void verify_space(Space* s, HeapWord* gen_start);
 
   enum ExtendedCardValue {
-    youngergen_card   = CardTableModRefBS::CT_MR_BS_last_reserved + 1,
+    youngergen_card   = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 1,
     // These are for parallel collection.
     // There are three P (parallel) youngergen card values.  In general, this
     // needs to be more than the number of generations (including the perm
     // gen) that might have younger_refs_do invoked on them separately.  So
     // if we add more gens, we have to add more values.
-    youngergenP1_card  = CardTableModRefBS::CT_MR_BS_last_reserved + 2,
-    youngergenP2_card  = CardTableModRefBS::CT_MR_BS_last_reserved + 3,
-    youngergenP3_card  = CardTableModRefBS::CT_MR_BS_last_reserved + 4,
+    youngergenP1_card  = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 2,
+    youngergenP2_card  = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 3,
+    youngergenP3_card  = CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 4,
     cur_youngergen_and_prev_nonclean_card =
-      CardTableModRefBS::CT_MR_BS_last_reserved + 5
+      CardTableModRefBSForCTRS::CT_MR_BS_last_reserved + 5
   };
 
   // An array that contains, for each generation, the card table value last
@@ -107,7 +107,7 @@
   // *** GenRemSet functions.
   CardTableRS* as_CardTableRS() { return this; }
 
-  CardTableModRefBS* ct_bs() { return _ct_bs; }
+  CardTableModRefBSForCTRS* ct_bs() { return _ct_bs; }
 
   // Override.
   void prepare_for_younger_refs_iterate(bool parallel);
@@ -147,7 +147,7 @@
   void invalidate_or_clear(Generation* old_gen);
 
   static uintx ct_max_alignment_constraint() {
-    return CardTableModRefBS::ct_max_alignment_constraint();
+    return CardTableModRefBSForCTRS::ct_max_alignment_constraint();
   }
 
   jbyte* byte_for(void* p)     { return _ct_bs->byte_for(p); }
--- a/hotspot/src/share/vm/shark/sharkBuilder.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp	Wed Jul 22 00:37:01 2015 -0400
@@ -25,6 +25,8 @@
 
 #include "precompiled.hpp"
 #include "ci/ciMethod.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTableModRefBS.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "runtime/os.hpp"
@@ -442,7 +444,7 @@
     Unimplemented();
 
   CreateStore(
-    LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card),
+    LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card_val()),
     CreateIntToPtr(
       CreateAdd(
         LLVMValue::intptr_constant(
--- a/hotspot/src/share/vm/shark/sharkBuilder.hpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/shark/sharkBuilder.hpp	Wed Jul 22 00:37:01 2015 -0400
@@ -27,8 +27,6 @@
 #define SHARE_VM_SHARK_SHARKBUILDER_HPP
 
 #include "ci/ciType.hpp"
-#include "gc/shared/barrierSet.hpp"
-#include "gc/shared/cardTableModRefBS.hpp"
 #include "shark/llvmHeaders.hpp"
 #include "shark/llvmValue.hpp"
 #include "shark/sharkCodeBuffer.hpp"
@@ -38,6 +36,8 @@
 #include "utilities/debug.hpp"
 #include "utilities/sizes.hpp"
 
+class BarrierSet;
+
 class SharkBuilder : public llvm::IRBuilder<> {
   friend class SharkCompileInvariants;