changeset 49733:6f0a3ea5ab75

8201209: Separate out CMS specific functions into CMSCardTable Reviewed-by: eosterlund, sjohanss
author stefank
date Tue, 10 Apr 2018 12:20:00 +0200
parents c09da96f609e
children f946776e9354
files src/hotspot/share/gc/cms/cmsCardTable.cpp src/hotspot/share/gc/cms/cmsCardTable.hpp src/hotspot/share/gc/cms/cmsHeap.cpp src/hotspot/share/gc/cms/cmsHeap.hpp src/hotspot/share/gc/shared/cardTableRS.cpp src/hotspot/share/gc/shared/cardTableRS.hpp src/hotspot/share/gc/shared/genCollectedHeap.cpp src/hotspot/share/gc/shared/genCollectedHeap.hpp
diffstat 8 files changed, 171 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/gc/cms/cmsCardTable.cpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsCardTable.cpp	Tue Apr 10 12:20:00 2018 +0200
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/cms/cmsCardTable.hpp"
 #include "gc/cms/cmsHeap.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableRS.hpp"
@@ -36,7 +37,24 @@
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
 
-void CardTableRS::
+CMSCardTable::CMSCardTable(MemRegion whole_heap) :
+    CardTableRS(whole_heap, CMSPrecleaningEnabled /* scanned_concurrently */) {
+}
+
+// Returns the number of chunks necessary to cover "mr".
+size_t CMSCardTable::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 CMSCardTable::addr_to_chunk_index(const void* addr) {
+  uintptr_t card = (uintptr_t) byte_for(addr);
+  return card / ParGCCardsPerStrideChunk;
+}
+
+void CMSCardTable::
 non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
                                      OopsInGenClosure* cl,
                                      CardTableRS* ct,
@@ -82,7 +100,7 @@
 }
 
 void
-CardTableRS::
+CMSCardTable::
 process_stride(Space* sp,
                MemRegion used,
                jint stride, int n_strides,
@@ -162,7 +180,7 @@
 }
 
 void
-CardTableRS::
+CMSCardTable::
 process_chunk_boundaries(Space* sp,
                          DirtyCardToOopClosure* dcto_cl,
                          MemRegion chunk_mr,
@@ -371,7 +389,7 @@
 }
 
 void
-CardTableRS::
+CMSCardTable::
 get_LNC_array_for_space(Space* sp,
                         jbyte**& lowest_non_clean,
                         uintptr_t& lowest_non_clean_base_chunk_index,
@@ -430,3 +448,26 @@
   lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i];
   lowest_non_clean_chunk_size       = _lowest_non_clean_chunk_size[i];
 }
+
+#ifdef ASSERT
+void CMSCardTable::verify_used_region_at_save_marks(Space* sp) const {
+  MemRegion ur    = sp->used_region();
+  MemRegion urasm = sp->used_region_at_save_marks();
+
+  if (!ur.contains(urasm)) {
+    log_warning(gc)("CMS+ParNew: Did you forget to call save_marks()? "
+                    "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
+                    "[" PTR_FORMAT ", " PTR_FORMAT ")",
+                    p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
+    MemRegion ur2 = sp->used_region();
+    MemRegion urasm2 = sp->used_region_at_save_marks();
+    if (!ur.equals(ur2)) {
+      log_warning(gc)("CMS+ParNew: Flickering used_region()!!");
+    }
+    if (!urasm.equals(urasm2)) {
+      log_warning(gc)("CMS+ParNew: Flickering used_region_at_save_marks()!!");
+    }
+    ShouldNotReachHere();
+  }
+}
+#endif // ASSERT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cmsCardTable.hpp	Tue Apr 10 12:20:00 2018 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2001, 2018, 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_GC_CMS_CMSCARDTABLE_HPP
+#define SHARE_GC_CMS_CMSCARDTABLE_HPP
+
+#include "gc/shared/cardTableRS.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class DirtyCardToOopClosure;
+class MemRegion;
+class OopsInGenClosure;
+class Space;
+
+class CMSCardTable : public CardTableRS {
+private:
+  // Returns the number of chunks necessary to cover "mr".
+  size_t chunks_to_cover(MemRegion mr);
+
+  // Returns the index of the chunk in a stride which
+  // covers the given address.
+  uintptr_t addr_to_chunk_index(const void* addr);
+
+  // 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);
+
+  // 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);
+
+  virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;
+
+protected:
+  // Work method used to implement non_clean_card_iterate_possibly_parallel()
+  // above in the parallel case.
+  virtual void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                                    OopsInGenClosure* cl, CardTableRS* ct,
+                                                    uint n_threads);
+
+public:
+  CMSCardTable(MemRegion whole_heap);
+};
+
+#endif // SHARE_GC_CMS_CMSCARDTABLE_HPP
--- a/src/hotspot/share/gc/cms/cmsHeap.cpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsHeap.cpp	Tue Apr 10 12:20:00 2018 +0200
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/cms/cmsCardTable.hpp"
 #include "gc/cms/compactibleFreeListSpace.hpp"
 #include "gc/cms/concurrentMarkSweepGeneration.hpp"
 #include "gc/cms/concurrentMarkSweepThread.hpp"
@@ -90,6 +91,10 @@
   return JNI_OK;
 }
 
