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

     1 /*
     2  * Copyright (c) 2001, 2011, 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 "precompiled.hpp"
    26 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
    27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
    28 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
    29 #include "gc_implementation/g1/g1MMUTracker.hpp"
    30 #include "gc_implementation/g1/vm_operations_g1.hpp"
    31 #include "memory/resourceArea.hpp"
    32 #include "runtime/vmThread.hpp"
    34 // ======= Concurrent Mark Thread ========
    36 // The CM thread is created when the G1 garbage collector is used
    38 SurrogateLockerThread*
    39      ConcurrentMarkThread::_slt = NULL;
    41 ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) :
    42   ConcurrentGCThread(),
    43   _cm(cm),
    44   _started(false),
    45   _in_progress(false),
    46   _vtime_accum(0.0),
    47   _vtime_mark_accum(0.0),
    48   _vtime_count_accum(0.0)
    49 {
    50   create_and_start();
    51 }
    53 class CMCheckpointRootsFinalClosure: public VoidClosure {
    55   ConcurrentMark* _cm;
    56 public:
    58   CMCheckpointRootsFinalClosure(ConcurrentMark* cm) :
    59     _cm(cm) {}
    61   void do_void(){
    62     _cm->checkpointRootsFinal(false); // !clear_all_soft_refs
    63   }
    64 };
    66 class CMCleanUp: public VoidClosure {
    67   ConcurrentMark* _cm;
    68 public:
    70   CMCleanUp(ConcurrentMark* cm) :
    71     _cm(cm) {}
    73   void do_void(){
    74     _cm->cleanup();
    75   }
    76 };
    80 void ConcurrentMarkThread::run() {
    81   initialize_in_thread();
    82   _vtime_start = os::elapsedVTime();
    83   wait_for_universe_init();
    85   G1CollectedHeap* g1h = G1CollectedHeap::heap();
    86   G1CollectorPolicy* g1_policy = g1h->g1_policy();
    87   G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
    88   Thread *current_thread = Thread::current();
    90   while (!_should_terminate) {
    91     // wait until started is set.
    92     sleepBeforeNextCycle();
    93     {
    94       ResourceMark rm;
    95       HandleMark   hm;
    96       double cycle_start = os::elapsedVTime();
    97       double mark_start_sec = os::elapsedTime();
    98       char verbose_str[128];
   100       if (PrintGC) {
   101         gclog_or_tty->date_stamp(PrintGCDateStamps);
   102         gclog_or_tty->stamp(PrintGCTimeStamps);
   103         gclog_or_tty->print_cr("[GC concurrent-mark-start]");
   104       }
   106       int iter = 0;
   107       do {
   108         iter++;
   109         if (!cm()->has_aborted()) {
   110           _cm->markFromRoots();
   111         }
   113         double mark_end_time = os::elapsedVTime();
   114         double mark_end_sec = os::elapsedTime();
   115         _vtime_mark_accum += (mark_end_time - cycle_start);
   116         if (!cm()->has_aborted()) {
   117           if (g1_policy->adaptive_young_list_length()) {
   118             double now = os::elapsedTime();
   119             double remark_prediction_ms = g1_policy->predict_remark_time_ms();
   120             jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms);
   121             os::sleep(current_thread, sleep_time_ms, false);
   122           }
   124           if (PrintGC) {
   125             gclog_or_tty->date_stamp(PrintGCDateStamps);
   126             gclog_or_tty->stamp(PrintGCTimeStamps);
   127             gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]",
   128                                       mark_end_sec - mark_start_sec);
   129           }
   131           CMCheckpointRootsFinalClosure final_cl(_cm);
   132           sprintf(verbose_str, "GC remark");
   133           VM_CGC_Operation op(&final_cl, verbose_str);
   134           VMThread::execute(&op);
   135         }
   136         if (cm()->restart_for_overflow() &&
   137             G1TraceMarkStackOverflow) {
   138           gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
   139                                  "in remark (restart #%d).", iter);
   140         }
   142         if (cm()->restart_for_overflow()) {
   143           if (PrintGC) {
   144             gclog_or_tty->date_stamp(PrintGCDateStamps);
   145             gclog_or_tty->stamp(PrintGCTimeStamps);
   146             gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]");
   147           }
   148         }
   149       } while (cm()->restart_for_overflow());
   150       double counting_start_time = os::elapsedVTime();
   152       // YSR: These look dubious (i.e. redundant) !!! FIX ME
   153       slt()->manipulatePLL(SurrogateLockerThread::acquirePLL);
   154       slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
   156       if (!cm()->has_aborted()) {
   157         double count_start_sec = os::elapsedTime();
   158         if (PrintGC) {
   159           gclog_or_tty->date_stamp(PrintGCDateStamps);
   160           gclog_or_tty->stamp(PrintGCTimeStamps);
   161           gclog_or_tty->print_cr("[GC concurrent-count-start]");
   162         }
   164         _sts.join();
   165         _cm->calcDesiredRegions();
   166         _sts.leave();
   168         if (!cm()->has_aborted()) {
   169           double count_end_sec = os::elapsedTime();
   170           if (PrintGC) {
   171             gclog_or_tty->date_stamp(PrintGCDateStamps);
   172             gclog_or_tty->stamp(PrintGCTimeStamps);
   173             gclog_or_tty->print_cr("[GC concurrent-count-end, %1.7lf]",
   174                                    count_end_sec - count_start_sec);
   175           }
   176         }
   177       }
   178       double end_time = os::elapsedVTime();
   179       _vtime_count_accum += (end_time - counting_start_time);
   180       // Update the total virtual time before doing this, since it will try
   181       // to measure it to get the vtime for this marking.  We purposely
   182       // neglect the presumably-short "completeCleanup" phase here.
   183       _vtime_accum = (end_time - _vtime_start);
   184       if (!cm()->has_aborted()) {
   185         if (g1_policy->adaptive_young_list_length()) {
   186           double now = os::elapsedTime();
   187           double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms();
   188           jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms);
   189           os::sleep(current_thread, sleep_time_ms, false);
   190         }
   192         CMCleanUp cl_cl(_cm);
   193         sprintf(verbose_str, "GC cleanup");
   194         VM_CGC_Operation op(&cl_cl, verbose_str);
   195         VMThread::execute(&op);
   196       } else {
   197         g1h->set_marking_complete();
   198       }
   200       // Check if cleanup set the free_regions_coming flag. If it
   201       // hasn't, we can just skip the next step.
   202       if (g1h->free_regions_coming()) {
   203         // The following will finish freeing up any regions that we
   204         // found to be empty during cleanup. We'll do this part
   205         // without joining the suspendible set. If an evacuation pause
   206         // takes place, then we would carry on freeing regions in
   207         // case they are needed by the pause. If a Full GC takes
   208         // place, it would wait for us to process the regions
   209         // reclaimed by cleanup.
   211         double cleanup_start_sec = os::elapsedTime();
   212         if (PrintGC) {
   213           gclog_or_tty->date_stamp(PrintGCDateStamps);
   214           gclog_or_tty->stamp(PrintGCTimeStamps);
   215           gclog_or_tty->print_cr("[GC concurrent-cleanup-start]");
   216         }
   218         // Now do the remainder of the cleanup operation.
   219         _cm->completeCleanup();
   220         // Notify anyone who's waiting that there are no more free
   221         // regions coming. We have to do this before we join the STS,
   222         // otherwise we might deadlock: a GC worker could be blocked
   223         // waiting for the notification whereas this thread will be
   224         // blocked for the pause to finish while it's trying to join
   225         // the STS, which is conditional on the GC workers finishing.
   226         g1h->reset_free_regions_coming();
   228         _sts.join();
   229         g1_policy->record_concurrent_mark_cleanup_completed();
   230         _sts.leave();
   232         double cleanup_end_sec = os::elapsedTime();
   233         if (PrintGC) {
   234           gclog_or_tty->date_stamp(PrintGCDateStamps);
   235           gclog_or_tty->stamp(PrintGCTimeStamps);
   236           gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
   237                                  cleanup_end_sec - cleanup_start_sec);
   238         }
   239       }
   240       guarantee(cm()->cleanup_list_is_empty(),
   241                 "at this point there should be no regions on the cleanup list");
   243       if (cm()->has_aborted()) {
   244         if (PrintGC) {
   245           gclog_or_tty->date_stamp(PrintGCDateStamps);
   246           gclog_or_tty->stamp(PrintGCTimeStamps);
   247           gclog_or_tty->print_cr("[GC concurrent-mark-abort]");
   248         }
   249       }
   251       // we now want to allow clearing of the marking bitmap to be
   252       // suspended by a collection pause.
   253       _sts.join();
   254       _cm->clearNextBitmap();
   255       _sts.leave();
   256     }
   258     // Update the number of full collections that have been
   259     // completed. This will also notify the FullGCCount_lock in case a
   260     // Java thread is waiting for a full GC to happen (e.g., it
   261     // called System.gc() with +ExplicitGCInvokesConcurrent).
   262     _sts.join();
   263     g1h->increment_full_collections_completed(true /* concurrent */);
   264     _sts.leave();
   265   }
   266   assert(_should_terminate, "just checking");
   268   terminate();
   269 }
   272 void ConcurrentMarkThread::yield() {
   273   _sts.yield("Concurrent Mark");
   274 }
   276 void ConcurrentMarkThread::stop() {
   277   // it is ok to take late safepoints here, if needed
   278   MutexLockerEx mu(Terminator_lock);
   279   _should_terminate = true;
   280   while (!_has_terminated) {
   281     Terminator_lock->wait();
   282   }
   283 }
   285 void ConcurrentMarkThread::print() const {
   286   print_on(tty);
   287 }
   289 void ConcurrentMarkThread::print_on(outputStream* st) const {
   290   st->print("\"G1 Main Concurrent Mark GC Thread\" ");
   291   Thread::print_on(st);
   292   st->cr();
   293 }
   295 void ConcurrentMarkThread::sleepBeforeNextCycle() {
   296   // We join here because we don't want to do the "shouldConcurrentMark()"
   297   // below while the world is otherwise stopped.
   298   assert(!in_progress(), "should have been cleared");
   300   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
   301   while (!started()) {
   302     CGC_lock->wait(Mutex::_no_safepoint_check_flag);
   303   }
   304   set_in_progress();
   305   clear_started();
   306 }
   308 // Note: this method, although exported by the ConcurrentMarkSweepThread,
   309 // which is a non-JavaThread, can only be called by a JavaThread.
   310 // Currently this is done at vm creation time (post-vm-init) by the
   311 // main/Primordial (Java)Thread.
   312 // XXX Consider changing this in the future to allow the CMS thread
   313 // itself to create this thread?
   314 void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
   315   assert(_slt == NULL, "SLT already created");
   316   _slt = SurrogateLockerThread::make(THREAD);
   317 }

mercurial