6841831: G1: assert(contains_reference(from),"We just added it!") fires
authoriveresov
Mon, 18 May 2009 11:52:46 -0700
changeset 2882 d508a8bac491
parent 2881 74a1337e4acc
child 2883 406d1e6d1aa1
6841831: G1: assert(contains_reference(from),"We just added it!") fires Summary: During parallel rset updating we have to make sure that the worker ids of the refinement threads do not intersect with the worker ids that can be claimed by the mutator threads. Reviewed-by: tonyp
hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp
hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp
hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp
hotspot/src/share/vm/gc_implementation/includeDB_gc_g1
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp	Mon May 18 11:52:46 2009 -0700
@@ -33,12 +33,13 @@
   _threads(NULL), _n_threads(0)
 {
   if (G1ConcRefine) {
-    _n_threads = (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads;
+    _n_threads = (int)thread_num();
     if (_n_threads > 0) {
       _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
+      int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
       ConcurrentG1RefineThread *next = NULL;
       for (int i = _n_threads - 1; i >= 0; i--) {
-        ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, i);
+        ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
         assert(t != NULL, "Conc refine should have been created");
         assert(t->cg1r() == this, "Conc refine thread should refer to this");
         _threads[i] = t;
@@ -48,6 +49,13 @@
   }
 }
 
+size_t ConcurrentG1Refine::thread_num() {
+  if (G1ConcRefine) {
+    return (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads;
+  }
+  return 0;
+}
+
 void ConcurrentG1Refine::init() {
   if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) {
     G1CollectedHeap* g1h = G1CollectedHeap::heap();
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp	Mon May 18 11:52:46 2009 -0700
@@ -29,7 +29,6 @@
 class ConcurrentG1Refine: public CHeapObj {
   ConcurrentG1RefineThread** _threads;
   int _n_threads;
-
   // The cache for card refinement.
   bool     _use_cache;
   bool     _def_use_cache;
@@ -86,4 +85,6 @@
 
   void clear_and_record_card_counts();
   void print_final_card_counts();
+
+  static size_t thread_num();
 };
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp	Mon May 18 11:52:46 2009 -0700
@@ -30,8 +30,10 @@
 // The CM thread is created when the G1 garbage collector is used
 
 ConcurrentG1RefineThread::
-ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, int worker_id) :
+ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
+                         int worker_id_offset, int worker_id) :
   ConcurrentGCThread(),
+  _worker_id_offset(worker_id_offset),
   _worker_id(worker_id),
   _active(false),
   _next(next),
@@ -114,7 +116,7 @@
     } else {
       lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
     }
-    while (dcqs.apply_closure_to_completed_buffer(_worker_id, lower_limit)) {
+    while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, lower_limit)) {
       double end_vtime_sec;
       double elapsed_vtime_sec;
       int elapsed_vtime_ms;
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp	Mon May 18 11:52:46 2009 -0700
@@ -34,6 +34,7 @@
   double _vtime_start;  // Initial virtual time.
   double _vtime_accum;  // Initial virtual time.
   int _worker_id;
+  int _worker_id_offset;
 
   // The refinement threads collection is linked list. A predecessor can activate a successor
   // when the number of the rset update buffer crosses a certain threshold. A successor
@@ -73,7 +74,8 @@
 
  public:
   // Constructor
-  ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next, int worker_id);
+  ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
+                           int worker_id_offset, int worker_id);
 
   // Printing
   void print();
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp	Mon May 18 11:52:46 2009 -0700
@@ -71,11 +71,11 @@
   _all_active = true;
 }
 
+// Determines how many mutator threads can process the buffers in parallel.
 size_t DirtyCardQueueSet::num_par_ids() {
-  return MAX2(ParallelGCThreads, (size_t)2);
+  return os::processor_count();
 }
 
-
 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
                                    int max_completed_queue,
                                    Mutex* lock, PtrQueueSet* fl_owner) {
@@ -85,8 +85,6 @@
 
   _shared_dirty_card_queue.set_lock(lock);
   _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
-  bool b = _free_ids->claim_perm_id(0);
-  guarantee(b, "Must reserve id zero for concurrent refinement thread.");
 }
 
 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Mon May 18 11:52:46 2009 -0700
@@ -1052,10 +1052,11 @@
 
 }
 
+// Determines how many threads can add records to an rset in parallel.
+// This can be done by either mutator threads together with the
+// concurrent refinement threads or GC threads.
 int HeapRegionRemSet::num_par_rem_sets() {
-  // We always have at least two, so that a mutator thread can claim an
-  // id and add to a rem set.
-  return (int) MAX2(ParallelGCThreads, (size_t)2);
+  return (int)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
 }
 
 HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Mon May 11 16:30:56 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_g1	Mon May 18 11:52:46 2009 -0700
@@ -282,6 +282,7 @@
 
 heapRegionRemSet.cpp                    allocation.hpp
 heapRegionRemSet.cpp                    bitMap.inline.hpp
+heapRegionRemSet.cpp                    concurrentG1Refine.hpp
 heapRegionRemSet.cpp                    g1BlockOffsetTable.inline.hpp
 heapRegionRemSet.cpp                    g1CollectedHeap.inline.hpp
 heapRegionRemSet.cpp                    heapRegionRemSet.hpp