hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp
void PSMarkSweepDecorator::compact(bool mangle_free_space ) {
{- -------------------------------------------
(1) (ここのコメントまで含めて SCAN_AND_COMPACT からコピペ??)
---------------------------------------- -}
// Copy all live objects to their new location
// Used by MarkSweep::mark_sweep_phase4()
{- -------------------------------------------
(1) (この関数では, bottom() から _end_of_live (これは phase2 中に値を設定) までの領域に対して
オブジェクトの移動処理を行う.
なお, この処理では LiveRange オブジェクトが使用されている (See: LiveRange))
---------------------------------------- -}
{- -------------------------------------------
(1) (変数宣言など)
(q は現在処理しているオブジェクトを指すポインタ.
t は処理範囲の終端を示すポインタ.)
---------------------------------------- -}
HeapWord* q = space()->bottom();
HeapWord* const t = _end_of_live;
debug_only(HeapWord* prev_q = NULL);
{- -------------------------------------------
(1) (領域の先頭部分には, コンパクションで場所が移動しないオブジェクトの塊が存在していることがある.
(領域の先頭のオブジェクトが is_gc_marked() で false を返すにも関わらず,
_first_dead の指し先がもっと先になっている場合には,
こういう塊が存在しているケース)
(See: PSMarkSweepDecorator::precompact())
これらのオブジェクトは, 場所が移動しないので, phase4 で行うべき処理はない.
そこで, そういった塊が存在する場合には,
以下の if ブロック内でその部分をスキップする.)
---------------------------------------- -}
if (q < t && _first_dead > q &&
!oop(q)->is_gc_marked()) {
#ifdef ASSERT
// we have a chunk of the space which hasn't moved and we've reinitialized the
// mark word during the previous pass, so we can't use is_gc_marked for the
// traversal.
HeapWord* const end = _first_dead;
while (q < end) {
size_t size = oop(q)->size();
assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)");
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q));
debug_only(prev_q = q);
q += size;
}
#endif
if (_first_dead == t) {
q = t;
} else {
// $$$ Funky
q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer();
}
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
const intx scan_interval = PrefetchScanIntervalInBytes;
const intx copy_interval = PrefetchCopyIntervalInBytes;
{- -------------------------------------------
(1) 処理範囲の終端(t)に到達するまで, 次の while ループを繰り返して, 処理を行っていく.
このループ内では以下のような処理を行う.
* dead オブジェクトに到達した場合 (= is_gc_marked() が false の場合):
phase2 の処理により, そこには次の live object の場所を示す
LiveRange オブジェクトが埋まっているはずなので,
そのアドレスまでポインタ(q)を進める.
(これにより, dead オブジェクトばかりが続く領域は一気にスキップし,
ループの次の週では次の live オブジェクトに対する処理が始まる)
* 処理対象の箇所(q)のオブジェクトが生きている間 (= is_gc_marked() が true の場合):
Copy::aligned_conjoint_words() でそのオブジェクトをコンパクション先にコピーし,
oopDesc::init_mark() で, そのオブジェクトの mark フィールドを初期状態の値にリセットする.
その後, そのオブジェクトの大きさ分だけポインタ(q)を前に進める.
(これにより, ループの次の週では, 次のオブジェクトに対する処理が始まる)
(なお高速化のため, Prefetch::read() と Prefetch::write() で
それぞれ PrefetchScanIntervalInBytes バイト, 及び PrefetchCopyIntervalInBytes バイトずつ
メモリをプリフェッチしながら行う)
---------------------------------------- -}
while (q < t) {
if (!oop(q)->is_gc_marked()) {
// mark is pointer to next marked oop
debug_only(prev_q = q);
q = (HeapWord*) oop(q)->mark()->decode_pointer();
assert(q > prev_q, "we should be moving forward through memory");
} else {
// prefetch beyond q
Prefetch::read(q, scan_interval);
// size and destination
size_t size = oop(q)->size();
HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee();
// prefetch beyond compaction_top
Prefetch::write(compaction_top, copy_interval);
// copy object and reinit its mark
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, compaction_top));
assert(q != compaction_top, "everything in this pass should be moving");
Copy::aligned_conjoint_words(q, compaction_top, size);
oop(compaction_top)->init_mark();
assert(oop(compaction_top)->klass() != NULL, "should have a class");
debug_only(prev_q = q);
q += size;
}
}
{- -------------------------------------------
(1) オブジェクトの移動処理が終わったので, コンパクション先の領域の top 位置を修正しておく.
---------------------------------------- -}
assert(compaction_top() >= space()->bottom() && compaction_top() <= space()->end(),
"should point inside space");
space()->set_top(compaction_top());
{- -------------------------------------------
(1) (デバッグ用の処理)
(もし引数で mangle 処理をするように指定されていた場合,
MutableSpace::mangle_unused_area() で
非使用の領域を書き潰しておく)
---------------------------------------- -}
if (mangle_free_space) {
space()->mangle_unused_area();
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.