hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(addr != NULL, "Should detect NULL oop earlier");
assert(PSParallelCompact::gc_heap()->is_in(addr), "addr not in heap");
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
#ifdef ASSERT
if (PSParallelCompact::mark_bitmap()->is_unmarked(addr)) {
gclog_or_tty->print_cr("calc_new_pointer:: addr " PTR_FORMAT, addr);
}
#endif
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(PSParallelCompact::mark_bitmap()->is_marked(addr), "obj not marked");
{- -------------------------------------------
(1) まず, 処理対象のオブジェクトが所属しているリージョンの先頭について
コンパクション後のアドレスを取得する (以下の result).
(このために, まず ParallelCompactData::addr_to_region_idx() と
ParallelCompactData::region() で対応する RegionData を取得している.
そして, そこから RegionData::destination() で移動先アドレスを出す.)
---------------------------------------- -}
// Region covering the object.
size_t region_index = addr_to_region_idx(addr);
const RegionData* const region_ptr = region(region_index);
HeapWord* const region_addr = region_align_down(addr);
assert(addr < region_addr + RegionSize, "Region does not cover object");
assert(addr_to_region_ptr(region_addr) == region_ptr, "sanity check");
HeapWord* result = region_ptr->destination();
{- -------------------------------------------
(1) 「リージョン先頭の移動先とオブジェクトの移動先との間の差分」を計算し,
さっき取得したリージョン先頭の移動先に足し込むことで
オブジェクトの移動先アドレスを求める (以下の result).
差分の求め方は2通り.
* 対応するリージョン内に live object しかない場合:
差分は, コンパクション前と変わらない (リージョン先頭からオブジェクトの先頭までの距離)
* そうではない場合:
差分は, 以下の2つの値の合計値.
* (もし存在するなら) リージョンの先頭に存在する partial object の大きさ
(これは RegionData::partial_obj_size() で取得)
* リージョンの先頭(もしくはリージョン先頭の partial object の末尾)から,
処理対象のオブジェクトまでの間の, 全 live object の合計量
(これは ParMarkBitMap::live_words_in_range() で取得)
どちらの場合も, 最終的には求めた移動先をリターン.
---------------------------------------- -}
// If all the data in the region is live, then the new location of the object
// can be calculated from the destination of the region plus the offset of the
// object in the region.
if (region_ptr->data_size() == RegionSize) {
result += pointer_delta(addr, region_addr);
DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result);)
return result;
}
// The new location of the object is
// region destination +
// size of the partial object extending onto the region +
// sizes of the live objects in the Region that are to the left of addr
const size_t partial_obj_size = region_ptr->partial_obj_size();
HeapWord* const search_start = region_addr + partial_obj_size;
const ParMarkBitMap* bitmap = PSParallelCompact::mark_bitmap();
size_t live_to_left = bitmap->live_words_in_range(search_start, oop(addr));
result += partial_obj_size + live_to_left;
DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result);)
return result;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.