1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon May 18 11:52:46 2009 -0700 1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue May 19 04:05:31 2009 -0700 1.3 @@ -446,6 +446,59 @@ 1.4 gclog_or_tty->print_cr(""); 1.5 } 1.6 1.7 +void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr) 1.8 +{ 1.9 + // Claim the right to put the region on the dirty cards region list 1.10 + // by installing a self pointer. 1.11 + HeapRegion* next = hr->get_next_dirty_cards_region(); 1.12 + if (next == NULL) { 1.13 + HeapRegion* res = (HeapRegion*) 1.14 + Atomic::cmpxchg_ptr(hr, hr->next_dirty_cards_region_addr(), 1.15 + NULL); 1.16 + if (res == NULL) { 1.17 + HeapRegion* head; 1.18 + do { 1.19 + // Put the region to the dirty cards region list. 1.20 + head = _dirty_cards_region_list; 1.21 + next = (HeapRegion*) 1.22 + Atomic::cmpxchg_ptr(hr, &_dirty_cards_region_list, head); 1.23 + if (next == head) { 1.24 + assert(hr->get_next_dirty_cards_region() == hr, 1.25 + "hr->get_next_dirty_cards_region() != hr"); 1.26 + if (next == NULL) { 1.27 + // The last region in the list points to itself. 1.28 + hr->set_next_dirty_cards_region(hr); 1.29 + } else { 1.30 + hr->set_next_dirty_cards_region(next); 1.31 + } 1.32 + } 1.33 + } while (next != head); 1.34 + } 1.35 + } 1.36 +} 1.37 + 1.38 +HeapRegion* G1CollectedHeap::pop_dirty_cards_region() 1.39 +{ 1.40 + HeapRegion* head; 1.41 + HeapRegion* hr; 1.42 + do { 1.43 + head = _dirty_cards_region_list; 1.44 + if (head == NULL) { 1.45 + return NULL; 1.46 + } 1.47 + HeapRegion* new_head = head->get_next_dirty_cards_region(); 1.48 + if (head == new_head) { 1.49 + // The last region. 1.50 + new_head = NULL; 1.51 + } 1.52 + hr = (HeapRegion*)Atomic::cmpxchg_ptr(new_head, &_dirty_cards_region_list, 1.53 + head); 1.54 + } while (hr != head); 1.55 + assert(hr != NULL, "invariant"); 1.56 + hr->set_next_dirty_cards_region(NULL); 1.57 + return hr; 1.58 +} 1.59 + 1.60 void G1CollectedHeap::stop_conc_gc_threads() { 1.61 _cg1r->stop(); 1.62 _czft->stop(); 1.63 @@ -1329,7 +1382,8 @@ 1.64 _gc_time_stamp(0), 1.65 _surviving_young_words(NULL), 1.66 _in_cset_fast_test(NULL), 1.67 - _in_cset_fast_test_base(NULL) { 1.68 + _in_cset_fast_test_base(NULL), 1.69 + _dirty_cards_region_list(NULL) { 1.70 _g1h = this; // To catch bugs. 1.71 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { 1.72 vm_exit_during_initialization("Failed necessary allocation."); 1.73 @@ -4691,15 +4745,58 @@ 1.74 } 1.75 } 1.76 1.77 + 1.78 +class G1ParCleanupCTTask : public AbstractGangTask { 1.79 + CardTableModRefBS* _ct_bs; 1.80 + G1CollectedHeap* _g1h; 1.81 +public: 1.82 + G1ParCleanupCTTask(CardTableModRefBS* ct_bs, 1.83 + G1CollectedHeap* g1h) : 1.84 + AbstractGangTask("G1 Par Cleanup CT Task"), 1.85 + _ct_bs(ct_bs), 1.86 + _g1h(g1h) 1.87 + { } 1.88 + 1.89 + void work(int i) { 1.90 + HeapRegion* r; 1.91 + while (r = _g1h->pop_dirty_cards_region()) { 1.92 + clear_cards(r); 1.93 + } 1.94 + } 1.95 + void clear_cards(HeapRegion* r) { 1.96 + // Cards for Survivor and Scan-Only regions will be dirtied later. 1.97 + if (!r->is_scan_only() && !r->is_survivor()) { 1.98 + _ct_bs->clear(MemRegion(r->bottom(), r->end())); 1.99 + } 1.100 + } 1.101 +}; 1.102 + 1.103 + 1.104 void G1CollectedHeap::cleanUpCardTable() { 1.105 CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); 1.106 double start = os::elapsedTime(); 1.107 1.108 - ct_bs->clear(_g1_committed); 1.109 - 1.110 + // Iterate over the dirty cards region list. 1.111 + G1ParCleanupCTTask cleanup_task(ct_bs, this); 1.112 + if (ParallelGCThreads > 0) { 1.113 + set_par_threads(workers()->total_workers()); 1.114 + workers()->run_task(&cleanup_task); 1.115 + set_par_threads(0); 1.116 + } else { 1.117 + while (_dirty_cards_region_list) { 1.118 + HeapRegion* r = _dirty_cards_region_list; 1.119 + cleanup_task.clear_cards(r); 1.120 + _dirty_cards_region_list = r->get_next_dirty_cards_region(); 1.121 + if (_dirty_cards_region_list == r) { 1.122 + // The last region. 1.123 + _dirty_cards_region_list = NULL; 1.124 + } 1.125 + r->set_next_dirty_cards_region(NULL); 1.126 + } 1.127 + } 1.128 // now, redirty the cards of the scan-only and survivor regions 1.129 // (it seemed faster to do it this way, instead of iterating over 1.130 - // all regions and then clearing / dirtying as approprite) 1.131 + // all regions and then clearing / dirtying as appropriate) 1.132 dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region()); 1.133 dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region()); 1.134