Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp @ 20211:82693fb204a5
8038930: G1CodeRootSet::test fails with assert(_num_chunks_handed_out == 0) failed: No elements must have been handed out yet
Summary: The test incorrectly assumed that it had been started with no other previous compilation activity. Fix this by allowing multiple code root free chunk lists, and use one separate from the global one to perform the test.
Reviewed-by: brutisso
author | tschatzl |
---|---|
date | Wed, 16 Apr 2014 10:14:50 +0200 |
parents | 8847586c9037 |
children | 570cb6369f17 |
rev | line source |
---|---|
342 | 1 /* |
1705 | 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
342 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1111
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1111
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1111
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/g1/dirtyCardQueue.hpp" | |
17833
bfdf528be8e8
8038498: Fix includes and C inlining after 8035330
tschatzl
parents:
7180
diff
changeset
|
27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" |
1972 | 28 #include "gc_implementation/g1/heapRegionRemSet.hpp" |
29 #include "runtime/atomic.hpp" | |
30 #include "runtime/mutexLocker.hpp" | |
31 #include "runtime/safepoint.hpp" | |
7180
f34d701e952e
8003935: Simplify the needed includes for using Thread::current()
stefank
parents:
3960
diff
changeset
|
32 #include "runtime/thread.inline.hpp" |
1972 | 33 #include "utilities/workgroup.hpp" |
342 | 34 |
35 bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, | |
36 bool consume, | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
37 uint worker_i) { |
342 | 38 bool res = true; |
39 if (_buf != NULL) { | |
40 res = apply_closure_to_buffer(cl, _buf, _index, _sz, | |
41 consume, | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
42 worker_i); |
342 | 43 if (res && consume) _index = _sz; |
44 } | |
45 return res; | |
46 } | |
47 | |
48 bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl, | |
49 void** buf, | |
50 size_t index, size_t sz, | |
51 bool consume, | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
52 uint worker_i) { |
342 | 53 if (cl == NULL) return true; |
54 for (size_t i = index; i < sz; i += oopSize) { | |
55 int ind = byte_index_to_index((int)i); | |
56 jbyte* card_ptr = (jbyte*)buf[ind]; | |
57 if (card_ptr != NULL) { | |
58 // Set the entry to null, so we don't do it again (via the test | |
59 // above) if we reconsider this buffer. | |
60 if (consume) buf[ind] = NULL; | |
61 if (!cl->do_card_ptr(card_ptr, worker_i)) return false; | |
62 } | |
63 } | |
64 return true; | |
65 } | |
66 | |
67 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away | |
68 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list | |
69 #endif // _MSC_VER | |
70 | |
1111 | 71 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : |
72 PtrQueueSet(notify_when_complete), | |
342 | 73 _closure(NULL), |
74 _shared_dirty_card_queue(this, true /*perm*/), | |
75 _free_ids(NULL), | |
76 _processed_buffers_mut(0), _processed_buffers_rs_thread(0) | |
77 { | |
78 _all_active = true; | |
79 } | |
80 | |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
81 // Determines how many mutator threads can process the buffers in parallel. |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
82 uint DirtyCardQueueSet::num_par_ids() { |
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
83 return (uint)os::processor_count(); |
342 | 84 } |
85 | |
86 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, | |
1111 | 87 int process_completed_threshold, |
342 | 88 int max_completed_queue, |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
470
diff
changeset
|
89 Mutex* lock, PtrQueueSet* fl_owner) { |
1111 | 90 PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, |
91 max_completed_queue, fl_owner); | |
883
27f6a9b9c311
6864886: G1: rename -XX parameters related to update buffers
tonyp
parents:
795
diff
changeset
|
92 set_buffer_size(G1UpdateBufferSize); |
342 | 93 _shared_dirty_card_queue.set_lock(lock); |
94 _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); | |
95 } | |
96 | |
97 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) { | |
98 t->dirty_card_queue().handle_zero_index(); | |
99 } | |
100 | |
101 void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) { | |
102 _closure = closure; | |
103 } | |
104 | |
105 void DirtyCardQueueSet::iterate_closure_all_threads(bool consume, | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
106 uint worker_i) { |
342 | 107 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); |
108 for(JavaThread* t = Threads::first(); t; t = t->next()) { | |
109 bool b = t->dirty_card_queue().apply_closure(_closure, consume); | |
110 guarantee(b, "Should not be interrupted."); | |
111 } | |
112 bool b = shared_dirty_card_queue()->apply_closure(_closure, | |
113 consume, | |
114 worker_i); | |
115 guarantee(b, "Should not be interrupted."); | |
116 } | |
117 | |
118 bool DirtyCardQueueSet::mut_process_buffer(void** buf) { | |
119 | |
120 // Used to determine if we had already claimed a par_id | |
121 // before entering this method. | |
122 bool already_claimed = false; | |
123 | |
124 // We grab the current JavaThread. | |
125 JavaThread* thread = JavaThread::current(); | |
126 | |
127 // We get the the number of any par_id that this thread | |
128 // might have already claimed. | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
129 uint worker_i = thread->get_claimed_par_id(); |
342 | 130 |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
131 // If worker_i is not UINT_MAX then the thread has already claimed |
342 | 132 // a par_id. We make note of it using the already_claimed value |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
133 if (worker_i != UINT_MAX) { |
342 | 134 already_claimed = true; |
135 } else { | |
136 | |
137 // Otherwise we need to claim a par id | |
138 worker_i = _free_ids->claim_par_id(); | |
139 | |
140 // And store the par_id value in the thread | |
141 thread->set_claimed_par_id(worker_i); | |
142 } | |
143 | |
144 bool b = false; | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
145 if (worker_i != UINT_MAX) { |
342 | 146 b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0, |
147 _sz, true, worker_i); | |
148 if (b) Atomic::inc(&_processed_buffers_mut); | |
149 | |
150 // If we had not claimed an id before entering the method | |
151 // then we must release the id. | |
152 if (!already_claimed) { | |
153 | |
154 // we release the id | |
155 _free_ids->release_par_id(worker_i); | |
156 | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
157 // and set the claimed_id in the thread to UINT_MAX |
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
158 thread->set_claimed_par_id(UINT_MAX); |
342 | 159 } |
160 } | |
161 return b; | |
162 } | |
163 | |
1111 | 164 |
165 BufferNode* | |
1090
fa357420e7d2
6899058: G1: Internal error in ptrQueue.cpp:201 in nightly tests
johnc
parents:
885
diff
changeset
|
166 DirtyCardQueueSet::get_completed_buffer(int stop_at) { |
1111 | 167 BufferNode* nd = NULL; |
342 | 168 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
169 | |
170 if ((int)_n_completed_buffers <= stop_at) { | |
171 _process_completed = false; | |
172 return NULL; | |
173 } | |
174 | |
175 if (_completed_buffers_head != NULL) { | |
176 nd = _completed_buffers_head; | |
1111 | 177 _completed_buffers_head = nd->next(); |
342 | 178 if (_completed_buffers_head == NULL) |
179 _completed_buffers_tail = NULL; | |
180 _n_completed_buffers--; | |
1111 | 181 assert(_n_completed_buffers >= 0, "Invariant"); |
342 | 182 } |
183 debug_only(assert_completed_buffer_list_len_correct_locked()); | |
184 return nd; | |
185 } | |
186 | |
187 bool DirtyCardQueueSet:: | |
1705 | 188 apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
189 uint worker_i, |
1111 | 190 BufferNode* nd) { |
342 | 191 if (nd != NULL) { |
1111 | 192 void **buf = BufferNode::make_buffer_from_node(nd); |
193 size_t index = nd->index(); | |
342 | 194 bool b = |
1705 | 195 DirtyCardQueue::apply_closure_to_buffer(cl, buf, |
1111 | 196 index, _sz, |
342 | 197 true, worker_i); |
198 if (b) { | |
199 deallocate_buffer(buf); | |
200 return true; // In normal case, go on to next buffer. | |
201 } else { | |
1111 | 202 enqueue_complete_buffer(buf, index); |
342 | 203 return false; |
204 } | |
205 } else { | |
206 return false; | |
207 } | |
208 } | |
209 | |
1705 | 210 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
211 uint worker_i, |
1705 | 212 int stop_at, |
213 bool during_pause) { | |
214 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); | |
215 BufferNode* nd = get_completed_buffer(stop_at); | |
216 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd); | |
217 if (res) Atomic::inc(&_processed_buffers_rs_thread); | |
218 return res; | |
219 } | |
220 | |
17844
8847586c9037
8016302: Change type of the number of GC workers to unsigned int (2)
vkempik
parents:
17833
diff
changeset
|
221 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i, |
342 | 222 int stop_at, |
1705 | 223 bool during_pause) { |
224 return apply_closure_to_completed_buffer(_closure, worker_i, | |
225 stop_at, during_pause); | |
342 | 226 } |
227 | |
228 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() { | |
1111 | 229 BufferNode* nd = _completed_buffers_head; |
342 | 230 while (nd != NULL) { |
231 bool b = | |
1111 | 232 DirtyCardQueue::apply_closure_to_buffer(_closure, |
233 BufferNode::make_buffer_from_node(nd), | |
234 0, _sz, false); | |
342 | 235 guarantee(b, "Should not stop early."); |
1111 | 236 nd = nd->next(); |
342 | 237 } |
238 } | |
239 | |
1705 | 240 // Deallocates any completed log buffers |
241 void DirtyCardQueueSet::clear() { | |
1111 | 242 BufferNode* buffers_to_delete = NULL; |
342 | 243 { |
244 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); | |
245 while (_completed_buffers_head != NULL) { | |
1111 | 246 BufferNode* nd = _completed_buffers_head; |
247 _completed_buffers_head = nd->next(); | |
248 nd->set_next(buffers_to_delete); | |
342 | 249 buffers_to_delete = nd; |
250 } | |
251 _n_completed_buffers = 0; | |
252 _completed_buffers_tail = NULL; | |
253 debug_only(assert_completed_buffer_list_len_correct_locked()); | |
254 } | |
255 while (buffers_to_delete != NULL) { | |
1111 | 256 BufferNode* nd = buffers_to_delete; |
257 buffers_to_delete = nd->next(); | |
258 deallocate_buffer(BufferNode::make_buffer_from_node(nd)); | |
342 | 259 } |
1705 | 260 |
261 } | |
262 | |
263 void DirtyCardQueueSet::abandon_logs() { | |
264 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); | |
265 clear(); | |
342 | 266 // Since abandon is done only at safepoints, we can safely manipulate |
267 // these queues. | |
268 for (JavaThread* t = Threads::first(); t; t = t->next()) { | |
269 t->dirty_card_queue().reset(); | |
270 } | |
271 shared_dirty_card_queue()->reset(); | |
272 } | |
273 | |
274 | |
275 void DirtyCardQueueSet::concatenate_logs() { | |
276 // Iterate over all the threads, if we find a partial log add it to | |
277 // the global list of logs. Temporarily turn off the limit on the number | |
278 // of outstanding buffers. | |
279 int save_max_completed_queue = _max_completed_queue; | |
280 _max_completed_queue = max_jint; | |
281 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); | |
282 for (JavaThread* t = Threads::first(); t; t = t->next()) { | |
283 DirtyCardQueue& dcq = t->dirty_card_queue(); | |
284 if (dcq.size() != 0) { | |
285 void **buf = t->dirty_card_queue().get_buf(); | |
286 // We must NULL out the unused entries, then enqueue. | |
287 for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) { | |
288 buf[PtrQueue::byte_index_to_index((int)i)] = NULL; | |
289 } | |
290 enqueue_complete_buffer(dcq.get_buf(), dcq.get_index()); | |
291 dcq.reinitialize(); | |
292 } | |
293 } | |
294 if (_shared_dirty_card_queue.size() != 0) { | |
295 enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(), | |
296 _shared_dirty_card_queue.get_index()); | |
297 _shared_dirty_card_queue.reinitialize(); | |
298 } | |
299 // Restore the completed buffer queue limit. | |
300 _max_completed_queue = save_max_completed_queue; | |
301 } |