hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
なお, CMTask::deal_with_reference() 中で使われている CHECK_BOTH_FINGERS は, 未マークのオブジェクトを見つけたときに local/global の両方を確認するか, それとも global だけ確認するかを制御する. 両方確認した方が正確になるので push する量は減るが, オーバーヘッドも増える. 現在は両方確認する(=1)に #define されている.
// This determines whether the method below will check both the local
// and global fingers when determining whether to push on the stack a
// gray object (value 1) or whether it will only check the global one
// (value 0). The tradeoffs are that the former will be a bit more
// accurate and possibly push less on the stack, but it might also be
// a little bit slower.
#define _CHECK_BOTH_FINGERS_ 1
void CMTask::deal_with_reference(oop obj) {
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] we're dealing with reference = "PTR_FORMAT,
_task_id, (void*) obj);
{- -------------------------------------------
(1)
---------------------------------------- -}
++_refs_reached;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
HeapWord* objAddr = (HeapWord*) obj;
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(obj->is_oop_or_null(true /* ignore mark word */), "Error");
{- -------------------------------------------
(1) もし, 処理対象のオブジェクトが...であり(= is_in_g1_reserved()),
かつまだマークされておらず, かつ TAMS の位置より前に存在している場合,
(マークの必要があるということなので)
CMBitMap::parMark() を呼び出してマークする.
_CHECK_BOTH_FINGERS_ が 1 の場合は, ... であれば push する.
逆に _CHECK_BOTH_FINGERS_ が 0 なら,
対象のオブジェクトのアドレスが global_finger よりも小さければ push する.
(<= これは, (既に処理済みだったら)再調査が必要だと記録するための処理??)
(ついでに(トレース出力)も出している)
---------------------------------------- -}
if (_g1h->is_in_g1_reserved(objAddr)) {
assert(obj != NULL, "is_in_g1_reserved should ensure this");
HeapRegion* hr = _g1h->heap_region_containing(obj);
if (_g1h->is_obj_ill(obj, hr)) {
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] "PTR_FORMAT" is not considered marked",
_task_id, (void*) obj);
// we need to mark it first
if (_nextMarkBitMap->parMark(objAddr)) {
// No OrderAccess:store_load() is needed. It is implicit in the
// CAS done in parMark(objAddr) above
HeapWord* global_finger = _cm->finger();
#if _CHECK_BOTH_FINGERS_
// we will check both the local and global fingers
if (_finger != NULL && objAddr < _finger) {
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] below the local finger ("PTR_FORMAT"), "
"pushing it", _task_id, _finger);
push(obj);
} else if (_curr_region != NULL && objAddr < _region_limit) {
// do nothing
} else if (objAddr < global_finger) {
// Notice that the global finger might be moving forward
// concurrently. This is not a problem. In the worst case, we
// mark the object while it is above the global finger and, by
// the time we read the global finger, it has moved forward
// passed this object. In this case, the object will probably
// be visited when a task is scanning the region and will also
// be pushed on the stack. So, some duplicate work, but no
// correctness problems.
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] below the global finger "
"("PTR_FORMAT"), pushing it",
_task_id, global_finger);
push(obj);
} else {
// do nothing
}
#else // _CHECK_BOTH_FINGERS_
// we will only check the global finger
if (objAddr < global_finger) {
// see long comment above
if (_cm->verbose_high())
gclog_or_tty->print_cr("[%d] below the global finger "
"("PTR_FORMAT"), pushing it",
_task_id, global_finger);
push(obj);
}
#endif // _CHECK_BOTH_FINGERS_
}
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.