8152182: Possible overflow in initialzation of _rescan_task_size and _marking_task_size
authorsangheki
Thu, 07 Apr 2016 15:34:21 -0700
changeset 37433 f8fd0bcc60af
parent 37432 4a57933cebfa
child 37434 303d15f45adf
child 37435 e7aff5e5eff9
child 37440 eea810d6f788
8152182: Possible overflow in initialzation of _rescan_task_size and _marking_task_size Summary: Add constraints for CMSRescanMultiple and CMSConcMarkMultiple flags Reviewed-by: jwilhelm, jmasa
hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp
hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp
hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp
hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp
hotspot/src/share/vm/runtime/globals.hpp
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Thu Apr 07 15:33:25 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Thu Apr 07 15:34:21 2016 -0700
@@ -2836,6 +2836,11 @@
   par_get_chunk_of_blocks_dictionary(word_sz, n, fl);
 }
 
+const size_t CompactibleFreeListSpace::max_flag_size_for_task_size() const {
+  const size_t ergo_max = _old_gen->reserved().word_size() / (CardTableModRefBS::card_size_in_words * BitsPerWord);
+  return ergo_max;
+}
+
 // Set up the space's par_seq_tasks structure for work claiming
 // for parallel rescan. See CMSParRemarkTask where this is currently used.
 // XXX Need to suitably abstract and generalize this and the next
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp	Thu Apr 07 15:33:25 2016 -0700
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp	Thu Apr 07 15:34:21 2016 -0700
@@ -345,6 +345,8 @@
   // Support for parallelization of rescan and marking.
   const size_t rescan_task_size()  const { return _rescan_task_size;  }
   const size_t marking_task_size() const { return _marking_task_size; }
+  // Return ergonomic max size for CMSRescanMultiple and CMSConcMarkMultiple.
+  const size_t max_flag_size_for_task_size() const;
   SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; }
   void initialize_sequential_subtasks_for_rescan(int n_threads);
   void initialize_sequential_subtasks_for_marking(int n_threads,
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Thu Apr 07 15:33:25 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp	Thu Apr 07 15:34:21 2016 -0700
@@ -457,6 +457,51 @@
   }
 }
 
+static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC) {
+    ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
+    const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size();
+    if (value > ergo_max) {
+      CommandLineError::print(verbose,
+                              "%s (" SIZE_FORMAT ") must be "
+                              "less than or equal to ergonomic maximum (" SIZE_FORMAT ") "
+                              "which is based on the maximum size of the old generation of the Java heap\n",
+                              name, value, ergo_max);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+#endif
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) {
+  Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose);
+
+#if INCLUDE_ALL_GCS
+  if (status == Flag::SUCCESS && UseConcMarkSweepGC) {
+    // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size()
+    // to be aligned to CardTableModRefBS::card_size * BitsPerWord.
+    // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize'
+    // because rescan_task_size() is CardTableModRefBS::card_size / HeapWordSize * BitsPerWord.
+    if (value % HeapWordSize != 0) {
+      CommandLineError::print(verbose,
+                              "CMSRescanMultiple (" SIZE_FORMAT ") must be "
+                              "a multiple of " SIZE_FORMAT "\n",
+                              value, HeapWordSize);
+      status = Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+#endif
+
+  return status;
+}
+
+Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) {
+  return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose);
+}
+
 Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) {
 #if INCLUDE_ALL_GCS
   if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) {
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Thu Apr 07 15:33:25 2016 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp	Thu Apr 07 15:34:21 2016 -0700
@@ -60,6 +60,8 @@
 Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose);
 Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose);
 Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose);
+Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose);
 Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose);
 Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose);
 Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Apr 07 15:33:25 2016 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Thu Apr 07 15:34:21 2016 -0700
@@ -1806,13 +1806,17 @@
           "enough work per iteration")                                      \
           range(0, max_intx)                                                \
                                                                             \
+  /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */          \
   product(size_t, CMSRescanMultiple, 32,                                    \
           "Size (in cards) of CMS parallel rescan task")                    \
-          range(1, max_uintx)                                               \
-                                                                            \
+          range(1, SIZE_MAX / 4096)                                         \
+          constraint(CMSRescanMultipleConstraintFunc,AfterMemoryInit)       \
+                                                                            \
+  /* 4096 = CardTableModRefBS::card_size_in_words * BitsPerWord */          \
   product(size_t, CMSConcMarkMultiple, 32,                                  \
           "Size (in cards) of CMS concurrent MT marking task")              \
-          range(1, max_uintx)                                               \
+          range(1, SIZE_MAX / 4096)                                         \
+          constraint(CMSConcMarkMultipleConstraintFunc,AfterMemoryInit)     \
                                                                             \
   product(bool, CMSAbortSemantics, false,                                   \
           "Whether abort-on-overflow semantics is implemented")             \