Top


定義場所(file name)

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

説明(description)

(コメントによると, 単純化のため single threaded 用のコードは削除したい, とのこと)

// SATB Queue has several assumptions on whether to call the par or
// non-par versions of the methods. this is why some of the code is
// replicated. We should really get rid of the single-threaded version
// of the code to simplify things.

名前(function name)

void CMTask::drain_satb_buffers() {

本体部(body)

  {- -------------------------------------------
  (1) 何らかの理由でこの CMTask が中断されていたら, ここでリターン
      ---------------------------------------- -}

      if (has_aborted())
        return;

  {- -------------------------------------------
  (1) (ここからが _draining_satb_buffers が true の範囲)
      ---------------------------------------- -}

      // We set this so that the regular clock knows that we're in the
      // middle of draining buffers and doesn't set the abort flag when it
      // notices that SATB buffers are available for draining. It'd be
      // very counter productive if it did that. :-)
      _draining_satb_buffers = true;

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

      CMObjectClosure oc(this);
      SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();

  {- -------------------------------------------
  (1) set_par_closure() もしくは set_closure を呼び出して,
      JavaThread::satb_mark_queue_set() に
      CMObjectClosure オブジェクトをセットしておく.
      (この closure が, この後の SATBMarkQueueSet::*_apply_closure_to_completed_buffer() の処理で使用される.)
      ---------------------------------------- -}

      if (G1CollectedHeap::use_parallel_gc_threads())
        satb_mq_set.set_par_closure(_task_id, &oc);
      else
        satb_mq_set.set_closure(&oc);

  {- -------------------------------------------
  (1) 以下のどちらかを呼び出し続けて, SATB バッファの処理を行う.
      (また, 一回呼び出すごとに CMTask::regular_clock_call() も呼び出して, 必要に応じて has_aborted() を true にする)
      この処理は, 呼び出した関数が false を返すか, または has_aborted() が true を返すようになるまで繰り返す.

      * SATBMarkQueueSet::par_apply_closure_to_completed_buffer()
        multi-thread 用
      * SATBMarkQueueSet::apply_closure_to_completed_buffer()
        single thread 用
      ---------------------------------------- -}

      // This keeps claiming and applying the closure to completed buffers
      // until we run out of buffers or we need to abort.
      if (G1CollectedHeap::use_parallel_gc_threads()) {
        while (!has_aborted() &&
               satb_mq_set.par_apply_closure_to_completed_buffer(_task_id)) {
          if (_cm->verbose_medium())
            gclog_or_tty->print_cr("[%d] processed an SATB buffer", _task_id);
          statsOnly( ++_satb_buffers_processed );
          regular_clock_call();
        }
      } else {
        while (!has_aborted() &&
               satb_mq_set.apply_closure_to_completed_buffer()) {
          if (_cm->verbose_medium())
            gclog_or_tty->print_cr("[%d] processed an SATB buffer", _task_id);
          statsOnly( ++_satb_buffers_processed );
          regular_clock_call();
        }
      }

  {- -------------------------------------------
  (1) もし, この処理が Final Mark 用のものであれば(??)
      (そして, まだこの CMTask が中断されていなければ)
      以下のどちらかを呼び出して, ... #TODO

      * SATBMarkQueueSet::par_iterate_closure_all_threads()
        multi-thread 用
      * SATBMarkQueueSet::iterate_closure_all_threads()
        single thread 用
      ---------------------------------------- -}

      if (!concurrent() && !has_aborted()) {
        // We should only do this during remark.
        if (G1CollectedHeap::use_parallel_gc_threads())
          satb_mq_set.par_iterate_closure_all_threads(_task_id);
        else
          satb_mq_set.iterate_closure_all_threads();
      }

  {- -------------------------------------------
  (1) (ここまでが _draining_satb_buffers が true の範囲)
      ---------------------------------------- -}

      _draining_satb_buffers = false;

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

      assert(has_aborted() ||
             concurrent() ||
             satb_mq_set.completed_buffers_num() == 0, "invariant");

  {- -------------------------------------------
  (1) ?? (#TODO) (satb_mq_set (つまり JavaThread::satb_mark_queue_set()) をリセットしている??)
      ---------------------------------------- -}

      if (G1CollectedHeap::use_parallel_gc_threads())
        satb_mq_set.set_par_closure(_task_id, NULL);
      else
        satb_mq_set.set_closure(NULL);

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

      // again, this was a potentially expensive operation, decrease the
      // limits to get the regular clock call early
      decrease_limits();
    }

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