Top


定義場所(file name)

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

名前(function name)

void PSParallelCompact::post_compact()
{

本体部(body)

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

      TraceTime tm("post compact", print_phases(), true, gclog_or_tty);

  {- -------------------------------------------
  (1) PSParallelCompact::clear_data_covering_space() を呼んで, 
      今回の GC で使用したオブジェクトの値をクリアしておく.
      (具体的には, PSParallelCompact::_mark_bitmap, 
       PSParallelCompact::_summary_data, 及び
       それぞれの Space に対応する SplitInfo オブジェクトの値をクリアする.
       なお, _mark_bitmap や _summary_data は
       今回の GC 中に使用してない部分までクリアするのは時間の無駄なので, 
       それぞれの Space ごとに使用した範囲だけをクリアしている)

      また, (この段階では各 Space オブジェクトの top 位置が GC 前のままになっているので)
      SpaceInfo::publish_new_top() で top を正しいアドレスに修正しておく.
      ---------------------------------------- -}

      for (unsigned int id = perm_space_id; id < last_space_id; ++id) {
        // Clear the marking bitmap, summary data and split info.
        clear_data_covering_space(SpaceId(id));
        // Update top().  Must be done after clearing the bitmap and summary data.
        _space_info[id].publish_new_top();
      }

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

      MutableSpace* const eden_space = _space_info[eden_space_id].space();
      MutableSpace* const from_space = _space_info[from_space_id].space();
      MutableSpace* const to_space   = _space_info[to_space_id].space();

      ParallelScavengeHeap* heap = gc_heap();
      bool eden_empty = eden_space->is_empty();

  {- -------------------------------------------
  (1) もし GC 後にも Eden 領域内にオブジェクトが残っていた場合, 
      PSParallelCompact::absorb_live_data_from_eden() を呼んで, 
      領域間の境界をずらすことで, それらを Old 領域内へと移動させることを試みる.
      (成功したかどうかが, 以下の eden_empty に格納される)
      ---------------------------------------- -}

      if (!eden_empty) {
        eden_empty = absorb_live_data_from_eden(heap->size_policy(),
                                                heap->young_gen(), heap->old_gen());
      }

  {- -------------------------------------------
  (1) Universe::update_heap_info_at_gc() を呼んで, 
      以下の値を現在のヒープの最大長(capacity)及び使用量(used)に応じた値に変更する.
        * Universe::get_heap_capacity_at_last_gc()
        * Universe::get_heap_free_at_last_gc() 
        * Universe::get_heap_used_at_last_gc()
      なお, これらの値は ReferencePolicy オブジェクト内で soft reference の消去ポリシーの決定に使用されている.
      (See: ReferencePolicy)
      ---------------------------------------- -}

      // Update heap occupancy information which is used as input to the soft ref
      // clearing policy at the next gc.
      Universe::update_heap_info_at_gc();

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

      bool young_gen_empty = eden_empty && from_space->is_empty() &&
        to_space->is_empty();

  {- -------------------------------------------
  (1) もし barrier set として ModRefBarrierSet (もしくはそのサブクラス) を使用している場合, 
      Perm 領域及び Old 領域に対応する barrier set の値を変更しておく.
      * もう New 領域内にオブジェクトがない場合 (以下の young_gen_empty が true):
        ModRefBarrierSet::clear() で, 対応する箇所全てをクリアする.
      * まだ New 領域内にオブジェクトがある場合 (以下の young_gen_empty が false):
        ModRefBarrierSet::invalidate() で, 対応する箇所全てを dirty にする.
      ---------------------------------------- -}

      BarrierSet* bs = heap->barrier_set();
      if (bs->is_a(BarrierSet::ModRef)) {
        ModRefBarrierSet* modBS = (ModRefBarrierSet*)bs;
        MemRegion old_mr = heap->old_gen()->reserved();
        MemRegion perm_mr = heap->perm_gen()->reserved();
        assert(perm_mr.end() <= old_mr.start(), "Generations out of order");

        if (young_gen_empty) {
          modBS->clear(MemRegion(perm_mr.start(), old_mr.end()));
        } else {
          modBS->invalidate(MemRegion(perm_mr.start(), old_mr.end()));
        }
      }

  {- -------------------------------------------
  (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) #ifdef COMPILER2 の場合には, GC が終わったので
      見つかった derived pointer の値を修正しておく.
      (See: DerivedPointerTable)
      ---------------------------------------- -}

      COMPILER2_PRESENT(DerivedPointerTable::update_pointers());

  {- -------------------------------------------
  (1) 参照オブジェクト(java.lang.ref オブジェクト)に対する後始末を行う.
      (ReferenceProcessor::enqueue_discovered_references() で
      リストに残った参照オブジェクト(= 差し先が死んだため特殊な処理が必要な参照オブジェクト)を pending list に追加する)
      ---------------------------------------- -}

      ref_processor()->enqueue_discovered_references(NULL);

  {- -------------------------------------------
  (1) (デバッグ用の処理)
      (ZapUnusedHeapArea オプションが指定されている場合は ...#TODO)
      ---------------------------------------- -}

      if (ZapUnusedHeapArea) {
        heap->gen_mangle_unused_area();
      }

  {- -------------------------------------------
  (1) PSParallelCompact::reset_millis_since_last_gc() で, _time_of_last_gc フィールドを現在時刻に更新しておく.

      (これは sun.misc.GC.maxObjectInspectionAge() メソッドを実現するため(だけ)の処理.
       See: JVM_MaxObjectInspectionAge())
      ---------------------------------------- -}

      // Update time of last GC
      reset_millis_since_last_gc();
    }

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