hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
// Update interior oops in the ranges of regions [beg_region, end_region).
void
PSParallelCompact::update_and_deadwood_in_dense_prefix(ParCompactionManager* cm,
SpaceId space_id,
size_t beg_region,
size_t end_region) {
{- -------------------------------------------
(1) (変数宣言など)
(beg_addr は, 処理対象範囲の先頭を指すアドレス. ただし後で微修正される可能性有り.
end_addr は, 処理対象範囲の終端を指すアドレス.)
---------------------------------------- -}
ParallelCompactData& sd = summary_data();
ParMarkBitMap* const mbm = mark_bitmap();
HeapWord* beg_addr = sd.region_to_addr(beg_region);
HeapWord* const end_addr = sd.region_to_addr(end_region);
assert(beg_region <= end_region, "bad region range");
assert(end_addr <= dense_prefix(space_id), "not in the dense prefix");
{- -------------------------------------------
(1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
---------------------------------------- -}
#ifdef ASSERT
// Claim the regions to avoid triggering an assert when they are marked as
// filled.
for (size_t claim_region = beg_region; claim_region < end_region; ++claim_region) {
assert(sd.region(claim_region)->claim_unsafe(), "claim() failed");
}
#endif // #ifdef ASSERT
{- -------------------------------------------
(1) 引数で指定された処理対象範囲の先頭アドレス(beg_addr)は,
たいていの場合オブジェクトの境界とはずれているので,
一番近いオブジェクトの頭出しを行い,
beg_addr をそのオブジェクトの先頭に変更しておく.
(ただし, beg_addr がヒープ領域(Space)の一番先頭(bottom)の場合は,
明らかにオブジェクトの先頭を指しているので, この処理は省略する.)
頭出しは以下のようにして行う.
* 対象の region に partial object がある場合 (RegionData::partial_obj_size() != 0 の場合):
partial object の直後にあわせる (ParallelCompactData::partial_obj_end() で取得)
* 対象の region の先頭を dead object がまたいでいる場合 (PSParallelCompact::dead_space_crosses_boundary() が true の場合):
最初の live オブジェクトの先頭にあわせる (ParMarkBitMap::find_obj_beg() で取得)
* それ以外の場合:
何もしない
---------------------------------------- -}
if (beg_addr != space(space_id)->bottom()) {
// Find the first live object or block of dead space that *starts* in this
// range of regions. If a partial object crosses onto the region, skip it;
// it will be marked for 'deferred update' when the object head is
// processed. If dead space crosses onto the region, it is also skipped; it
// will be filled when the prior region is processed. If neither of those
// apply, the first word in the region is the start of a live object or dead
// space.
assert(beg_addr > space(space_id)->bottom(), "sanity");
const RegionData* const cp = sd.region(beg_region);
if (cp->partial_obj_size() != 0) {
beg_addr = sd.partial_obj_end(beg_region);
} else if (dead_space_crosses_boundary(cp, mbm->addr_to_bit(beg_addr))) {
beg_addr = mbm->find_obj_beg(beg_addr, end_addr);
}
}
{- -------------------------------------------
(1) 処理対象範囲(beg_addr ~ end_addr)を ParMarkBitMap::iterate() で辿る.
この中で UpdateOnlyClosure 及び FillClosure によって
live オブジェクト内のポインタの修正処理, 及び
dead オブジェクトをダミーオブジェクトで上書きする処理を行う.
(ただし, 処理対象範囲が空の場合(= beg_addr と end_addr が一致する場合)には,
何もすることはないので, この処理自体を省略する)
(なお, ParMarkBitMap::iterate() の返値が ParMarkBitMap::incomplete だった場合には,
処理されなかったオブジェクトが残っているということなので (See: ParMarkBitMap::iterate()),
最後に UpdateOnlyClosure::do_addr() を呼び出して
そのオブジェクトの処理も終わらせておく.)
---------------------------------------- -}
if (beg_addr < end_addr) {
// A live object or block of dead space starts in this range of Regions.
HeapWord* const dense_prefix_end = dense_prefix(space_id);
// Create closures and iterate.
UpdateOnlyClosure update_closure(mbm, cm, space_id);
FillClosure fill_closure(cm, space_id);
ParMarkBitMap::IterationStatus status;
status = mbm->iterate(&update_closure, &fill_closure, beg_addr, end_addr,
dense_prefix_end);
if (status == ParMarkBitMap::incomplete) {
update_closure.do_addr(update_closure.source());
}
}
{- -------------------------------------------
(1) 処理が終わったので,
処理範囲に対応する PSParallelCompact::RegionData オブジェクトに対して
PSParallelCompact::RegionData::set_completed() を呼んで,
処理完了の印を付けておく.
---------------------------------------- -}
// Mark the regions as filled.
RegionData* const beg_cp = sd.region(beg_region);
RegionData* const end_cp = sd.region(end_region);
for (RegionData* cp = beg_cp; cp < end_cp; ++cp) {
cp->set_completed();
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.