Top


定義場所(file name)

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

説明(description)

(この関数は, PSMarkSweep::absorb_live_data_from_eden() とそっくり)

名前(function name)

bool PSParallelCompact::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy,
                                             PSYoungGen* young_gen,
                                             PSOldGen* old_gen) {

本体部(body)

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

      MutableSpace* const eden_space = young_gen->eden_space();
      assert(!eden_space->is_empty(), "eden must be non-empty");
      assert(young_gen->virtual_space()->alignment() ==
             old_gen->virtual_space()->alignment(), "alignments do not match");

  {- -------------------------------------------
  (1) UseAdaptiveSizePolicy オプション, 及び UseAdaptiveGCBoundary オプションが指定されていない場合には
      (領域間の境界をずらすことは出来ないので)
      ここでリターン
      ---------------------------------------- -}

      if (!(UseAdaptiveSizePolicy && UseAdaptiveGCBoundary)) {
        return false;
      }

  {- -------------------------------------------
  (1) もし, New 領域と Old 領域の両方が完全に commmit された状態でなければ, 
      (領域間の境界をずらすことは出来ないので)
      ここでリターン.
      ---------------------------------------- -}

      // Both generations must be completely committed.
      if (young_gen->virtual_space()->uncommitted_size() != 0) {
        return false;
      }
      if (old_gen->virtual_space()->uncommitted_size() != 0) {
        return false;
      }

  {- -------------------------------------------
  (1) (変数宣言など)
      (以下の absorb_size が境界の移動量.
       absorb_size は, 現在の Eden 領域の使用量(以下の eden_used)に平均昇格量(以下の promoted)を足したもの 
       (正確には, それを align させたもの)
       平均昇格量を加えているのは, そうしないと次の Minor GC 時の昇格オブジェクトが Old に入りきらず, 
       いきなり Full GC に bail out するのが明らかだから.)
      ---------------------------------------- -}

      // Figure out how much to take from eden.  Include the average amount promoted
      // in the total; otherwise the next young gen GC will simply bail out to a
      // full GC.
      const size_t alignment = old_gen->virtual_space()->alignment();
      const size_t eden_used = eden_space->used_in_bytes();
      const size_t promoted = (size_t)size_policy->avg_promoted()->padded_average();
      const size_t absorb_size = align_size_up(eden_used + promoted, alignment);
      const size_t eden_capacity = eden_space->capacity_in_bytes();

  {- -------------------------------------------
  (1) もし, 境界移動後の Eden 領域の大きさが 0 以下になるようであれば, 
      そんな移動は許されないので, ここでリターン.
      ---------------------------------------- -}

      if (absorb_size >= eden_capacity) {
        return false; // Must leave some space in eden.
      }

  {- -------------------------------------------
  (1) もし, 境界移動後の New 領域の大きさが New 領域の最小サイズを下回るようであれば, 
      そんな移動は許されないので, ここでリターン.
      ---------------------------------------- -}

      const size_t new_young_size = young_gen->capacity_in_bytes() - absorb_size;
      if (new_young_size < young_gen->min_gen_size()) {
        return false; // Respect young gen minimum size.
      }

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

      if (TraceAdaptiveGCBoundary && Verbose) {
        gclog_or_tty->print(" absorbing " SIZE_FORMAT "K:  "
                            "eden " SIZE_FORMAT "K->" SIZE_FORMAT "K "
                            "from " SIZE_FORMAT "K, to " SIZE_FORMAT "K "
                            "young_gen " SIZE_FORMAT "K->" SIZE_FORMAT "K ",
                            absorb_size / K,
                            eden_capacity / K, (eden_capacity - absorb_size) / K,
                            young_gen->from_space()->used_in_bytes() / K,
                            young_gen->to_space()->used_in_bytes() / K,
                            young_gen->capacity_in_bytes() / K, new_young_size / K);
      }

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

      // Fill the unused part of the old gen.
      MutableSpace* const old_space = old_gen->object_space();
      HeapWord* const unused_start = old_space->top();
      size_t const unused_words = pointer_delta(old_space->end(), unused_start);

  {- -------------------------------------------
  (1) もし Old 領域に未使用の領域が残っていれば (= top 位置と end が同じでなければ), 
      CollectedHeap::fill_with_objects() を呼んで
      ダミーのオブジェクトを詰めておく.

      (ただし, CollectedHeap::min_fill_size() 未満の中途半端な領域の場合には, 
       ダミーオブジェクトの詰め様がないので, あきらめてここでリターン)
      ---------------------------------------- -}

      if (unused_words > 0) {
        if (unused_words < CollectedHeap::min_fill_size()) {
          return false;  // If the old gen cannot be filled, must give up.
        }
        CollectedHeap::fill_with_objects(unused_start, unused_words);
      }

      // Take the live data from eden and set both top and end in the old gen to
      // eden top.  (Need to set end because reset_after_change() mangles the region
      // from end to virtual_space->high() in debug builds).
      HeapWord* const new_top = eden_space->top();
      old_gen->virtual_space()->expand_into(young_gen->virtual_space(),
                                            absorb_size);
      young_gen->reset_after_change();
      old_space->set_top(new_top);
      old_space->set_end(new_top);
      old_gen->reset_after_change();

  {- -------------------------------------------
  (1) 拡張した部分についての offset array (object start array) の情報を更新しておく.
      ---------------------------------------- -}

      // Update the object start array for the filler object and the data from eden.
      ObjectStartArray* const start_array = old_gen->start_array();
      for (HeapWord* p = unused_start; p < new_top; p += oop(p)->size()) {
        start_array->allocate_block(p);
      }

  {- -------------------------------------------
  (1) AdaptiveSizePolicy を更新する.
      ---------------------------------------- -}

      // Could update the promoted average here, but it is not typically updated at
      // full GCs and the value to use is unclear.  Something like
      //
      // cur_promoted_avg + absorb_size / number_of_scavenges_since_last_full_gc.

      size_policy->set_bytes_absorbed_from_eden(absorb_size);

  {- -------------------------------------------
  (1) リターン
      ---------------------------------------- -}

      return true;
    }

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