hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
void PSParallelCompact::fill_dense_prefix_end(SpaceId id)
{
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
HeapWord* const dense_prefix_end = dense_prefix(id);
const RegionData* region = _summary_data.addr_to_region_ptr(dense_prefix_end);
const idx_t dense_prefix_bit = _mark_bitmap.addr_to_bit(dense_prefix_end);
{- -------------------------------------------
(1) もし dead space が境界をまたがっていない場合
(= PSParallelCompact::dead_space_crosses_boundary() が false の場合) には,
何もしない
---------------------------------------- -}
if (dead_space_crosses_boundary(region, dense_prefix_bit)) {
{- -------------------------------------------
(1) (ここで埋めるダミーオブジェクトは, dense prefix の終端ぎりぎりに
必要最小限の大きさで埋めるものとする.
ただし, ダミーオブジェクトを埋めた後にできる dead space にも
後でダミーオブジェクトを埋められるよう,
最小限のオブジェクトサイズ以下の空き領域が出来ないようにする.
32bit の場合は, ParMarkBitMap の 1bit が 2word に相当するため,
dead space がどんな状態でも終端ぎりぎりにダミーオブジェクトを埋めることが出来る (下図参照).
64bit の場合は, ParMarkBitMap の 1bit が 1word に相当するため,
dead space の状態によって埋め方を変える必要がある
(最小オブジェクトサイズが 2word なので, 下手な埋め方をすると
前のオブジェクトを潰してしまったり,
ダミーオブジェクトを埋められない dead space が出来たりする) (下図参照).
---------------------------------------- -}
// Only enough dead space is filled so that any remaining dead space to the
// left is larger than the minimum filler object. (The remainder is filled
// during the copy/update phase.)
//
// The size of the dead space to the right of the boundary is not a
// concern, since compaction will be able to use whatever space is
// available.
//
// Here '||' is the boundary, 'x' represents a don't care bit and a box
// surrounds the space to be filled with an object.
//
// In the 32-bit VM, each bit represents two 32-bit words:
// +---+
// a) beg_bits: ... x x x | 0 | || 0 x x ...
// end_bits: ... x x x | 0 | || 0 x x ...
// +---+
//
// In the 64-bit VM, each bit represents one 64-bit word:
// +------------+
// b) beg_bits: ... x x x | 0 || 0 | x x ...
// end_bits: ... x x 1 | 0 || 0 | x x ...
// +------------+
// +-------+
// c) beg_bits: ... x x | 0 0 | || 0 x x ...
// end_bits: ... x 1 | 0 0 | || 0 x x ...
// +-------+
// +-----------+
// d) beg_bits: ... x | 0 0 0 | || 0 x x ...
// end_bits: ... 1 | 0 0 0 | || 0 x x ...
// +-----------+
// +-------+
// e) beg_bits: ... 0 0 | 0 0 | || 0 x x ...
// end_bits: ... 0 0 | 0 0 | || 0 x x ...
// +-------+
{- -------------------------------------------
(1) まずは (上図の) a, c, e のケースを想定し,
終端ぎりぎりに CollectedHeap::min_fill_size() 分の大きさのダミーオブジェクトを埋めることにする.
---------------------------------------- -}
// Initially assume case a, c or e will apply.
size_t obj_len = CollectedHeap::min_fill_size();
HeapWord* obj_beg = dense_prefix_end - obj_len;
{- -------------------------------------------
(1) 64bit の場合には, 他のケースを想定する必要がある.
* MinObjAlignment が 1 より大きい場合:
特にすることはない
(オブジェクトの最小サイズが 2 word だから,
2 word 以上でアラインメントされていれば問題は生じない, ということ?? #TODO)
* dense prefix 境界の 2 word 前で終わっている live オブジェクトがいる場合: (b のケース)
そのままだと, そのオブジェクトを踏みつぶしてしまうので,
ダミーオブジェクトを 1 word 分だけ後ろにずらす.
(この場合, dense prefix 境界の後ろに少しはみ出る)
* dense prefix 境界の 4 word 前で終わっている live オブジェクトがいる場合: (d のケース)
そのままだと, ダミーオブジェクトを埋められない (= 1 word 分の大きさしかない) dead space が出来てしまうので,
ダミーオブジェクトを 1 word 分だけ前に伸ばす.
---------------------------------------- -}
#ifdef _LP64
if (MinObjAlignment > 1) { // object alignment > heap word size
// Cases a, c or e.
} else if (_mark_bitmap.is_obj_end(dense_prefix_bit - 2)) {
// Case b above.
obj_beg = dense_prefix_end - 1;
} else if (!_mark_bitmap.is_obj_end(dense_prefix_bit - 3) &&
_mark_bitmap.is_obj_end(dense_prefix_bit - 4)) {
// Case d above.
obj_beg = dense_prefix_end - 3;
obj_len = 3;
}
#endif // #ifdef _LP64
{- -------------------------------------------
(1) CollectedHeap::fill_with_object() でダミーオブジェクトを埋め,
それに併せて _mark_bitmap や _summary_data, start_array の情報を更新しておく.
---------------------------------------- -}
CollectedHeap::fill_with_object(obj_beg, obj_len);
_mark_bitmap.mark_obj(obj_beg, obj_len);
_summary_data.add_obj(obj_beg, obj_len);
assert(start_array(id) != NULL, "sanity");
start_array(id)->allocate_block(obj_beg);
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.