Top


定義場所(file name)

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

説明(description)

// This method iterates over all objects in the young generation,
// unforwarding markOops. It then restores any preserved mark oops,
// and clears the _preserved_mark_stack.

名前(function name)

void PSScavenge::clean_up_failed_promotion() {

本体部(body)

  {- -------------------------------------------
  (1) (Minor GC が失敗した場合は, しょうがないので Full GC で回収を試みることになる.

       Minor GC が失敗した直後の状態では, Eden や From 領域に
       (メモリ不足により)コピーできなかったオブジェクトが一部残っている.

       が, これらの領域には, コピーが成功したオブジェクトも含まれている(かもしれない).
       また, コピーが成功したものも失敗したものも, mark フィールドの下2bitは marked の状態になっているので, 
       そのままでは Full GC を実行することが出来ない
       (Full GC のアルゴリズムが混乱する)

       というわけで, Full GC が実行できるように, 以下のような状態まで持って行く.
       * コピーが成功したもの:
         mark フィールドの下2bitを, 通常のオブジェクトとしてあり得る状態にする.
         (なおコピーが成功したものは, (みんなコピー先を参照していて) 
          コピー元はもう誰も参照していないはずなので, あまり丁寧に処理しなくていいはず.
          Full GC 時にはゴミだと判定される)
       * コピーが失敗したもの:
         mark フィールドを Minor GC 実行前の状態に復元する.)

      ---------------------------------------- -}

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

      ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
      assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
      assert(promotion_failed(), "Sanity");

      PSYoungGen* young_gen = heap->young_gen();

      {
        ResourceMark rm;

  {- -------------------------------------------
  (1) PSPromotionFailedClosure で, 
      New 領域中の全てのオブジェクトの mark フィールドを, 初期状態の値にリセットする.
      ---------------------------------------- -}

        // Unforward all pointers in the young gen.
        PSPromotionFailedClosure unforward_closure;
        young_gen->object_iterate(&unforward_closure);

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

        if (PrintGC && Verbose) {
          gclog_or_tty->print_cr("Restoring %d marks", _preserved_oop_stack.size());
        }

  {- -------------------------------------------
  (1) コピーが失敗したオブジェクトについては
      PSPromotionManager::oop_promotion_failed() で mark フィールドの値を待避していたはずなので, 
      その待避していた値をオブジェクトの mark フィールドに書き戻す.
      ---------------------------------------- -}

        // Restore any saved marks.
        while (!_preserved_oop_stack.is_empty()) {
          oop obj      = _preserved_oop_stack.pop();
          markOop mark = _preserved_mark_stack.pop();
          obj->set_mark(mark);
        }

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

        // Clear the preserved mark and oop stack caches.
        _preserved_mark_stack.clear(true);
        _preserved_oop_stack.clear(true);
        _promotion_failed = false;
      }

  {- -------------------------------------------
  (1) (デバッグ用の処理)
      ---------------------------------------- -}

      // Reset the PromotionFailureALot counters.
      NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
    }

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