Top


定義場所(file name)

hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp

名前(function name)

void PSMarkSweepDecorator::adjust_pointers() {

本体部(body)

  {- -------------------------------------------
  (1) (ここのコメントまで含めて SCAN_AND_ADJUST_POINTERS からコピペ??)
      ---------------------------------------- -}

      // adjust all the interior pointers to point at the new locations of objects
      // Used by MarkSweep::mark_sweep_phase3()

  {- -------------------------------------------
  (1) (この関数では, bottom() から _end_of_live (これは phase2 中に値を設定) までの領域に対して
       ポインタの修正処理を行う.
       なお, この処理では LiveRange オブジェクトが使用されている (See: LiveRange))
      ---------------------------------------- -}

  {- -------------------------------------------
  (1) (変数宣言など)
      (q は現在処理しているオブジェクトを指すポインタ.
       t は処理範囲の終端を示すポインタ.)
      ---------------------------------------- -}

      HeapWord* q = space()->bottom();
      HeapWord* t = _end_of_live;  // Established by "prepare_for_compaction".

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

      assert(_first_dead <= _end_of_live, "Stands to reason, no?");

  {- -------------------------------------------
  (1) (領域の先頭部分には, コンパクションで場所が移動しないオブジェクトの塊が存在していることがある.
       (領域の先頭のオブジェクトが is_gc_marked() で false を返すにも関わらず, 
        _first_dead の指し先がもっと先になっている場合には, 
        こういう塊が存在しているケース)

       これらのオブジェクトは, mark フィールドが oopDesc::init_mark() で初期化された状態になっている.
       (See: PSMarkSweepDecorator::precompact())
       このため, これらについては is_gc_marked() による判定は出来ない.

       そこで, そういった塊が存在する場合には, 以下の if ブロック内で処理しておく)
      ---------------------------------------- -}

      if (q < t && _first_dead > q &&
          !oop(q)->is_gc_marked()) {
        // we have a chunk of the space which hasn't moved and we've
        // reinitialized the mark word during the previous pass, so we can't
        // use is_gc_marked for the traversal.

    {- -------------------------------------------
  (1.1) 先頭から _first_dead までのオブジェクトを処理する.
        (oopDesc::adjust_pointers() でポインタを修正し, 
         次のオブジェクトへとポインタ(q)を進める, という作業の繰り返し)
        ---------------------------------------- -}

        HeapWord* end = _first_dead;

        while (q < end) {
          VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));
          // point all the oops to the new location
          size_t size = oop(q)->adjust_pointers();
          VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());
          VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));
          q += size;
        }

    {- -------------------------------------------
  (1.1) _first_dead までたどり着いたら, phase2 の処理により
        そこには次の live object の場所を示す LiveRange オブジェクトが埋まっているはずなので, 
        そのアドレスを取り出す.

        (ただし, _first_dead 以降にもう live オブジェクトがない場合 (_first_dead == t の場合) には, 
         単に q を t に設定するだけ.
         この場合, これ以上の処理はもう行われない.)
        ---------------------------------------- -}

        if (_first_dead == t) {
          q = t;
        } else {
          // $$$ This is funky.  Using this to read the previously written
          // LiveRange.  See also use below.
          q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer();
        }
      }

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

      const intx interval = PrefetchScanIntervalInBytes;

      debug_only(HeapWord* prev_q = NULL);

  {- -------------------------------------------
  (1) 処理範囲の終端(t)に到達するまで, 次の while ループを繰り返して, 処理を行っていく.
      このループ内では以下のような処理を行う.
      * 処理対象の箇所(q)のオブジェクトが生きている間 (= is_gc_marked() が true の場合):
        oopDesc::adjust_pointers() でそのオブジェクト内のポインタを修正し, 
        そのオブジェクトの大きさ分だけポインタ(q)を前に進める.
        (これにより, ループの次の週では, 次のオブジェクトに対する処理が始まる)
      * dead オブジェクトに到達した場合 (= is_gc_marked() が false の場合):
        phase2 の処理により, そこには次の live object の場所を示す 
        LiveRange オブジェクトが埋まっているはずなので, 
        そのアドレスまでポインタ(q)を進める.
        (これにより, dead オブジェクトばかりが続く領域は一気にスキップし, 
         ループの次の週では次の live オブジェクトに対する処理が始まる)

      (なお高速化のため, Prefetch::write() で
       PrefetchScanIntervalInBytes バイトずつ
       メモリをプリフェッチしながら行う)
      ---------------------------------------- -}

      while (q < t) {
        // prefetch beyond q
        Prefetch::write(q, interval);
        if (oop(q)->is_gc_marked()) {
          // q is alive
          VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));
          // point all the oops to the new location
          size_t size = oop(q)->adjust_pointers();
          VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());
          VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));
          debug_only(prev_q = q);
          q += size;
        } else {
          // q is not a live object, so its mark should point at the next
          // live object
          debug_only(prev_q = q);
          q = (HeapWord*) oop(q)->mark()->decode_pointer();
          assert(q > prev_q, "we should be moving forward through memory");
        }
      }

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

      assert(q == t, "just checking");
    }

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