Mon, 02 Aug 2010 12:51:43 -0700
6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp
1 /*
2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "incls/_precompiled.incl"
26 #include "incls/_concurrentMarkThread.cpp.incl"
28 // ======= Concurrent Mark Thread ========
30 // The CM thread is created when the G1 garbage collector is used
32 SurrogateLockerThread*
33 ConcurrentMarkThread::_slt = NULL;
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 }
47 class CMCheckpointRootsInitialClosure: public VoidClosure {
49 ConcurrentMark* _cm;
50 public:
52 CMCheckpointRootsInitialClosure(ConcurrentMark* cm) :
53 _cm(cm) {}
55 void do_void(){
56 _cm->checkpointRootsInitial();
57 }
58 };
60 class CMCheckpointRootsFinalClosure: public VoidClosure {
62 ConcurrentMark* _cm;
63 public:
65 CMCheckpointRootsFinalClosure(ConcurrentMark* cm) :
66 _cm(cm) {}
68 void do_void(){
69 _cm->checkpointRootsFinal(false); // !clear_all_soft_refs
70 }
71 };
73 class CMCleanUp: public VoidClosure {
74 ConcurrentMark* _cm;
75 public:
77 CMCleanUp(ConcurrentMark* cm) :
78 _cm(cm) {}
80 void do_void(){
81 _cm->cleanup();
82 }
83 };
87 void ConcurrentMarkThread::run() {
88 initialize_in_thread();
89 _vtime_start = os::elapsedVTime();
90 wait_for_universe_init();
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();
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];
107 if (PrintGC) {
108 gclog_or_tty->date_stamp(PrintGCDateStamps);
109 gclog_or_tty->stamp(PrintGCTimeStamps);
110 gclog_or_tty->print_cr("[GC concurrent-mark-start]");
111 }
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();
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 }
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 }
134 int iter = 0;
135 do {
136 iter++;
137 if (!cm()->has_aborted()) {
138 _cm->markFromRoots();
139 }
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 }
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 }
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 }
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();
180 // YSR: These look dubious (i.e. redundant) !!! FIX ME
181 slt()->manipulatePLL(SurrogateLockerThread::acquirePLL);
182 slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
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 }
192 _sts.join();
193 _cm->calcDesiredRegions();
194 _sts.leave();
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 }
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 }
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 }
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();
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);
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 }
263 // we now want to allow clearing of the marking bitmap to be
264 // suspended by a collection pause.
265 _sts.join();
266 _cm->clearNextBitmap();
267 _sts.leave();
268 }
270 // Update the number of full collections that have been
271 // completed. This will also notify the FullGCCount_lock in case a
272 // Java thread is waiting for a full GC to happen (e.g., it
273 // called System.gc() with +ExplicitGCInvokesConcurrent).
274 g1->increment_full_collections_completed(true /* outer */);
275 }
276 assert(_should_terminate, "just checking");
278 terminate();
279 }
282 void ConcurrentMarkThread::yield() {
283 _sts.yield("Concurrent Mark");
284 }
286 void ConcurrentMarkThread::stop() {
287 // it is ok to take late safepoints here, if needed
288 MutexLockerEx mu(Terminator_lock);
289 _should_terminate = true;
290 while (!_has_terminated) {
291 Terminator_lock->wait();
292 }
293 }
295 void ConcurrentMarkThread::print() const {
296 print_on(tty);
297 }
299 void ConcurrentMarkThread::print_on(outputStream* st) const {
300 st->print("\"G1 Main Concurrent Mark GC Thread\" ");
301 Thread::print_on(st);
302 st->cr();
303 }
305 void ConcurrentMarkThread::sleepBeforeNextCycle() {
306 clear_in_progress();
307 // We join here because we don't want to do the "shouldConcurrentMark()"
308 // below while the world is otherwise stopped.
309 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
310 while (!started()) {
311 CGC_lock->wait(Mutex::_no_safepoint_check_flag);
312 }
313 set_in_progress();
314 clear_started();
315 }
317 // Note: this method, although exported by the ConcurrentMarkSweepThread,
318 // which is a non-JavaThread, can only be called by a JavaThread.
319 // Currently this is done at vm creation time (post-vm-init) by the
320 // main/Primordial (Java)Thread.
321 // XXX Consider changing this in the future to allow the CMS thread
322 // itself to create this thread?
323 void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
324 assert(_slt == NULL, "SLT already created");
325 _slt = SurrogateLockerThread::make(THREAD);
326 }