Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @ 807:d44bdab1c03d
6843694: G1: assert(index < _vs.committed_size(),"bad index"), g1BlockOffsetTable.inline.hpp:55
Summary: For heaps larger than 32Gb, the number of heap regions overflows the data type used to hold the region index in the SparsePRT structure. Changed the region indexes, card indexes, and RSet hash table buckets to ints and added some size overflow guarantees.
Reviewed-by: ysr, tonyp
author | johnc |
---|---|
date | Thu, 11 Jun 2009 17:19:33 -0700 |
parents | 20c6f43950b5 |
children | bd02caa94611 |
rev | line source |
---|---|
342 | 1 /* |
2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. | |
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 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_concurrentMarkThread.cpp.incl" | |
27 | |
28 // ======= Concurrent Mark Thread ======== | |
29 | |
30 // The CM thread is created when the G1 garbage collector is used | |
31 | |
32 SurrogateLockerThread* | |
33 ConcurrentMarkThread::_slt = NULL; | |
34 | |
35 ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : | |
36 ConcurrentGCThread(), | |
37 _cm(cm), | |
38 _started(false), | |
39 _in_progress(false), | |
40 _vtime_accum(0.0), | |
41 _vtime_mark_accum(0.0), | |
42 _vtime_count_accum(0.0) | |
43 { | |
44 create_and_start(); | |
45 } | |
46 | |
47 class CMCheckpointRootsInitialClosure: public VoidClosure { | |
48 | |
49 ConcurrentMark* _cm; | |
50 public: | |
51 | |
52 CMCheckpointRootsInitialClosure(ConcurrentMark* cm) : | |
53 _cm(cm) {} | |
54 | |
55 void do_void(){ | |
56 _cm->checkpointRootsInitial(); | |
57 } | |
58 }; | |
59 | |
60 class CMCheckpointRootsFinalClosure: public VoidClosure { | |
61 | |
62 ConcurrentMark* _cm; | |
63 public: | |
64 | |
65 CMCheckpointRootsFinalClosure(ConcurrentMark* cm) : | |
66 _cm(cm) {} | |
67 | |
68 void do_void(){ | |
69 _cm->checkpointRootsFinal(false); // !clear_all_soft_refs | |
70 } | |
71 }; | |
72 | |
73 class CMCleanUp: public VoidClosure { | |
74 ConcurrentMark* _cm; | |
75 public: | |
76 | |
77 CMCleanUp(ConcurrentMark* cm) : | |
78 _cm(cm) {} | |
79 | |
80 void do_void(){ | |
81 _cm->cleanup(); | |
82 } | |
83 }; | |
84 | |
85 | |
86 | |
87 void ConcurrentMarkThread::run() { | |
88 initialize_in_thread(); | |
89 _vtime_start = os::elapsedVTime(); | |
90 wait_for_universe_init(); | |
91 | |
92 G1CollectedHeap* g1 = G1CollectedHeap::heap(); | |
93 G1CollectorPolicy* g1_policy = g1->g1_policy(); | |
94 G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker(); | |
95 Thread *current_thread = Thread::current(); | |
96 | |
97 while (!_should_terminate) { | |
98 // wait until started is set. | |
99 sleepBeforeNextCycle(); | |
100 { | |
101 ResourceMark rm; | |
102 HandleMark hm; | |
103 double cycle_start = os::elapsedVTime(); | |
104 double mark_start_sec = os::elapsedTime(); | |
105 char verbose_str[128]; | |
106 | |
107 if (PrintGC) { | |
108 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
109 gclog_or_tty->stamp(PrintGCTimeStamps); | |
619
7ea5ca260b28
6814467: G1: small fixes related to concurrent marking verboseness
tonyp
parents:
342
diff
changeset
|
110 gclog_or_tty->print_cr("[GC concurrent-mark-start]"); |
342 | 111 } |
112 | |
113 if (!g1_policy->in_young_gc_mode()) { | |
114 // this ensures the flag is not set if we bail out of the marking | |
115 // cycle; normally the flag is cleared immediately after cleanup | |
116 g1->set_marking_complete(); | |
117 | |
118 if (g1_policy->adaptive_young_list_length()) { | |
119 double now = os::elapsedTime(); | |
120 double init_prediction_ms = g1_policy->predict_init_time_ms(); | |
121 jlong sleep_time_ms = mmu_tracker->when_ms(now, init_prediction_ms); | |
122 os::sleep(current_thread, sleep_time_ms, false); | |
123 } | |
124 | |
125 // We don't have to skip here if we've been asked to restart, because | |
126 // in the worst case we just enqueue a new VM operation to start a | |
127 // marking. Note that the init operation resets has_aborted() | |
128 CMCheckpointRootsInitialClosure init_cl(_cm); | |
129 strcpy(verbose_str, "GC initial-mark"); | |
130 VM_CGC_Operation op(&init_cl, verbose_str); | |
131 VMThread::execute(&op); | |
132 } | |
133 | |
134 int iter = 0; | |
135 do { | |
136 iter++; | |
137 if (!cm()->has_aborted()) { | |
138 _cm->markFromRoots(); | |
139 } | |
140 | |
141 double mark_end_time = os::elapsedVTime(); | |
142 double mark_end_sec = os::elapsedTime(); | |
143 _vtime_mark_accum += (mark_end_time - cycle_start); | |
144 if (!cm()->has_aborted()) { | |
145 if (g1_policy->adaptive_young_list_length()) { | |
146 double now = os::elapsedTime(); | |
147 double remark_prediction_ms = g1_policy->predict_remark_time_ms(); | |
148 jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms); | |
149 os::sleep(current_thread, sleep_time_ms, false); | |
150 } | |
151 | |
152 if (PrintGC) { | |
153 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
154 gclog_or_tty->stamp(PrintGCTimeStamps); | |
155 gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]", | |
156 mark_end_sec - mark_start_sec); | |
157 } | |
158 | |
159 CMCheckpointRootsFinalClosure final_cl(_cm); | |
160 sprintf(verbose_str, "GC remark"); | |
161 VM_CGC_Operation op(&final_cl, verbose_str); | |
162 VMThread::execute(&op); | |
163 } | |
164 if (cm()->restart_for_overflow() && | |
165 G1TraceMarkStackOverflow) { | |
166 gclog_or_tty->print_cr("Restarting conc marking because of MS overflow " | |
167 "in remark (restart #%d).", iter); | |
168 } | |
169 | |
170 if (cm()->restart_for_overflow()) { | |
171 if (PrintGC) { | |
172 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
173 gclog_or_tty->stamp(PrintGCTimeStamps); | |
174 gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]"); | |
175 } | |
176 } | |
177 } while (cm()->restart_for_overflow()); | |
178 double counting_start_time = os::elapsedVTime(); | |
179 | |
180 // YSR: These look dubious (i.e. redundant) !!! FIX ME | |
181 slt()->manipulatePLL(SurrogateLockerThread::acquirePLL); | |
182 slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL); | |
183 | |
184 if (!cm()->has_aborted()) { | |
185 double count_start_sec = os::elapsedTime(); | |
186 if (PrintGC) { | |
187 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
188 gclog_or_tty->stamp(PrintGCTimeStamps); | |
189 gclog_or_tty->print_cr("[GC concurrent-count-start]"); | |
190 } | |
191 | |
192 _sts.join(); | |
193 _cm->calcDesiredRegions(); | |
194 _sts.leave(); | |
195 | |
196 if (!cm()->has_aborted()) { | |
197 double count_end_sec = os::elapsedTime(); | |
198 if (PrintGC) { | |
199 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
200 gclog_or_tty->stamp(PrintGCTimeStamps); | |
201 gclog_or_tty->print_cr("[GC concurrent-count-end, %1.7lf]", | |
202 count_end_sec - count_start_sec); | |
203 } | |
204 } | |
205 } | |
206 double end_time = os::elapsedVTime(); | |
207 _vtime_count_accum += (end_time - counting_start_time); | |
208 // Update the total virtual time before doing this, since it will try | |
209 // to measure it to get the vtime for this marking. We purposely | |
210 // neglect the presumably-short "completeCleanup" phase here. | |
211 _vtime_accum = (end_time - _vtime_start); | |
212 if (!cm()->has_aborted()) { | |
213 if (g1_policy->adaptive_young_list_length()) { | |
214 double now = os::elapsedTime(); | |
215 double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms(); | |
216 jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms); | |
217 os::sleep(current_thread, sleep_time_ms, false); | |
218 } | |
219 | |
220 CMCleanUp cl_cl(_cm); | |
221 sprintf(verbose_str, "GC cleanup"); | |
222 VM_CGC_Operation op(&cl_cl, verbose_str); | |
223 VMThread::execute(&op); | |
224 } else { | |
225 G1CollectedHeap::heap()->set_marking_complete(); | |
226 } | |
227 | |
228 if (!cm()->has_aborted()) { | |
229 double cleanup_start_sec = os::elapsedTime(); | |
230 if (PrintGC) { | |
231 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
232 gclog_or_tty->stamp(PrintGCTimeStamps); | |
233 gclog_or_tty->print_cr("[GC concurrent-cleanup-start]"); | |
234 } | |
235 | |
236 // Now do the remainder of the cleanup operation. | |
237 _sts.join(); | |
238 _cm->completeCleanup(); | |
239 if (!cm()->has_aborted()) { | |
240 g1_policy->record_concurrent_mark_cleanup_completed(); | |
241 | |
242 double cleanup_end_sec = os::elapsedTime(); | |
243 if (PrintGC) { | |
244 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
245 gclog_or_tty->stamp(PrintGCTimeStamps); | |
246 gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]", | |
247 cleanup_end_sec - cleanup_start_sec); | |
248 } | |
249 } | |
250 _sts.leave(); | |
251 } | |
252 // We're done: no more unclean regions coming. | |
253 G1CollectedHeap::heap()->set_unclean_regions_coming(false); | |
254 | |
255 if (cm()->has_aborted()) { | |
256 if (PrintGC) { | |
257 gclog_or_tty->date_stamp(PrintGCDateStamps); | |
258 gclog_or_tty->stamp(PrintGCTimeStamps); | |
259 gclog_or_tty->print_cr("[GC concurrent-mark-abort]"); | |
260 } | |
261 } | |
262 | |
263 _sts.join(); | |
264 _cm->disable_co_trackers(); | |
265 _sts.leave(); | |
266 | |
267 // we now want to allow clearing of the marking bitmap to be | |
268 // suspended by a collection pause. | |
269 _sts.join(); | |
270 _cm->clearNextBitmap(); | |
271 _sts.leave(); | |
272 } | |
273 } | |
274 assert(_should_terminate, "just checking"); | |
275 | |
276 terminate(); | |
277 } | |
278 | |
279 | |
280 void ConcurrentMarkThread::yield() { | |
281 _sts.yield("Concurrent Mark"); | |
282 } | |
283 | |
284 void ConcurrentMarkThread::stop() { | |
285 // it is ok to take late safepoints here, if needed | |
286 MutexLockerEx mu(Terminator_lock); | |
287 _should_terminate = true; | |
288 while (!_has_terminated) { | |
289 Terminator_lock->wait(); | |
290 } | |
291 } | |
292 | |
293 void ConcurrentMarkThread::print() { | |
294 gclog_or_tty->print("\"Concurrent Mark GC Thread\" "); | |
295 Thread::print(); | |
296 gclog_or_tty->cr(); | |
297 } | |
298 | |
299 void ConcurrentMarkThread::sleepBeforeNextCycle() { | |
300 clear_in_progress(); | |
301 // We join here because we don't want to do the "shouldConcurrentMark()" | |
302 // below while the world is otherwise stopped. | |
303 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag); | |
304 while (!started()) { | |
305 CGC_lock->wait(Mutex::_no_safepoint_check_flag); | |
306 } | |
307 set_in_progress(); | |
308 clear_started(); | |
309 } | |
310 | |
311 // Note: this method, although exported by the ConcurrentMarkSweepThread, | |
312 // which is a non-JavaThread, can only be called by a JavaThread. | |
313 // Currently this is done at vm creation time (post-vm-init) by the | |
314 // main/Primordial (Java)Thread. | |
315 // XXX Consider changing this in the future to allow the CMS thread | |
316 // itself to create this thread? | |
317 void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) { | |
318 assert(_slt == NULL, "SLT already created"); | |
319 _slt = SurrogateLockerThread::make(THREAD); | |
320 } |