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

changeset 2011
4e5661ba9d98
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
     1.1 --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Mon Jun 28 14:13:18 2010 -0400
     1.2 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp	Mon Jun 28 14:13:17 2010 -0400
     1.3 @@ -42,8 +42,65 @@
     1.4  void VM_G1IncCollectionPause::doit() {
     1.5    JvmtiGCForAllocationMarker jgcm;
     1.6    G1CollectedHeap* g1h = G1CollectedHeap::heap();
     1.7 +  assert(!_should_initiate_conc_mark ||
     1.8 +  ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
     1.9 +   (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)),
    1.10 +         "only a GC locker or a System.gc() induced GC should start a cycle");
    1.11 +
    1.12    GCCauseSetter x(g1h, _gc_cause);
    1.13 -  g1h->do_collection_pause_at_safepoint();
    1.14 +  if (_should_initiate_conc_mark) {
    1.15 +    // It's safer to read full_collections_completed() here, given
    1.16 +    // that noone else will be updating it concurrently. Since we'll
    1.17 +    // only need it if we're initiating a marking cycle, no point in
    1.18 +    // setting it earlier.
    1.19 +    _full_collections_completed_before = g1h->full_collections_completed();
    1.20 +
    1.21 +    // At this point we are supposed to start a concurrent cycle. We
    1.22 +    // will do so if one is not already in progress.
    1.23 +    bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle();
    1.24 +  }
    1.25 +  g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
    1.26 +}
    1.27 +
    1.28 +void VM_G1IncCollectionPause::doit_epilogue() {
    1.29 +  VM_GC_Operation::doit_epilogue();
    1.30 +
    1.31 +  // If the pause was initiated by a System.gc() and
    1.32 +  // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
    1.33 +  // that just started (or maybe one that was already in progress) to
    1.34 +  // finish.
    1.35 +  if (_gc_cause == GCCause::_java_lang_system_gc &&
    1.36 +      _should_initiate_conc_mark) {
    1.37 +    assert(ExplicitGCInvokesConcurrent,
    1.38 +           "the only way to be here is if ExplicitGCInvokesConcurrent is set");
    1.39 +
    1.40 +    G1CollectedHeap* g1h = G1CollectedHeap::heap();
    1.41 +
    1.42 +    // In the doit() method we saved g1h->full_collections_completed()
    1.43 +    // in the _full_collections_completed_before field. We have to
    1.44 +    // wait until we observe that g1h->full_collections_completed()
    1.45 +    // has increased by at least one. This can happen if a) we started
    1.46 +    // a cycle and it completes, b) a cycle already in progress
    1.47 +    // completes, or c) a Full GC happens.
    1.48 +
    1.49 +    // If the condition has already been reached, there's no point in
    1.50 +    // actually taking the lock and doing the wait.
    1.51 +    if (g1h->full_collections_completed() <=
    1.52 +                                          _full_collections_completed_before) {
    1.53 +      // The following is largely copied from CMS
    1.54 +
    1.55 +      Thread* thr = Thread::current();
    1.56 +      assert(thr->is_Java_thread(), "invariant");
    1.57 +      JavaThread* jt = (JavaThread*)thr;
    1.58 +      ThreadToNativeFromVM native(jt);
    1.59 +
    1.60 +      MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
    1.61 +      while (g1h->full_collections_completed() <=
    1.62 +                                          _full_collections_completed_before) {
    1.63 +        FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
    1.64 +      }
    1.65 +    }
    1.66 +  }
    1.67  }
    1.68  
    1.69  void VM_CGC_Operation::doit() {

mercurial