Top


定義場所(file name)

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

名前(function name)

void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {

本体部(body)

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

      // world is stopped at this checkpoint
      assert(SafepointSynchronize::is_at_safepoint(),
             "world should be stopped");

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      G1CollectedHeap* g1h = G1CollectedHeap::heap();

  {- -------------------------------------------
  (1) 並行して Full GC が実行されてしまった場合は
      (= ConcurrentMark::has_aborted() が true の場合は), 
      これ以上 marking 処理を続けても結果は不正なので, ここでリターン.

      (ついでに, G1CollectedHeap::set_marking_complete() を呼んで 
       Concurrent Mark 処理が終了したことが分かるようにしておく.)
      ---------------------------------------- -}

      // If a full collection has happened, we shouldn't do this.
      if (has_aborted()) {
        g1h->set_marking_complete(); // So bitmap clearing isn't confused
        return;
      }

  {- -------------------------------------------
  (1) (DTrace のフック点) (JVMTI のフック点)
      (See: SvcGCMarker)
      ---------------------------------------- -}

      SvcGCMarker sgcm(SvcGCMarker::OTHER);

  {- -------------------------------------------
  (1) (verify)
      ---------------------------------------- -}

      if (VerifyDuringGC) {
        HandleMark hm;  // handle scope
        gclog_or_tty->print(" VerifyDuringGC:(before)");
        Universe::heap()->prepare_for_verify();
        Universe::verify(true, false, true);
      }

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      G1CollectorPolicy* g1p = g1h->g1_policy();

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      g1p->record_concurrent_mark_remark_start();

  {- -------------------------------------------
  (1) ConcurrentMark::checkpointRootsFinalWork() を呼び出して, 
      root から辿れるオブジェクトに対して Final marking 処理を行う.

      (ついでに, 処理の前後で開始時間/終了時間も計測しているが, これはトレース出力用の処理.)
      ---------------------------------------- -}

      double start = os::elapsedTime();

      checkpointRootsFinalWork();

      double mark_work_end = os::elapsedTime();

  {- -------------------------------------------
  (1) 次に, ConcurrentMark::weakRefsWork() を呼び出して, 
      ConcurrentMark::checkpointRootsFinalWork() 処理中に見つかった
      参照オブジェクト(java.lang.ref オブジェクト)の処理を行う.
      ---------------------------------------- -}

      weakRefsWork(clear_all_soft_refs);

  {- -------------------------------------------
  (1) もし marking 処理が (ConcurrentMark 内のスタックが一杯になったことで) 失敗していた場合は
      (= ConcurrentMark::has_overflown() が true の場合は), 
      _restart_for_overflow フィールドをセットして concurrent marking をもう一度やり直すことにする.

      (_restart_for_overflow を true にすると, 
       ConcurrentMarkThread::run() 内で concurrent marking 処理が再実行される
       See: ConcurrentMarkThread::run())

      (ついでに, ConcurrentMark::has_overflown() の値はもう消して構わないので, 
       ConcurrentMark::clear_has_overflown() でリセットしている)
      ---------------------------------------- -}

      if (has_overflown()) {
        // Oops.  We overflowed.  Restart concurrent marking.
        _restart_for_overflow = true;
        // Clear the flag. We do not need it any more.
        clear_has_overflown();
        if (G1TraceMarkStackOverflow)
          gclog_or_tty->print_cr("\nRemark led to restart for overflow.");

  {- -------------------------------------------
  (1) marking 処理が成功していた場合は (= ConcurrentMark::has_overflown() が false の場合は), 
      SATBMarkQueueSet::set_active_all_threads() を呼んで
      write barrier を通常時のモード(ポインタを記録しないモード)に戻しておく.
      (See: [here](no2114EV0.html) for details)

      (ついでに, (トレース出力)も出している)
      ---------------------------------------- -}

      } else {
        SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
        // We're done with marking.
        // This is the end of  the marking cycle, we're expected all
        // threads to have SATB queues with active set to true.
        satb_mq_set.set_active_all_threads(false, /* new active value */
                                           true /* expected_active */);

        if (VerifyDuringGC) {
          HandleMark hm;  // handle scope
          gclog_or_tty->print(" VerifyDuringGC:(after)");
          Universe::heap()->prepare_for_verify();
          Universe::heap()->verify(/* allow_dirty */      true,
                                   /* silent */           false,
                                   /* use_prev_marking */ false);
        }
        assert(!restart_for_overflow(), "sanity");
      }

  {- -------------------------------------------
  (1) marking 処理が成功していた場合は (= restart_for_overflow が false の場合は), 
      ConcurrentMark::set_non_marking_state() を呼んで
      ConcurrentMark の状態をリセットしておく.

      (なんで上の if 分の中にまとめていない?? #TODO)
      ---------------------------------------- -}

      // Reset the marking state if marking completed
      if (!restart_for_overflow()) {
        set_non_marking_state();
      }

  {- -------------------------------------------
  (1) (verify)
      ---------------------------------------- -}

    #if VERIFY_OBJS_PROCESSED
      _scan_obj_cl.objs_processed = 0;
      ThreadLocalObjQueue::objs_enqueued = 0;
    #endif

  {- -------------------------------------------
  (1) (トレース出力用の処理)
      (これらのフィールドは現在は以下のパスでのみ参照されている.

      before_exit()
      -> G1CollectedHeap::print_tracing_info()
         -> ConcurrentMark::print_summary_info() (G1SummarizeConcMark オプション指定時のみ))
      ---------------------------------------- -}

      // Statistics
      double now = os::elapsedTime();
      _remark_mark_times.add((mark_work_end - start) * 1000.0);
      _remark_weak_ref_times.add((now - mark_work_end) * 1000.0);
      _remark_times.add((now - start) * 1000.0);

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      g1p->record_concurrent_mark_remark_end();
    }

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