Top


定義場所(file name)

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

名前(function name)

void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
                                      bool clear_all_softrefs) {

本体部(body)

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

      assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");

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

      SharedHeap* sh = SharedHeap::heap();

  {- -------------------------------------------
  (1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
      ---------------------------------------- -}

    #ifdef ASSERT
      if (sh->collector_policy()->should_clear_all_soft_refs()) {
        assert(clear_all_softrefs, "Policy should have been checked earler");
      }
    #endif

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

      // hook up weak ref data so it can be used during Mark-Sweep
      assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
      assert(rp != NULL, "should be non-NULL");

  {- -------------------------------------------
  (1) rp 引数で渡された ReferenceProcessor を GenMarkSweep::_ref_processor フィールドに格納し, 
      ついでに ReferenceProcessor::setup_policy() を呼んで初期化もしておく.
      ---------------------------------------- -}

      GenMarkSweep::_ref_processor = rp;
      rp->setup_policy(clear_all_softrefs);

  {- -------------------------------------------
  (1) フレーム中の bcp (byte code pointer, バイトコードを指すポインタ) を格納している箇所については
      GC によって methodOop が移動すると値が不正になってしまうので, 
      Threads::gc_prologue() を呼んで
      フレーム中の bcp を bci (byte code index, そのバイトコードのメソッド先頭からのオフセット値) に変えておく.

      (なお, CodeCache::gc_prologue()の方は, 単なる(assert) (See: CodeCache::gc_prologue()))
      ---------------------------------------- -}

      // When collecting the permanent generation methodOops may be moving,
      // so we either have to flush all bcp data or convert it into bci.
      CodeCache::gc_prologue();
      Threads::gc_prologue();

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

      // Increment the invocation count for the permanent generation, since it is
      // implicitly collected whenever we do a full mark sweep collection.
      sh->perm_gen()->stat_record()->invocations++;

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

      bool marked_for_unloading = false;

  {- -------------------------------------------
  (1) G1MarkSweep::allocate_stacks() を呼んで, mark フィールドの値を待避するための領域を確保しておく.
      (See: PreservedMark)
      ---------------------------------------- -}

      allocate_stacks();

  {- -------------------------------------------
  (1) BiasedLocking::preserve_marks() を呼んで, 
      mark フィールドが biased pattern になっているオブジェクトのうち
      現在ロックを取得されているものについては, 
      その mark 値を待避しておく.
      (この後の GC 処理では, 生きているオブジェクトに (生きているということを示すための) 印を付ける.
       この印はオブジェクトの mark フィールドに書き込まれるが, 
       そのままだと元の mark フィールドの値は失われてしまうので, 
       元の mark をどこかに待避しておいて, GC 後に書き戻してやる必要がある.)
      ---------------------------------------- -}

      // We should save the marks of the currently locked biased monitors.
      // The marking doesn't preserve the marks of biased objects.
      BiasedLocking::preserve_marks();

  {- -------------------------------------------
  (1) G1MarkSweep::mark_sweep_phase1() を呼んで, 
      全ての生きているオブジェクト(live object)にマークを付ける.
      ---------------------------------------- -}

      mark_sweep_phase1(marked_for_unloading, clear_all_softrefs);

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

      if (VerifyDuringGC) {
          G1CollectedHeap* g1h = G1CollectedHeap::heap();
          g1h->checkConcurrentMark();
      }

  {- -------------------------------------------
  (1) G1MarkSweep::mark_sweep_phase2() を呼んで, 
      各 live object に対して, コンパクション後の新しいアドレスを forwarding pointer として埋め込む.
      ---------------------------------------- -}

      mark_sweep_phase2();

  {- -------------------------------------------
  (1) #ifdef COMPILER2 の場合には, (これから GC を行うので) DerivedPointerTable の値をリセットしておく.
      (See: DerivedPointerTable)
      ---------------------------------------- -}

      // Don't add any more derived pointers during phase3
      COMPILER2_PRESENT(DerivedPointerTable::set_active(false));

  {- -------------------------------------------
  (1) G1MarkSweep::mark_sweep_phase3() を呼んで, 各 live object 内のポインタを新しいアドレスに修正する.
      ---------------------------------------- -}

      mark_sweep_phase3();

  {- -------------------------------------------
  (1) G1MarkSweep::mark_sweep_phase4() を呼んで, 各 live object を新しいアドレスに移動させる.
      ---------------------------------------- -}

      mark_sweep_phase4();

  {- -------------------------------------------
  (1) MarkSweep::restore_marks() を呼んで, 
      MarkSweep::preserve_mark() で待避していた mark 値を, 元のオブジェクトの mark フィールドに書き戻す.
      (See: PreservedMark)
      ---------------------------------------- -}

      GenMarkSweep::restore_marks();

  {- -------------------------------------------
  (1) BiasedLocking::restore_marks() を呼んで, 
      BiasedLocking::preserve_marks() で待避していた mark 値を
      元のオブジェクトの mark フィールドに書き戻す.
      ---------------------------------------- -}

      BiasedLocking::restore_marks();

  {- -------------------------------------------
  (1) GenMarkSweep::deallocate_stacks() を呼んで, 
      GenMarkSweep::allocate_stacks() で確保した領域を解放する.
      (See: PreservedMark)
      ---------------------------------------- -}

      GenMarkSweep::deallocate_stacks();

  {- -------------------------------------------
  (1) CardTableRS::invalidate() を呼んで, Perm 領域の Remembered Set を初期化しておく.
      ---------------------------------------- -}

      // We must invalidate the perm-gen rs, so that it gets rebuilt.
      GenRemSet* rs = sh->rem_set();
      rs->invalidate(sh->perm_gen()->used_region(), true /*whole_heap*/);

  {- -------------------------------------------
  (1) (なんだかコメントアウトされているが... #TODO)
      ---------------------------------------- -}

      // "free at last gc" is calculated from these.
      // CHF: cheating for now!!!
      //  Universe::set_heap_capacity_at_last_gc(Universe::heap()->capacity());
      //  Universe::set_heap_used_at_last_gc(Universe::heap()->used());

  {- -------------------------------------------
  (1) フレーム中の bcp (byte code pointer, バイトコードを指すポインタ) を格納している箇所については
      GC 前に Threads::gc_prologue() で 
      bcp から bci(byte code index, そのバイトコードのメソッド先頭からのオフセット値) へと値を変更していたので, 
      Threads::gc_epilogue() を呼んで元に戻しておく.
      (ついでに, フレーム内の値について環境依存(プラットフォーム依存)な処理が必要であれば, それも行っている)
      ---------------------------------------- -}

      Threads::gc_epilogue();

  {- -------------------------------------------
  (1) #TODO
      ---------------------------------------- -}

      CodeCache::gc_epilogue();

  {- -------------------------------------------
  (1) JvmtiExport::gc_epilogue() を呼んで, 
      JvmtiBreakpointCache 内でキャッシュしているブレークポイントを指すポインタも更新しておく.
      ---------------------------------------- -}

      JvmtiExport::gc_epilogue();

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

      // refs processing: clean slate
      GenMarkSweep::_ref_processor = NULL;
    }

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