68 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list |
68 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list |
69 #endif // _MSC_VER |
69 #endif // _MSC_VER |
70 |
70 |
71 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : |
71 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : |
72 PtrQueueSet(notify_when_complete), |
72 PtrQueueSet(notify_when_complete), |
73 _closure(NULL), |
73 _mut_process_closure(NULL), |
74 _shared_dirty_card_queue(this, true /*perm*/), |
74 _shared_dirty_card_queue(this, true /*perm*/), |
75 _free_ids(NULL), |
75 _free_ids(NULL), |
76 _processed_buffers_mut(0), _processed_buffers_rs_thread(0) |
76 _processed_buffers_mut(0), _processed_buffers_rs_thread(0) |
77 { |
77 { |
78 _all_active = true; |
78 _all_active = true; |
81 // Determines how many mutator threads can process the buffers in parallel. |
81 // Determines how many mutator threads can process the buffers in parallel. |
82 uint DirtyCardQueueSet::num_par_ids() { |
82 uint DirtyCardQueueSet::num_par_ids() { |
83 return (uint)os::processor_count(); |
83 return (uint)os::processor_count(); |
84 } |
84 } |
85 |
85 |
86 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, |
86 void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, |
87 int process_completed_threshold, |
87 int process_completed_threshold, |
88 int max_completed_queue, |
88 int max_completed_queue, |
89 Mutex* lock, PtrQueueSet* fl_owner) { |
89 Mutex* lock, PtrQueueSet* fl_owner) { |
|
90 _mut_process_closure = cl; |
90 PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, |
91 PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, |
91 max_completed_queue, fl_owner); |
92 max_completed_queue, fl_owner); |
92 set_buffer_size(G1UpdateBufferSize); |
93 set_buffer_size(G1UpdateBufferSize); |
93 _shared_dirty_card_queue.set_lock(lock); |
94 _shared_dirty_card_queue.set_lock(lock); |
94 _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); |
95 _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); |
96 |
97 |
97 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) { |
98 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) { |
98 t->dirty_card_queue().handle_zero_index(); |
99 t->dirty_card_queue().handle_zero_index(); |
99 } |
100 } |
100 |
101 |
101 void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) { |
102 void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl, |
102 _closure = closure; |
103 bool consume, |
103 } |
|
104 |
|
105 void DirtyCardQueueSet::iterate_closure_all_threads(bool consume, |
|
106 uint worker_i) { |
104 uint worker_i) { |
107 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); |
105 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); |
108 for(JavaThread* t = Threads::first(); t; t = t->next()) { |
106 for(JavaThread* t = Threads::first(); t; t = t->next()) { |
109 bool b = t->dirty_card_queue().apply_closure(_closure, consume); |
107 bool b = t->dirty_card_queue().apply_closure(cl, consume); |
110 guarantee(b, "Should not be interrupted."); |
108 guarantee(b, "Should not be interrupted."); |
111 } |
109 } |
112 bool b = shared_dirty_card_queue()->apply_closure(_closure, |
110 bool b = shared_dirty_card_queue()->apply_closure(cl, |
113 consume, |
111 consume, |
114 worker_i); |
112 worker_i); |
115 guarantee(b, "Should not be interrupted."); |
113 guarantee(b, "Should not be interrupted."); |
116 } |
114 } |
117 |
115 |
141 thread->set_claimed_par_id(worker_i); |
139 thread->set_claimed_par_id(worker_i); |
142 } |
140 } |
143 |
141 |
144 bool b = false; |
142 bool b = false; |
145 if (worker_i != UINT_MAX) { |
143 if (worker_i != UINT_MAX) { |
146 b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0, |
144 b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0, |
147 _sz, true, worker_i); |
145 _sz, true, worker_i); |
148 if (b) Atomic::inc(&_processed_buffers_mut); |
146 if (b) Atomic::inc(&_processed_buffers_mut); |
149 |
147 |
150 // If we had not claimed an id before entering the method |
148 // If we had not claimed an id before entering the method |
151 // then we must release the id. |
149 // then we must release the id. |
216 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd); |
214 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd); |
217 if (res) Atomic::inc(&_processed_buffers_rs_thread); |
215 if (res) Atomic::inc(&_processed_buffers_rs_thread); |
218 return res; |
216 return res; |
219 } |
217 } |
220 |
218 |
221 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i, |
219 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { |
222 int stop_at, |
|
223 bool during_pause) { |
|
224 return apply_closure_to_completed_buffer(_closure, worker_i, |
|
225 stop_at, during_pause); |
|
226 } |
|
227 |
|
228 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() { |
|
229 BufferNode* nd = _completed_buffers_head; |
220 BufferNode* nd = _completed_buffers_head; |
230 while (nd != NULL) { |
221 while (nd != NULL) { |
231 bool b = |
222 bool b = |
232 DirtyCardQueue::apply_closure_to_buffer(_closure, |
223 DirtyCardQueue::apply_closure_to_buffer(cl, |
233 BufferNode::make_buffer_from_node(nd), |
224 BufferNode::make_buffer_from_node(nd), |
234 0, _sz, false); |
225 0, _sz, false); |
235 guarantee(b, "Should not stop early."); |
226 guarantee(b, "Should not stop early."); |
236 nd = nd->next(); |
227 nd = nd->next(); |
|
228 } |
|
229 } |
|
230 |
|
231 void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { |
|
232 BufferNode* nd = _cur_par_buffer_node; |
|
233 while (nd != NULL) { |
|
234 BufferNode* next = (BufferNode*)nd->next(); |
|
235 BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd); |
|
236 if (actual == nd) { |
|
237 bool b = |
|
238 DirtyCardQueue::apply_closure_to_buffer(cl, |
|
239 BufferNode::make_buffer_from_node(actual), |
|
240 0, _sz, false); |
|
241 guarantee(b, "Should not stop early."); |
|
242 nd = next; |
|
243 } else { |
|
244 nd = actual; |
|
245 } |
237 } |
246 } |
238 } |
247 } |
239 |
248 |
240 // Deallocates any completed log buffers |
249 // Deallocates any completed log buffers |
241 void DirtyCardQueueSet::clear() { |
250 void DirtyCardQueueSet::clear() { |