+CardTableRS* CMSHeap::create_rem_set(const MemRegion& reserved_region) {
+  return new CMSCardTable(reserved_region);
+}
+
 void CMSHeap::initialize_serviceability() {
   _young_manager = new GCMemoryManager("ParNew", "end of minor GC");
   _old_manager = new GCMemoryManager("ConcurrentMarkSweep", "end of major GC");
--- a/src/hotspot/share/gc/cms/cmsHeap.hpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp	Tue Apr 10 12:20:00 2018 +0200
@@ -51,6 +51,7 @@
 
   // Returns JNI_OK on success
   virtual jint initialize();
+  virtual CardTableRS* create_rem_set(const MemRegion& reserved_region);
 
   // Convenience function to be used in situations where the heap type can be
   // asserted to be this type.
--- a/src/hotspot/share/gc/shared/cardTableRS.cpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardTableRS.cpp	Tue Apr 10 12:20:00 2018 +0200
@@ -279,36 +279,24 @@
 void CardTableRS::younger_refs_in_space_iterate(Space* sp,
                                                 OopsInGenClosure* cl,
                                                 uint n_threads) {
+  verify_used_region_at_save_marks(sp);
+
   const MemRegion urasm = sp->used_region_at_save_marks();
+  non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);
+}
+
 #ifdef ASSERT
-  // Convert the assertion check to a warning if we are running
-  // CMS+ParNew until related bug is fixed.
+void CardTableRS::verify_used_region_at_save_marks(Space* sp) const {
   MemRegion ur    = sp->used_region();
-  assert(ur.contains(urasm) || (UseConcMarkSweepGC),
+  MemRegion urasm = sp->used_region_at_save_marks();
+
+  assert(ur.contains(urasm),
          "Did you forget to call save_marks()? "
          "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
          "[" PTR_FORMAT ", " PTR_FORMAT ")",
          p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
-  // In the case of CMS+ParNew, issue a warning
-  if (!ur.contains(urasm)) {
-    assert(UseConcMarkSweepGC, "Tautology: see assert above");
-    log_warning(gc)("CMS+ParNew: Did you forget to call save_marks()? "
-                    "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
-                    "[" PTR_FORMAT ", " PTR_FORMAT ")",
-                    p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
-    MemRegion ur2 = sp->used_region();
-    MemRegion urasm2 = sp->used_region_at_save_marks();
-    if (!ur.equals(ur2)) {
-      log_warning(gc)("CMS+ParNew: Flickering used_region()!!");
-    }
-    if (!urasm.equals(urasm2)) {
-      log_warning(gc)("CMS+ParNew: Flickering used_region_at_save_marks()!!");
-    }
-    ShouldNotReachHere();
-  }
+}
 #endif
-  non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);
-}
 
 void CardTableRS::clear_into_younger(Generation* old_gen) {
   assert(GenCollectedHeap::heap()->is_old_gen(old_gen),
@@ -611,8 +599,8 @@
   CardTable::verify();
 }
 
-CardTableRS::CardTableRS(MemRegion whole_heap) :
-  CardTable(whole_heap, /* scanned concurrently */ UseConcMarkSweepGC && CMSPrecleaningEnabled),
+CardTableRS::CardTableRS(MemRegion whole_heap, bool scanned_concurrently) :
+  CardTable(whole_heap, scanned_concurrently),
   _cur_youngergen_card_val(youngergenP1_card),
   // LNC functionality
   _lowest_non_clean(NULL),
@@ -698,11 +686,7 @@
 {
   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.
 
@@ -717,6 +701,12 @@
   }
 }
 
+void CardTableRS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                                       OopsInGenClosure* cl, CardTableRS* ct,
+                                                       uint n_threads) {
+  fatal("Parallel gc not supported here.");
+}
+
 bool CardTableRS::is_in_young(oop obj) const {
   return GenCollectedHeap::heap()->is_in_young(obj);
 }
--- a/src/hotspot/share/gc/shared/cardTableRS.hpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardTableRS.hpp	Tue Apr 10 12:20:00 2018 +0200
@@ -99,13 +99,15 @@
   jbyte find_unused_youngergenP_card_value();
 
 public:
-  CardTableRS(MemRegion whole_heap);
+  CardTableRS(MemRegion whole_heap, bool scanned_concurrently);
   ~CardTableRS();
 
   CLDRemSet* cld_rem_set() { return &_cld_rem_set; }
 
   void younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl, uint n_threads);
 
+  virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;
+
   // Override.
   void prepare_for_younger_refs_iterate(bool parallel);
 
@@ -174,9 +176,9 @@
 
   // 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);
+  virtual 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
@@ -190,53 +192,7 @@
   uintptr_t* _lowest_non_clean_base_chunk_index;
   volatile 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);
-
   virtual bool is_in_young(oop obj) const;
-
 };
 
 class ClearNoncleanCardWrapper: public MemRegionClosure {
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Tue Apr 10 12:20:00 2018 +0200
@@ -110,7 +110,7 @@
 
   initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*)(heap_rs.base() + heap_rs.size()));
 
-  _rem_set = new CardTableRS(reserved_region());
+  _rem_set = create_rem_set(reserved_region());
   _rem_set->initialize();
   CardTableBarrierSet *bs = new CardTableBarrierSet(_rem_set);
   bs->initialize();
@@ -127,6 +127,10 @@
   return JNI_OK;
 }
 
+CardTableRS* GenCollectedHeap::create_rem_set(const MemRegion& reserved_region) {
+  return new CardTableRS(reserved_region, false /* scan_concurrently */);
+}
+
 void GenCollectedHeap::initialize_size_policy(size_t init_eden_size,
                                               size_t init_promo_size,
                                               size_t init_survivor_size) {
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Tue Apr 10 12:18:42 2018 +0200
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Tue Apr 10 12:20:00 2018 +0200
@@ -167,6 +167,7 @@
 
   // Returns JNI_OK on success
   virtual jint initialize();
+  virtual CardTableRS* create_rem_set(const MemRegion& reserved_region);
 
   void initialize_size_policy(size_t init_eden_size,
                               size_t init_promo_size,