Top


定義場所(file name)

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

名前(function name)

void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q,
                                                    uint parallel_gc_threads) {

本体部(body)

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

      TraceTime tm("dense prefix task setup", print_phases(), true, gclog_or_tty);

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

      ParallelCompactData& sd = PSParallelCompact::summary_data();

  {- -------------------------------------------
  (1) 以下の for ループ内で, 各 Space の dense prefix 部分を
      処理する UpdateDensePrefixTask オブジェクトをキューに詰めていく.

      (ただし, dense prefix 量が 0 ならば, その Space に関しては何もしない (というかすることがない))


      各 Space に対して生成される UpdateDensePrefixTask オブジェクトの個数(以下の tasks_for_dense_prefix), 
      及び 1つの UpdateDensePrefixTask で処理する region 数(以下の regions_per_thread) は
      以下の通り.
      (なお, 以下の total_dense_prefix_regions は「dense prefix に含まれる region の個数」, 
       parallel_gc_threads は「引数で指定された GC スレッド数」のこと)

      * total_dense_prefix_regions が parallel_gc_threads よりも小さい場合
        * 生成される UpdateDensePrefixTask オブジェクトの個数 : 
          total_dense_prefix_regions と同数
        * 1つの UpdateDensePrefixTask で処理する region 数  : 
          1 個

      * total_dense_prefix_regions が 「parallel_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING」以下の場合
        * 生成される UpdateDensePrefixTask オブジェクトの個数 : 
          parallel_gc_threads と同数 (半端な残りが出た場合は +1)
        * 1つの UpdateDensePrefixTask で処理する region 数  : 
          total_dense_prefix_regions/parallel_gc_threads  (端数切り捨て)
          (最後の1つについてはこの大きさに満たないこともある)

      * total_dense_prefix_regions が 「parallel_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING」より大きい場合
        * 生成される UpdateDensePrefixTask オブジェクトの個数 : 
          parallel_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING (半端な残りが出た場合は +1)
        * 1つの UpdateDensePrefixTask で処理する region 数  : 
          total_dense_prefix_regions/(parallel_gc_threads*PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING)  (端数切り捨て)
          (最後の1つについてはこの大きさに満たないこともある)
      ---------------------------------------- -}

      // Iterate over all the spaces adding tasks for updating
      // regions in the dense prefix.  Assume that 1 gc thread
      // will work on opening the gaps and the remaining gc threads
      // will work on the dense prefix.
      unsigned int space_id;
      for (space_id = old_space_id; space_id < last_space_id; ++ space_id) {
        HeapWord* const dense_prefix_end = _space_info[space_id].dense_prefix();
        const MutableSpace* const space = _space_info[space_id].space();

    {- -------------------------------------------
  (1.1) dense prefix がなければ, その Space については処理は行わない.
        ---------------------------------------- -}

        if (dense_prefix_end == space->bottom()) {
          // There is no dense prefix for this space.
          continue;
        }

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

        // The dense prefix is before this region.
        size_t region_index_end_dense_prefix =
            sd.addr_to_region_idx(dense_prefix_end);
        RegionData* const dense_prefix_cp =
          sd.region(region_index_end_dense_prefix);
        assert(dense_prefix_end == space->end() ||
               dense_prefix_cp->available() ||
               dense_prefix_cp->claimed(),
               "The region after the dense prefix should always be ready to fill");

        size_t region_index_start = sd.addr_to_region_idx(space->bottom());

        // Is there dense prefix work?
        size_t total_dense_prefix_regions =
          region_index_end_dense_prefix - region_index_start;

    {- -------------------------------------------
  (1.1) (以下の if 式の条件 (total_dense_prefix_regions > 0) が true になるのはどういうケース?? #TODO)
        ---------------------------------------- -}

        // How many regions of the dense prefix should be given to
        // each thread?
        if (total_dense_prefix_regions > 0) {

    {- -------------------------------------------
  (1.1) (tasks_for_dense_prefix 及び regions_per_thread を計算)
        ---------------------------------------- -}

          uint tasks_for_dense_prefix = 1;
          if (total_dense_prefix_regions <=
              (parallel_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING)) {
            // Don't over partition.  This assumes that
            // PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING is a small integer value
            // so there are not many regions to process.
            tasks_for_dense_prefix = parallel_gc_threads;
          } else {
            // Over partition
            tasks_for_dense_prefix = parallel_gc_threads *
              PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING;
          }
          size_t regions_per_thread = total_dense_prefix_regions /
            tasks_for_dense_prefix;
          // Give each thread at least 1 region.
          if (regions_per_thread == 0) {
            regions_per_thread = 1;
          }

    {- -------------------------------------------
  (1.1) tasks_for_dense_prefix 分だけ UpdateDensePrefixTask オブジェクトを生成
        (ただし, dense prefix に含まれるリージョン数が parallel_gc_threads に満たない場合は, 
         そのリージョン数に達したところで終了 
         (以下の region_index_start >= region_index_end_dense_prefix という条件での break))
        ---------------------------------------- -}

          for (uint k = 0; k < tasks_for_dense_prefix; k++) {
            if (region_index_start >= region_index_end_dense_prefix) {
              break;
            }
            // region_index_end is not processed
            size_t region_index_end = MIN2(region_index_start + regions_per_thread,
                                           region_index_end_dense_prefix);
            q->enqueue(new UpdateDensePrefixTask(SpaceId(space_id),
                                                 region_index_start,
                                                 region_index_end));
            region_index_start = region_index_end;
          }
        }

    {- -------------------------------------------
  (1.1) もし半端に残っている region があった場合には, 
        そこを処理する UpdateDensePrefixTask オブジェクトを作っておく.
        ---------------------------------------- -}

        // This gets any part of the dense prefix that did not
        // fit evenly.
        if (region_index_start < region_index_end_dense_prefix) {
          q->enqueue(new UpdateDensePrefixTask(SpaceId(space_id),
                                               region_index_start,
                                               region_index_end_dense_prefix));
        }
      }
    }

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