Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp @ 12233:40136aa2cdb1
8010722: assert: failed: heap size is too big for compressed oops
Summary: Use conservative assumptions of required alignment for the various garbage collector components into account when determining the maximum heap size that supports compressed oops. Using this conservative value avoids several circular dependencies in the calculation.
Reviewed-by: stefank, dholmes
author | tschatzl |
---|---|
date | Wed, 11 Sep 2013 16:25:02 +0200 |
parents | f34d701e952e |
children | bfdf528be8e8 |
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" | |
27 #include "gc_implementation/g1/heapRegionRemSet.hpp" | |
28 #include "runtime/atomic.hpp" | |
29 #include "runtime/mutexLocker.hpp" | |
30 #include "runtime/safepoint.hpp" | |
7180
f34d701e952e
8003935: Simplify the needed includes for using Thread::current()
stefank
parents:
3960
diff
changeset
|
31 #include "runtime/thread.inline.hpp" |
1972 | 32 #include "utilities/workgroup.hpp" |
342 | 33 |
34 bool DirtyCardQueue::apply_closure(CardTableEntryClosure* cl, | |
35 bool consume, | |
36 size_t worker_i) { | |
37 bool res = true; | |
38 if (_buf != NULL) { | |
39 res = apply_closure_to_buffer(cl, _buf, _index, _sz, | |
40 consume, | |
41 (int) worker_i); | |
42 if (res && consume) _index = _sz; | |
43 } | |
44 return res; | |
45 } | |
46 | |
47 bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl, | |
48 void** buf, | |
49 size_t index, size_t sz, | |
50 bool consume, | |
51 int worker_i) { | |
52 if (cl == NULL) return true; | |
53 for (size_t i = index; i < sz; i += oopSize) { | |
54 int ind = byte_index_to_index((int)i); | |
55 jbyte* card_ptr = (jbyte*)buf[ind]; | |
56 if (card_ptr != NULL) { | |
57 // Set the entry to null, so we don't do it again (via the test | |
58 // above) if we reconsider this buffer. | |
59 if (consume) buf[ind] = NULL; | |
60 if (!cl->do_card_ptr(card_ptr, worker_i)) return false; | |
61 } | |
62 } | |
63 return true; | |
64 } | |
65 | |
66 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away | |
67 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list | |
68 #endif // _MSC_VER | |
69 | |
1111 | 70 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : |
71 PtrQueueSet(notify_when_complete), | |
342 | 72 _closure(NULL), |
73 _shared_dirty_card_queue(this, true /*perm*/), | |
74 _free_ids(NULL), | |
75 _processed_buffers_mut(0), _processed_buffers_rs_thread(0) | |
76 { | |
77 _all_active = true; | |
78 } | |
79 | |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
80 // Determines how many mutator threads can process the buffers in parallel. |
342 | 81 size_t DirtyCardQueueSet::num_par_ids() { |
795
215f81b4d9b3
6841831: G1: assert(contains_reference(from),"We just added it!") fires
iveresov
parents:
794
diff
changeset
|
82 return os::processor_count(); |
342 | 83 } |
84 | |
85 void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, | |
1111 | 86 int process_completed_threshold, |
342 | 87 int max_completed_queue, |
616
4f360ec815ba
6720309: G1: don't synchronously update RSet during evacuation pauses
iveresov
parents:
470
diff
changeset
|
88 Mutex* lock, PtrQueueSet* fl_owner) { |
1111 | 89 PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, |
90 max_completed_queue, fl_owner); | |
883
27f6a9b9c311
6864886: G1: rename -XX parameters related to update buffers
tonyp
parents:
795
diff
changeset
|
91 set_buffer_size(G1UpdateBufferSize); |
342 | 92 _shared_dirty_card_queue.set_lock(lock); |
93 _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); | |
94 } | |
95 | |
96 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) { | |
97 t->dirty_card_queue().handle_zero_index(); | |
98 } | |
99 | |
100 void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) { | |
101 _closure = closure; | |
102 } | |
103 | |
104 void DirtyCardQueueSet::iterate_closure_all_threads(bool consume, | |
105 size_t worker_i) { | |
106 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); | |
107 for(JavaThread* t = Threads::first(); t; t = t->next()) { | |
108 bool b = t->dirty_card_queue().apply_closure(_closure, consume); | |
109 guarantee(b, "Should not be interrupted."); | |
110 } | |
111 bool b = shared_dirty_card_queue()->apply_closure(_closure, | |
112 consume, | |
113 worker_i); | |
114 guarantee(b, "Should not be interrupted."); | |
115 } | |
116 | |
117 bool DirtyCardQueueSet::mut_process_buffer(void** buf) { | |
118 | |
119 // Used to determine if we had already claimed a par_id | |
120 // before entering this method. | |
121 bool already_claimed = false; | |
122 | |
123 // We grab the current JavaThread. | |
124 JavaThread* thread = JavaThread::current(); | |
125 | |
126 // We get the the number of any par_id that this thread | |
127 // might have already claimed. | |
128 int worker_i = thread->get_claimed_par_id(); | |
129 | |
130 // If worker_i is not -1 then the thread has already claimed | |
131 // a par_id. We make note of it using the already_claimed value | |
132 if (worker_i != -1) { | |
133 already_claimed = true; | |
134 } else { | |
135 | |
136 // Otherwise we need to claim a par id | |
137 worker_i = _free_ids->claim_par_id(); | |
138 | |
139 // And store the par_id value in the thread | |
140 thread->set_claimed_par_id(worker_i); | |
141 } | |
142 | |
143 bool b = false; | |
144 if (worker_i != -1) { | |
145 b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0, | |
146 _sz, true, worker_i); | |
147 if (b) Atomic::inc(&_processed_buffers_mut); | |
148 | |
149 // If we had not claimed an id before entering the method | |
150 // then we must release the id. | |
151 if (!already_claimed) { | |
152 | |
153 // we release the id | |
154 _free_ids->release_par_id(worker_i); | |
155 | |
156 // and set the claimed_id in the thread to -1 | |
157 thread->set_claimed_par_id(-1); | |
158 } | |
159 } | |
160 return b; | |
161 } | |
162 | |
1111 | 163 |
164 BufferNode* | |
1090
fa357420e7d2
6899058: G1: Internal error in ptrQueue.cpp:201 in nightly tests
johnc
parents:
885
diff
changeset
|
165 DirtyCardQueueSet::get_completed_buffer(int stop_at) { |
1111 | 166 BufferNode* nd = NULL; |
342 | 167 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); |
168 | |
169 if ((int)_n_completed_buffers <= stop_at) { | |
170 _process_completed = false; | |
171 return NULL; | |
172 } | |
173 | |
174 if (_completed_buffers_head != NULL) { | |
175 nd = _completed_buffers_head; | |
1111 | 176 _completed_buffers_head = nd->next(); |
342 | 177 if (_completed_buffers_head == NULL) |
178 _completed_buffers_tail = NULL; | |
179 _n_completed_buffers--; | |
1111 | 180 assert(_n_completed_buffers >= 0, "Invariant"); |
342 | 181 } |
182 debug_only(assert_completed_buffer_list_len_correct_locked()); | |
183 return nd; | |
184 } | |
185 | |
186 bool DirtyCardQueueSet:: | |
1705 | 187 apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, |
188 int worker_i, | |
1111 | 189 BufferNode* nd) { |
342 | 190 if (nd != NULL) { |
1111 | 191 void **buf = BufferNode::make_buffer_from_node(nd); |
192 size_t index = nd->index(); | |
342 | 193 bool b = |
1705 | 194 DirtyCardQueue::apply_closure_to_buffer(cl, buf, |
1111 | 195 index, _sz, |
342 | 196 true, worker_i); |
197 if (b) { | |
198 deallocate_buffer(buf); | |
199 return true; // In normal case, go on to next buffer. | |
200 } else { | |
1111 | 201 enqueue_complete_buffer(buf, index); |
342 | 202 return false; |
203 } | |
204 } else { | |
205 return false; | |
206 } | |
207 } | |
208 | |
1705 | 209 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, |
210 int worker_i, | |
211 int stop_at, | |
212 bool during_pause) { | |
213 assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); | |
214 BufferNode* nd = get_completed_buffer(stop_at); | |
215 bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd); | |
216 if (res) Atomic::inc(&_processed_buffers_rs_thread); | |
217 return res; | |
218 } | |
219 | |
342 | 220 bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i, |
221 int stop_at, | |
1705 | 222 bool during_pause) { |
223 return apply_closure_to_completed_buffer(_closure, worker_i, | |
224 stop_at, during_pause); | |
342 | 225 } |
226 | |
227 void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() { | |
1111 | 228 BufferNode* nd = _completed_buffers_head; |
342 | 229 while (nd != NULL) { |
230 bool b = | |
1111 | 231 DirtyCardQueue::apply_closure_to_buffer(_closure, |
232 BufferNode::make_buffer_from_node(nd), | |
233 0, _sz, false); | |
342 | 234 guarantee(b, "Should not stop early."); |
1111 | 235 nd = nd->next(); |
342 | 236 } |
237 } | |
238 | |
1705 | 239 // Deallocates any completed log buffers |
240 void DirtyCardQueueSet::clear() { | |
1111 | 241 BufferNode* buffers_to_delete = NULL; |
342 | 242 { |
243 MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); | |
244 while (_completed_buffers_head != NULL) { | |
1111 | 245 BufferNode* nd = _completed_buffers_head; |
246 _completed_buffers_head = nd->next(); | |
247 nd->set_next(buffers_to_delete); | |
342 | 248 buffers_to_delete = nd; |
249 } | |
250 _n_completed_buffers = 0; | |
251 _completed_buffers_tail = NULL; | |
252 debug_only(assert_completed_buffer_list_len_correct_locked()); | |
253 } | |
254 while (buffers_to_delete != NULL) { | |
1111 | 255 BufferNode* nd = buffers_to_delete; |
256 buffers_to_delete = nd->next(); | |
257 deallocate_buffer(BufferNode::make_buffer_from_node(nd)); | |
342 | 258 } |
1705 | 259 |
260 } | |
261 | |
262 void DirtyCardQueueSet::abandon_logs() { | |
263 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); | |
264 clear(); | |
342 | 265 // Since abandon is done only at safepoints, we can safely manipulate |
266 // these queues. | |
267 for (JavaThread* t = Threads::first(); t; t = t->next()) { | |
268 t->dirty_card_queue().reset(); | |
269 } | |
270 shared_dirty_card_queue()->reset(); | |
271 } | |
272 | |
273 | |
274 void DirtyCardQueueSet::concatenate_logs() { | |
275 // Iterate over all the threads, if we find a partial log add it to | |
276 // the global list of logs. Temporarily turn off the limit on the number | |
277 // of outstanding buffers. | |
278 int save_max_completed_queue = _max_completed_queue; | |
279 _max_completed_queue = max_jint; | |
280 assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); | |
281 for (JavaThread* t = Threads::first(); t; t = t->next()) { | |
282 DirtyCardQueue& dcq = t->dirty_card_queue(); | |
283 if (dcq.size() != 0) { | |
284 void **buf = t->dirty_card_queue().get_buf(); | |
285 // We must NULL out the unused entries, then enqueue. | |
286 for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) { | |
287 buf[PtrQueue::byte_index_to_index((int)i)] = NULL; | |
288 } | |
289 enqueue_complete_buffer(dcq.get_buf(), dcq.get_index()); | |
290 dcq.reinitialize(); | |
291 } | |
292 } | |
293 if (_shared_dirty_card_queue.size() != 0) { | |
294 enqueue_complete_buffer(_shared_dirty_card_queue.get_buf(), | |
295 _shared_dirty_card_queue.get_index()); | |
296 _shared_dirty_card_queue.reinitialize(); | |
297 } | |
298 // Restore the completed buffer queue limit. | |
299 _max_completed_queue = save_max_completed_queue; | |
300 } |