Top


定義場所(file name)

hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp

名前(function name)

void G1CollectedHeap::increment_full_collections_completed(bool concurrent) {

本体部(body)

  {- -------------------------------------------
  (1) (この関数は Concurrent Mark Thread と 
       Full GC を行った VMThread から同時に呼ばれる可能性があるので, 
       FullGCCount_lock を取って排他しておく)
      ---------------------------------------- -}

      MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);

  {- -------------------------------------------
  (1) (concurrent 引数が true であれば, 呼び出し元は Concurrent Mark Thread.
       逆に false であれば, 呼び出し元は Full GC を実行した VMThread)
      (呼び出し元を簡単に確認できる方法があれば assert を追加したい, とのこと)
      ---------------------------------------- -}

      // We assume that if concurrent == true, then the caller is a
      // concurrent thread that was joined the Suspendible Thread
      // Set. If there's ever a cheap way to check this, we should add an
      // assert here.

  {- -------------------------------------------
  (1) (assert)

      (_full_collections_completed フィールドには以前の total_full_collections() の数を記録してある.
       total_full_collections() の回数は GC 開始時にインクリメントしているので, 
       この時点での数字は _full_collections_completed フィールドの値より大きい.

       ただし, Concurrent Mark 処理と Full GC 処理は同時に行われる可能性があるので, 
       1つ大きくなっているケースと 2つ大きくなっているケースが考えられる.

       Concurrent Mark Thread から呼ばれた場合は, 
       処理中に Full GC も発生し, しかもそれがまだ終わっていなければ, 2つ増えている可能性がある.
       VMThread から呼ばれた場合は, 1つ大きくなっているケースしかありえない.)
      ---------------------------------------- -}

      // We have already incremented _total_full_collections at the start
      // of the GC, so total_full_collections() represents how many full
      // collections have been started.
      unsigned int full_collections_started = total_full_collections();

      // Given that this method is called at the end of a Full GC or of a
      // concurrent cycle, and those can be nested (i.e., a Full GC can
      // interrupt a concurrent cycle), the number of full collections
      // completed should be either one (in the case where there was no
      // nesting) or two (when a Full GC interrupted a concurrent cycle)
      // behind the number of full collections started.

      // This is the case for the inner caller, i.e. a Full GC.
      assert(concurrent ||
             (full_collections_started == _full_collections_completed + 1) ||
             (full_collections_started == _full_collections_completed + 2),
             err_msg("for inner caller (Full GC): full_collections_started = %u "
                     "is inconsistent with _full_collections_completed = %u",
                     full_collections_started, _full_collections_completed));

      // This is the case for the outer caller, i.e. the concurrent cycle.
      assert(!concurrent ||
             (full_collections_started == _full_collections_completed + 1),
             err_msg("for outer caller (concurrent cycle): "
                     "full_collections_started = %u "
                     "is inconsistent with _full_collections_completed = %u",
                     full_collections_started, _full_collections_completed));

  {- -------------------------------------------
  (1) _full_collections_completed フィールドをインクリメント.

      (このフィールドの値は, System.gc() で Concurrent Full GC が実行された場合に, 
       その終了を待ち合わせるために使用される.
       See: VM_G1IncCollectionPause::doit(), VM_G1IncCollectionPause::doit_epilogue())
      ---------------------------------------- -}

      _full_collections_completed += 1;

  {- -------------------------------------------
  (1) Concurrent Mark Thread から呼び出された場合は, 
      ConcurrentMarkThread::clear_in_progress() を呼んで
      in_progress フィールドをクリアしておく.

      (これは, Full GC の完了を待っているスレッドが
       起床後に System.gc() を呼び出すようなケースで, 
       Concurrent Mark が実行中だと勘違いしないようにするための措置.)
      ---------------------------------------- -}

      // We need to clear the "in_progress" flag in the CM thread before
      // we wake up any waiters (especially when ExplicitInvokesConcurrent
      // is set) so that if a waiter requests another System.gc() it doesn't
      // incorrectly see that a marking cyle is still in progress.
      if (concurrent) {
        _cmThread->clear_in_progress();
      }

  {- -------------------------------------------
  (1) (Full GC の完了を待っているスレッドがいるかもしれないので)
      FullGCCount_lock に対して Monitor::notify_all() を呼び出し, 
      待っているスレッドがいれば起床させておく.
      (See: VM_G1IncCollectionPause::doit_epilogue())
      ---------------------------------------- -}

      // This notify_all() will ensure that a thread that called
      // System.gc() with (with ExplicitGCInvokesConcurrent set or not)
      // and it's waiting for a full GC to finish will be woken up. It is
      // waiting in VM_G1IncCollectionPause::doit_epilogue().
      FullGCCount_lock->notify_all();
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.