src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 3065
ff53346271fe
child 3208
ec4b032a4977
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

ysr@777 1 /*
tonyp@2472 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
stefank@2314 25 #include "precompiled.hpp"
stefank@2314 26 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
stefank@2314 27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
stefank@2314 28 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
stefank@2314 29 #include "gc_implementation/g1/g1MMUTracker.hpp"
stefank@2314 30 #include "gc_implementation/g1/vm_operations_g1.hpp"
stefank@2314 31 #include "memory/resourceArea.hpp"
stefank@2314 32 #include "runtime/vmThread.hpp"
ysr@777 33
ysr@777 34 // ======= Concurrent Mark Thread ========
ysr@777 35
ysr@777 36 // The CM thread is created when the G1 garbage collector is used
ysr@777 37
ysr@777 38 SurrogateLockerThread*
ysr@777 39 ConcurrentMarkThread::_slt = NULL;
ysr@777 40
ysr@777 41 ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) :
ysr@777 42 ConcurrentGCThread(),
ysr@777 43 _cm(cm),
ysr@777 44 _started(false),
ysr@777 45 _in_progress(false),
ysr@777 46 _vtime_accum(0.0),
ysr@777 47 _vtime_mark_accum(0.0),
ysr@777 48 _vtime_count_accum(0.0)
ysr@777 49 {
ysr@777 50 create_and_start();
ysr@777 51 }
ysr@777 52
ysr@777 53 class CMCheckpointRootsFinalClosure: public VoidClosure {
ysr@777 54
ysr@777 55 ConcurrentMark* _cm;
ysr@777 56 public:
ysr@777 57
ysr@777 58 CMCheckpointRootsFinalClosure(ConcurrentMark* cm) :
ysr@777 59 _cm(cm) {}
ysr@777 60
ysr@777 61 void do_void(){
ysr@777 62 _cm->checkpointRootsFinal(false); // !clear_all_soft_refs
ysr@777 63 }
ysr@777 64 };
ysr@777 65
ysr@777 66 class CMCleanUp: public VoidClosure {
ysr@777 67 ConcurrentMark* _cm;
ysr@777 68 public:
ysr@777 69
ysr@777 70 CMCleanUp(ConcurrentMark* cm) :
ysr@777 71 _cm(cm) {}
ysr@777 72
ysr@777 73 void do_void(){
ysr@777 74 _cm->cleanup();
ysr@777 75 }
ysr@777 76 };
ysr@777 77
ysr@777 78
ysr@777 79
ysr@777 80 void ConcurrentMarkThread::run() {
ysr@777 81 initialize_in_thread();
ysr@777 82 _vtime_start = os::elapsedVTime();
ysr@777 83 wait_for_universe_init();
ysr@777 84
tonyp@2472 85 G1CollectedHeap* g1h = G1CollectedHeap::heap();
tonyp@2472 86 G1CollectorPolicy* g1_policy = g1h->g1_policy();
ysr@777 87 G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
ysr@777 88 Thread *current_thread = Thread::current();
ysr@777 89
ysr@777 90 while (!_should_terminate) {
ysr@777 91 // wait until started is set.
ysr@777 92 sleepBeforeNextCycle();
ysr@777 93 {
ysr@777 94 ResourceMark rm;
ysr@777 95 HandleMark hm;
ysr@777 96 double cycle_start = os::elapsedVTime();
ysr@777 97 double mark_start_sec = os::elapsedTime();
ysr@777 98 char verbose_str[128];
ysr@777 99
ysr@777 100 if (PrintGC) {
ysr@777 101 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 102 gclog_or_tty->stamp(PrintGCTimeStamps);
tonyp@1054 103 gclog_or_tty->print_cr("[GC concurrent-mark-start]");
ysr@777 104 }
ysr@777 105
ysr@777 106 int iter = 0;
ysr@777 107 do {
ysr@777 108 iter++;
ysr@777 109 if (!cm()->has_aborted()) {
ysr@777 110 _cm->markFromRoots();
ysr@777 111 }
ysr@777 112
ysr@777 113 double mark_end_time = os::elapsedVTime();
ysr@777 114 double mark_end_sec = os::elapsedTime();
ysr@777 115 _vtime_mark_accum += (mark_end_time - cycle_start);
ysr@777 116 if (!cm()->has_aborted()) {
ysr@777 117 if (g1_policy->adaptive_young_list_length()) {
ysr@777 118 double now = os::elapsedTime();
ysr@777 119 double remark_prediction_ms = g1_policy->predict_remark_time_ms();
ysr@777 120 jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms);
ysr@777 121 os::sleep(current_thread, sleep_time_ms, false);
ysr@777 122 }
ysr@777 123
ysr@777 124 if (PrintGC) {
ysr@777 125 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 126 gclog_or_tty->stamp(PrintGCTimeStamps);
ysr@777 127 gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]",
ysr@777 128 mark_end_sec - mark_start_sec);
ysr@777 129 }
ysr@777 130
ysr@777 131 CMCheckpointRootsFinalClosure final_cl(_cm);
ysr@777 132 sprintf(verbose_str, "GC remark");
ysr@777 133 VM_CGC_Operation op(&final_cl, verbose_str);
ysr@777 134 VMThread::execute(&op);
ysr@777 135 }
ysr@777 136 if (cm()->restart_for_overflow() &&
ysr@777 137 G1TraceMarkStackOverflow) {
ysr@777 138 gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
ysr@777 139 "in remark (restart #%d).", iter);
ysr@777 140 }
ysr@777 141
ysr@777 142 if (cm()->restart_for_overflow()) {
ysr@777 143 if (PrintGC) {
ysr@777 144 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 145 gclog_or_tty->stamp(PrintGCTimeStamps);
ysr@777 146 gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]");
ysr@777 147 }
ysr@777 148 }
ysr@777 149 } while (cm()->restart_for_overflow());
ysr@777 150 double counting_start_time = os::elapsedVTime();
ysr@777 151
ysr@777 152 // YSR: These look dubious (i.e. redundant) !!! FIX ME
ysr@777 153 slt()->manipulatePLL(SurrogateLockerThread::acquirePLL);
ysr@777 154 slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
ysr@777 155
ysr@777 156 if (!cm()->has_aborted()) {
ysr@777 157 double count_start_sec = os::elapsedTime();
ysr@777 158 if (PrintGC) {
ysr@777 159 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 160 gclog_or_tty->stamp(PrintGCTimeStamps);
ysr@777 161 gclog_or_tty->print_cr("[GC concurrent-count-start]");
ysr@777 162 }
ysr@777 163
ysr@777 164 _sts.join();
ysr@777 165 _cm->calcDesiredRegions();
ysr@777 166 _sts.leave();
ysr@777 167
ysr@777 168 if (!cm()->has_aborted()) {
ysr@777 169 double count_end_sec = os::elapsedTime();
ysr@777 170 if (PrintGC) {
ysr@777 171 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 172 gclog_or_tty->stamp(PrintGCTimeStamps);
ysr@777 173 gclog_or_tty->print_cr("[GC concurrent-count-end, %1.7lf]",
ysr@777 174 count_end_sec - count_start_sec);
ysr@777 175 }
ysr@777 176 }
ysr@777 177 }
ysr@777 178 double end_time = os::elapsedVTime();
ysr@777 179 _vtime_count_accum += (end_time - counting_start_time);
ysr@777 180 // Update the total virtual time before doing this, since it will try
ysr@777 181 // to measure it to get the vtime for this marking. We purposely
ysr@777 182 // neglect the presumably-short "completeCleanup" phase here.
ysr@777 183 _vtime_accum = (end_time - _vtime_start);
ysr@777 184 if (!cm()->has_aborted()) {
ysr@777 185 if (g1_policy->adaptive_young_list_length()) {
ysr@777 186 double now = os::elapsedTime();
ysr@777 187 double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms();
ysr@777 188 jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms);
ysr@777 189 os::sleep(current_thread, sleep_time_ms, false);
ysr@777 190 }
ysr@777 191
ysr@777 192 CMCleanUp cl_cl(_cm);
ysr@777 193 sprintf(verbose_str, "GC cleanup");
ysr@777 194 VM_CGC_Operation op(&cl_cl, verbose_str);
ysr@777 195 VMThread::execute(&op);
ysr@777 196 } else {
tonyp@2472 197 g1h->set_marking_complete();
ysr@777 198 }
ysr@777 199
tonyp@2472 200 // Check if cleanup set the free_regions_coming flag. If it
tonyp@2472 201 // hasn't, we can just skip the next step.
tonyp@2472 202 if (g1h->free_regions_coming()) {
tonyp@2472 203 // The following will finish freeing up any regions that we
tonyp@2472 204 // found to be empty during cleanup. We'll do this part
tonyp@2472 205 // without joining the suspendible set. If an evacuation pause
tonyp@2643 206 // takes place, then we would carry on freeing regions in
tonyp@2472 207 // case they are needed by the pause. If a Full GC takes
tonyp@2643 208 // place, it would wait for us to process the regions
tonyp@2472 209 // reclaimed by cleanup.
tonyp@2472 210
ysr@777 211 double cleanup_start_sec = os::elapsedTime();
ysr@777 212 if (PrintGC) {
ysr@777 213 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 214 gclog_or_tty->stamp(PrintGCTimeStamps);
ysr@777 215 gclog_or_tty->print_cr("[GC concurrent-cleanup-start]");
ysr@777 216 }
ysr@777 217
ysr@777 218 // Now do the remainder of the cleanup operation.
ysr@777 219 _cm->completeCleanup();
tonyp@2501 220 // Notify anyone who's waiting that there are no more free
tonyp@2501 221 // regions coming. We have to do this before we join the STS,
tonyp@2501 222 // otherwise we might deadlock: a GC worker could be blocked
tonyp@2501 223 // waiting for the notification whereas this thread will be
tonyp@2501 224 // blocked for the pause to finish while it's trying to join
tonyp@2501 225 // the STS, which is conditional on the GC workers finishing.
tonyp@2501 226 g1h->reset_free_regions_coming();
tonyp@2501 227
tonyp@2492 228 _sts.join();
tonyp@2472 229 g1_policy->record_concurrent_mark_cleanup_completed();
tonyp@2492 230 _sts.leave();
ysr@777 231
tonyp@2472 232 double cleanup_end_sec = os::elapsedTime();
tonyp@2472 233 if (PrintGC) {
tonyp@2472 234 gclog_or_tty->date_stamp(PrintGCDateStamps);
tonyp@2472 235 gclog_or_tty->stamp(PrintGCTimeStamps);
tonyp@2472 236 gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
tonyp@2472 237 cleanup_end_sec - cleanup_start_sec);
ysr@777 238 }
ysr@777 239 }
tonyp@2472 240 guarantee(cm()->cleanup_list_is_empty(),
tonyp@2472 241 "at this point there should be no regions on the cleanup list");
ysr@777 242
ysr@777 243 if (cm()->has_aborted()) {
ysr@777 244 if (PrintGC) {
ysr@777 245 gclog_or_tty->date_stamp(PrintGCDateStamps);
ysr@777 246 gclog_or_tty->stamp(PrintGCTimeStamps);
ysr@777 247 gclog_or_tty->print_cr("[GC concurrent-mark-abort]");
ysr@777 248 }
ysr@777 249 }
ysr@777 250
ysr@777 251 // we now want to allow clearing of the marking bitmap to be
ysr@777 252 // suspended by a collection pause.
ysr@777 253 _sts.join();
ysr@777 254 _cm->clearNextBitmap();
ysr@777 255 _sts.leave();
ysr@777 256 }
tonyp@2011 257
tonyp@2011 258 // Update the number of full collections that have been
tonyp@2011 259 // completed. This will also notify the FullGCCount_lock in case a
tonyp@2011 260 // Java thread is waiting for a full GC to happen (e.g., it
tonyp@2011 261 // called System.gc() with +ExplicitGCInvokesConcurrent).
tonyp@2372 262 _sts.join();
tonyp@2472 263 g1h->increment_full_collections_completed(true /* concurrent */);
tonyp@2372 264 _sts.leave();
ysr@777 265 }
ysr@777 266 assert(_should_terminate, "just checking");
ysr@777 267
ysr@777 268 terminate();
ysr@777 269 }
ysr@777 270
ysr@777 271
ysr@777 272 void ConcurrentMarkThread::yield() {
ysr@777 273 _sts.yield("Concurrent Mark");
ysr@777 274 }
ysr@777 275
ysr@777 276 void ConcurrentMarkThread::stop() {
ysr@777 277 // it is ok to take late safepoints here, if needed
ysr@777 278 MutexLockerEx mu(Terminator_lock);
ysr@777 279 _should_terminate = true;
ysr@777 280 while (!_has_terminated) {
ysr@777 281 Terminator_lock->wait();
ysr@777 282 }
ysr@777 283 }
ysr@777 284
tonyp@1454 285 void ConcurrentMarkThread::print() const {
tonyp@1454 286 print_on(tty);
tonyp@1454 287 }
tonyp@1454 288
tonyp@1454 289 void ConcurrentMarkThread::print_on(outputStream* st) const {
tonyp@1454 290 st->print("\"G1 Main Concurrent Mark GC Thread\" ");
tonyp@1454 291 Thread::print_on(st);
tonyp@1454 292 st->cr();
ysr@777 293 }
ysr@777 294
ysr@777 295 void ConcurrentMarkThread::sleepBeforeNextCycle() {
ysr@777 296 // We join here because we don't want to do the "shouldConcurrentMark()"
ysr@777 297 // below while the world is otherwise stopped.
johnc@2195 298 assert(!in_progress(), "should have been cleared");
johnc@2195 299
ysr@777 300 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
ysr@777 301 while (!started()) {
ysr@777 302 CGC_lock->wait(Mutex::_no_safepoint_check_flag);
ysr@777 303 }
ysr@777 304 set_in_progress();
ysr@777 305 clear_started();
ysr@777 306 }
ysr@777 307
ysr@777 308 // Note: this method, although exported by the ConcurrentMarkSweepThread,
ysr@777 309 // which is a non-JavaThread, can only be called by a JavaThread.
ysr@777 310 // Currently this is done at vm creation time (post-vm-init) by the
ysr@777 311 // main/Primordial (Java)Thread.
ysr@777 312 // XXX Consider changing this in the future to allow the CMS thread
ysr@777 313 // itself to create this thread?
ysr@777 314 void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
ysr@777 315 assert(_slt == NULL, "SLT already created");
ysr@777 316 _slt = SurrogateLockerThread::make(THREAD);
ysr@777 317 }

mercurial