hotspot/src/share/vm/memory/space.hpp
#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \
{- -------------------------------------------
(1) (このマクロでは, bottom() から _end_of_live (これは phase2 中に値を設定) までの領域に対して
ポインタの修正処理を行う.
なお, この処理では LiveRange オブジェクトが使用されている (See: LiveRange))
---------------------------------------- -}
/* adjust all the interior pointers to point at the new locations of objects \
* Used by MarkSweep::mark_sweep_phase3() */ \
\
{- -------------------------------------------
(1) (変数宣言など)
(q は現在処理しているオブジェクトを指すポインタ.
t は処理範囲の終端を示すポインタ.)
---------------------------------------- -}
HeapWord* q = bottom(); \
HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \
\
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \
\
{- -------------------------------------------
(1) (領域の先頭部分には, コンパクションで場所が移動しないオブジェクトの塊が存在していることがある.
(領域の先頭のオブジェクトが is_gc_marked() で false を返すにも関わらず,
_first_dead の指し先がもっと先になっている場合には,
こういう塊が存在しているケース)
これらのオブジェクトは, mark フィールドが oopDesc::init_mark() で初期化された状態になっている.
(See: CompactibleSpace::forward())
このため, これらについては is_gc_marked() による判定は出来ない.
そこで, そういった塊が存在する場合には, 以下の if ブロック内で処理しておく)
---------------------------------------- -}
if (q < t && _first_dead > q && \
!oop(q)->is_gc_marked()) { \
/* 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. */ \
{- -------------------------------------------
(1.1) 先頭から _first_dead までのオブジェクトを処理する.
(oopDesc::adjust_pointers() でポインタを修正し,
次のオブジェクトへとポインタ(q)を進める, という作業の繰り返し)
---------------------------------------- -}
HeapWord* end = _first_dead; \
\
while (q < end) { \
/* I originally tried to conjoin "block_start(q) == q" to the \
* assertion below, but that doesn't work, because you can't \
* accurately traverse previous objects to get to the current one \
* after their pointers (including pointers into permGen) have been \
* updated, until the actual compaction is done. dld, 4/00 */ \
assert(block_is_obj(q), \
"should be at block boundaries, and should be looking at objs"); \
\
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \
\
/* point all the oops to the new location */ \
size_t size = oop(q)->adjust_pointers(); \
size = adjust_obj_size(size); \
\
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \
\
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \
\
q += size; \
} \
\
{- -------------------------------------------
(1.1) _first_dead までたどり着いたら, phase2 の処理により
そこには次の live object の場所を示す LiveRange オブジェクトが埋まっているはずなので,
そのアドレスを取り出す.
(ただし, _first_dead 以降にもう live オブジェクトがない場合 (_first_dead == t の場合) には,
単に q を t に設定するだけ.
この場合, これ以上の処理はもう行われない.)
---------------------------------------- -}
if (_first_dead == t) { \
q = t; \
} else { \
/* $$$ This is funky. Using this to read the previously written \
* LiveRange. See also use below. */ \
q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \
} \
} \
\
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
const intx interval = PrefetchScanIntervalInBytes; \
\
debug_only(HeapWord* prev_q = NULL); \
{- -------------------------------------------
(1) 処理範囲の終端(t)に到達するまで処理を行っていく.
この処理は以下のようにして行う.
* 処理対象の箇所(q)のオブジェクトが生きている間 (= is_gc_marked() が true の場合):
oopDesc::adjust_pointers() でそのオブジェクト内のポインタを修正し,
そのオブジェクトの大きさ分だけポインタ(q)を前に進める.
* dead オブジェクトに到達した場合 (= is_gc_marked() が false の場合):
phase2 の処理により, そこには次の live object の場所を示す
LiveRange オブジェクトが埋まっているはずなので,
そのアドレスまでポインタ(q)を進める.
(これにより, dead オブジェクトが連続している領域を一気にスキップする)
(なお高速化のため, Prefetch::write() で
PrefetchScanIntervalInBytes バイトずつ
メモリをプリフェッチしながら行う)
---------------------------------------- -}
while (q < t) { \
/* prefetch beyond q */ \
Prefetch::write(q, interval); \
if (oop(q)->is_gc_marked()) { \
/* q is alive */ \
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \
/* point all the oops to the new location */ \
size_t size = oop(q)->adjust_pointers(); \
size = adjust_obj_size(size); \
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \
debug_only(prev_q = q); \
q += size; \
} else { \
/* q is not a live object, so its mark should point at the next \
* live object */ \
debug_only(prev_q = q); \
q = (HeapWord*) oop(q)->mark()->decode_pointer(); \
assert(q > prev_q, "we should be moving forward through memory"); \
} \
} \
\
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(q == t, "just checking"); \
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.