Top


定義場所(file name)

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

説明(description)

なお, CMTask::deal_with_reference() 中で使われている CHECK_BOTH_FINGERS は, 未マークのオブジェクトを見つけたときに local/global の両方を確認するか, それとも global だけ確認するかを制御する. 両方確認した方が正確になるので push する量は減るが, オーバーヘッドも増える. 現在は両方確認する(=1)に #define されている.

// This determines whether the method below will check both the local
// and global fingers when determining whether to push on the stack a
// gray object (value 1) or whether it will only check the global one
// (value 0). The tradeoffs are that the former will be a bit more
// accurate and possibly push less on the stack, but it might also be
// a little bit slower.

#define _CHECK_BOTH_FINGERS_      1

名前(function name)

void CMTask::deal_with_reference(oop obj) {

本体部(body)

  {- -------------------------------------------
  (1) (トレース出力)
      ---------------------------------------- -}

      if (_cm->verbose_high())
        gclog_or_tty->print_cr("[%d] we're dealing with reference = "PTR_FORMAT,
                               _task_id, (void*) obj);

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

      ++_refs_reached;

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

      HeapWord* objAddr = (HeapWord*) obj;

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

      assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");

  {- -------------------------------------------
  (1) もし, 処理対象のオブジェクトが...であり(= is_in_g1_reserved()),
      かつまだマークされておらず, かつ TAMS の位置より前に存在している場合,
      (マークの必要があるということなので)
      CMBitMap::parMark() を呼び出してマークする.

      _CHECK_BOTH_FINGERS_ が 1 の場合は, ... であれば push する.
      逆に _CHECK_BOTH_FINGERS_ が 0 なら,
      対象のオブジェクトのアドレスが global_finger よりも小さければ push する.
      (<= これは, (既に処理済みだったら)再調査が必要だと記録するための処理??)

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

      if (_g1h->is_in_g1_reserved(objAddr)) {
        assert(obj != NULL, "is_in_g1_reserved should ensure this");
        HeapRegion* hr =  _g1h->heap_region_containing(obj);
        if (_g1h->is_obj_ill(obj, hr)) {
          if (_cm->verbose_high())
            gclog_or_tty->print_cr("[%d] "PTR_FORMAT" is not considered marked",
                                   _task_id, (void*) obj);

          // we need to mark it first
          if (_nextMarkBitMap->parMark(objAddr)) {
            // No OrderAccess:store_load() is needed. It is implicit in the
            // CAS done in parMark(objAddr) above
            HeapWord* global_finger = _cm->finger();

    #if _CHECK_BOTH_FINGERS_
            // we will check both the local and global fingers

            if (_finger != NULL && objAddr < _finger) {
              if (_cm->verbose_high())
                gclog_or_tty->print_cr("[%d] below the local finger ("PTR_FORMAT"), "
                                       "pushing it", _task_id, _finger);
              push(obj);
            } else if (_curr_region != NULL && objAddr < _region_limit) {
              // do nothing
            } else if (objAddr < global_finger) {
              // Notice that the global finger might be moving forward
              // concurrently. This is not a problem. In the worst case, we
              // mark the object while it is above the global finger and, by
              // the time we read the global finger, it has moved forward
              // passed this object. In this case, the object will probably
              // be visited when a task is scanning the region and will also
              // be pushed on the stack. So, some duplicate work, but no
              // correctness problems.

              if (_cm->verbose_high())
                gclog_or_tty->print_cr("[%d] below the global finger "
                                       "("PTR_FORMAT"), pushing it",
                                       _task_id, global_finger);
              push(obj);
            } else {
              // do nothing
            }
    #else // _CHECK_BOTH_FINGERS_
            // we will only check the global finger

            if (objAddr < global_finger) {
              // see long comment above

              if (_cm->verbose_high())
                gclog_or_tty->print_cr("[%d] below the global finger "
                                       "("PTR_FORMAT"), pushing it",
                                       _task_id, global_finger);
              push(obj);
            }
    #endif // _CHECK_BOTH_FINGERS_
          }
        }
      }
    }

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