hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q,
uint parallel_gc_threads) {
{- -------------------------------------------
(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.