< prev index next >

src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp

Print this page

        

@@ -4739,10 +4739,17 @@
       assert(mr.is_empty() || space->used_region().contains(mr),
              "Should be in space");
       // Verify that "start" is an object boundary
       assert(mr.is_empty() || oop(mr.start())->is_oop(),
              "Should be an oop");
+      // Inspect that there is good distribution of rescan tasks
+      #ifdef ASSERT
+        if (PrintCMSStatistics != 0) {
+          tty->print_cr("rescan task=" UINT32_FORMAT "/" UINT32_FORMAT ", " PTR_FORMAT "-" PTR_FORMAT ", size=" SIZE_FORMAT".",
+                        nth_task, n_tasks, p2i(mr.start()), p2i(mr.end()), mr.word_size());
+        }
+      #endif
       space->par_oop_iterate(mr, cl);
     }
     pst->all_tasks_completed();
   }
 }

@@ -4953,19 +4960,23 @@
   for (int j = 0; j < no_of_gc_threads; j++) {
     _cursor[j] = 0;
   }
   HeapWord* top = surv->top();
   size_t i;
+  // Stride through the _survivor_plab_arrays based on the number of gc threads so
+  // the whole structure is scanned regardless of the min plab size. This will
+  // produce a more even distribution of scan tasks for the parallel phase.
+  size_t stride = ParallelGCThreads > 4 ? ParallelGCThreads/2 : ParallelGCThreads;
   for (i = 0; i < _survivor_chunk_capacity; i++) {  // all sca entries
     HeapWord* min_val = top;          // Higher than any PLAB address
     uint      min_tid = 0;            // position of min_val this round
     for (int j = 0; j < no_of_gc_threads; j++) {
       ChunkArray* cur_sca = &_survivor_plab_array[j];
-      if (_cursor[j] == cur_sca->end()) {
+      if (_cursor[j] >= cur_sca->end()) {
         continue;
       }
-      assert(_cursor[j] < cur_sca->end(), "ctl pt invariant");
+      assert(_cursor[j] < (cur_sca->end()), "ctl pt invariant");
       HeapWord* cur_val = cur_sca->nth(_cursor[j]);
       assert(surv->used_region().contains(cur_val), "Out of bounds value");
       if (cur_val < min_val) {
         min_tid = j;
         min_val = cur_val;

@@ -4980,28 +4991,33 @@
     // and increment _cursor[min_tid] prior to the next round i.
     if (min_val == top) {
       break;
     }
     _survivor_chunk_array[i] = min_val;
-    _cursor[min_tid]++;
+    _cursor[min_tid] += stride;
   }
   // We are all done; record the size of the _survivor_chunk_array
   _survivor_chunk_index = i; // exclusive: [0, i)
   if (PrintCMSStatistics > 0) {
     gclog_or_tty->print(" (Survivor:" SIZE_FORMAT "chunks) ", i);
   }
   // Verify that we used up all the recorded entries
   #ifdef ASSERT
     size_t total = 0;
     for (int j = 0; j < no_of_gc_threads; j++) {
-      assert(_cursor[j] == _survivor_plab_array[j].end(), "Ctl pt invariant");
+      assert(_cursor[j] >= _survivor_plab_array[j].end() && _cursor[j] < (_survivor_plab_array[j].end() + stride) ,
+             err_msg("Did not use all entries of thread  " INT32_FORMAT ": _cursor[]=" SIZE_FORMAT
+                      " != survivor_plab_array[]=" SIZE_FORMAT,
+                      j, _cursor[j], _survivor_plab_array[j].end()));
       total += _cursor[j];
     }
-    assert(total == _survivor_chunk_index, "Ctl Pt Invariant");
+    assert(total == (_survivor_chunk_index * stride),
+           err_msg("Survivor stride error: total=" SIZE_FORMAT ": _survivor_chunk_index=" SIZE_FORMAT,
+                   total, _survivor_chunk_index));
     // Check that the merged array is in sorted order
-    if (total > 0) {
-      for (size_t i = 0; i < total - 1; i++) {
+    if (_survivor_chunk_index > 0) {
+      for (size_t i = 0; i < _survivor_chunk_index - 1; i++) {
         if (PrintCMSStatistics > 0) {
           gclog_or_tty->print(" (chunk" SIZE_FORMAT ":" INTPTR_FORMAT ") ",
                               i, p2i(_survivor_chunk_array[i]));
         }
         assert(_survivor_chunk_array[i] < _survivor_chunk_array[i+1],
< prev index next >