hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
// world is stopped at this checkpoint
assert(SafepointSynchronize::is_at_safepoint(),
"world should be stopped");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
G1CollectedHeap* g1h = G1CollectedHeap::heap();
{- -------------------------------------------
(1) 並行して Full GC が実行されてしまった場合は
(= ConcurrentMark::has_aborted() が true の場合は),
これ以上 marking 処理を続けても結果は不正なので, ここでリターン.
(ついでに, G1CollectedHeap::set_marking_complete() を呼んで
Concurrent Mark 処理が終了したことが分かるようにしておく.)
---------------------------------------- -}
// If a full collection has happened, we shouldn't do this.
if (has_aborted()) {
g1h->set_marking_complete(); // So bitmap clearing isn't confused
return;
}
{- -------------------------------------------
(1) (DTrace のフック点) (JVMTI のフック点)
(See: SvcGCMarker)
---------------------------------------- -}
SvcGCMarker sgcm(SvcGCMarker::OTHER);
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
if (VerifyDuringGC) {
HandleMark hm; // handle scope
gclog_or_tty->print(" VerifyDuringGC:(before)");
Universe::heap()->prepare_for_verify();
Universe::verify(true, false, true);
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
G1CollectorPolicy* g1p = g1h->g1_policy();
{- -------------------------------------------
(1)
---------------------------------------- -}
g1p->record_concurrent_mark_remark_start();
{- -------------------------------------------
(1) ConcurrentMark::checkpointRootsFinalWork() を呼び出して,
root から辿れるオブジェクトに対して Final marking 処理を行う.
(ついでに, 処理の前後で開始時間/終了時間も計測しているが, これはトレース出力用の処理.)
---------------------------------------- -}
double start = os::elapsedTime();
checkpointRootsFinalWork();
double mark_work_end = os::elapsedTime();
{- -------------------------------------------
(1) 次に, ConcurrentMark::weakRefsWork() を呼び出して,
ConcurrentMark::checkpointRootsFinalWork() 処理中に見つかった
参照オブジェクト(java.lang.ref オブジェクト)の処理を行う.
---------------------------------------- -}
weakRefsWork(clear_all_soft_refs);
{- -------------------------------------------
(1) もし marking 処理が (ConcurrentMark 内のスタックが一杯になったことで) 失敗していた場合は
(= ConcurrentMark::has_overflown() が true の場合は),
_restart_for_overflow フィールドをセットして concurrent marking をもう一度やり直すことにする.
(_restart_for_overflow を true にすると,
ConcurrentMarkThread::run() 内で concurrent marking 処理が再実行される
See: ConcurrentMarkThread::run())
(ついでに, ConcurrentMark::has_overflown() の値はもう消して構わないので,
ConcurrentMark::clear_has_overflown() でリセットしている)
---------------------------------------- -}
if (has_overflown()) {
// Oops. We overflowed. Restart concurrent marking.
_restart_for_overflow = true;
// Clear the flag. We do not need it any more.
clear_has_overflown();
if (G1TraceMarkStackOverflow)
gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
{- -------------------------------------------
(1) marking 処理が成功していた場合は (= ConcurrentMark::has_overflown() が false の場合は),
SATBMarkQueueSet::set_active_all_threads() を呼んで
write barrier を通常時のモード(ポインタを記録しないモード)に戻しておく.
(See: [here](no2114EV0.html) for details)
(ついでに, (トレース出力)も出している)
---------------------------------------- -}
} else {
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
// We're done with marking.
// This is the end of the marking cycle, we're expected all
// threads to have SATB queues with active set to true.
satb_mq_set.set_active_all_threads(false, /* new active value */
true /* expected_active */);
if (VerifyDuringGC) {
HandleMark hm; // handle scope
gclog_or_tty->print(" VerifyDuringGC:(after)");
Universe::heap()->prepare_for_verify();
Universe::heap()->verify(/* allow_dirty */ true,
/* silent */ false,
/* use_prev_marking */ false);
}
assert(!restart_for_overflow(), "sanity");
}
{- -------------------------------------------
(1) marking 処理が成功していた場合は (= restart_for_overflow が false の場合は),
ConcurrentMark::set_non_marking_state() を呼んで
ConcurrentMark の状態をリセットしておく.
(なんで上の if 分の中にまとめていない?? #TODO)
---------------------------------------- -}
// Reset the marking state if marking completed
if (!restart_for_overflow()) {
set_non_marking_state();
}
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
#if VERIFY_OBJS_PROCESSED
_scan_obj_cl.objs_processed = 0;
ThreadLocalObjQueue::objs_enqueued = 0;
#endif
{- -------------------------------------------
(1) (トレース出力用の処理)
(これらのフィールドは現在は以下のパスでのみ参照されている.
before_exit()
-> G1CollectedHeap::print_tracing_info()
-> ConcurrentMark::print_summary_info() (G1SummarizeConcMark オプション指定時のみ))
---------------------------------------- -}
// Statistics
double now = os::elapsedTime();
_remark_mark_times.add((mark_work_end - start) * 1000.0);
_remark_weak_ref_times.add((now - mark_work_end) * 1000.0);
_remark_times.add((now - start) * 1000.0);
{- -------------------------------------------
(1)
---------------------------------------- -}
g1p->record_concurrent_mark_remark_end();
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.