hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
void work(int i) {
{- -------------------------------------------
(1) もし, 同じタスクを2回以上取得した場合(??)には, することはないのでここでリターン.
(なお _n_workers は G1CollectedHeap::evacuate_collection_set() 内で G1ParTask を生成する際に設定されている.
値は (ParallelGCThreads > 0 ? workers()->total_workers() : 1).
workers()->total_workers() の方は FlexibleWorkGang の生成時に指定される値で, ParallelGCThreads の値に設定されている.
See: G1CollectedHeap::evacuate_collection_set(), SharedHeap::SharedHeap())
---------------------------------------- -}
if (i >= _n_workers) return; // no work needed this round
{- -------------------------------------------
(1) worker が処理を開始した時間(つまり現在時間)を G1CollectorPolicy に記録する.
---------------------------------------- -}
double start_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_start_time(i, start_time_ms);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ResourceMark rm;
HandleMark hm;
{- -------------------------------------------
(1) ?? #TODO
---------------------------------------- -}
G1ParScanThreadState pss(_g1h, i);
G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss);
G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss);
G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss);
{- -------------------------------------------
(1) ?? #TODO
---------------------------------------- -}
pss.set_evac_closure(&scan_evac_cl);
pss.set_evac_failure_closure(&evac_failure_cl);
pss.set_partial_scan_closure(&partial_scan_cl);
{- -------------------------------------------
(1) (変数宣言など)
(これらが実際に Copy 処理を行う Closure 達) ?? #TODO
(G1ParScanHeapRSClosure の only_scan_heap_rs_cl と
G1ParScanAndMarkHeapRSClosure の scan_mark_heap_rs_cl は
使われている箇所が見当たらないが... #TODO)
---------------------------------------- -}
G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss);
G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss);
G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss);
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss);
G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss);
G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss);
OopsInHeapRegionClosure *scan_root_cl;
OopsInHeapRegionClosure *scan_perm_cl;
{- -------------------------------------------
(1) 上記の Closure の中から実際に使用するものを選択.
(Concurrent Marking の実施中かどうかで使用する Closure が異なる.
これは, 実施中であれば mark bit に記入する必要があるため)
---------------------------------------- -}
if (_g1h->g1_policy()->during_initial_mark_pause()) {
scan_root_cl = &scan_mark_root_cl;
scan_perm_cl = &scan_mark_perm_cl;
} else {
scan_root_cl = &only_scan_root_cl;
scan_perm_cl = &only_scan_perm_cl;
}
{- -------------------------------------------
(1) まず, G1CollectedHeap::g1_process_strong_roots() を呼び出して root から参照されているオブジェクトを全て処理する.
(なお, 処理の前後に G1ParScanThreadState::start_strong_roots() と
G1ParScanThreadState::end_strong_roots() を入れ, 処理に掛かった時間を計測している)
---------------------------------------- -}
pss.start_strong_roots();
_g1h->g1_process_strong_roots(/* not collecting perm */ false,
SharedHeap::SO_AllClasses,
scan_root_cl,
&push_heap_rs_cl,
scan_perm_cl,
i);
pss.end_strong_roots();
{- -------------------------------------------
(1) 次に, G1ParEvacuateFollowersClosure::do_void() を呼び出して, 処理したオブジェクトから再帰的にたどれる範囲についても全て処理する.
(なお, 処理の前後で os::elapsedTime() で時間を取得し,
また G1ParScanThreadState::term_time() 内に記録されている情報も使って
コピー処理に掛かった時間(?)と...処理に掛かった時間を算出して
G1CollectorPolicy に記録している.)
---------------------------------------- -}
{
double start = os::elapsedTime();
G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
evac.do_void();
double elapsed_ms = (os::elapsedTime()-start)*1000.0;
double term_ms = pss.term_time()*1000.0;
_g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms);
_g1h->g1_policy()->record_termination(i, term_ms, pss.term_attempts());
}
{- -------------------------------------------
(1) ?? #TODO
---------------------------------------- -}
_g1h->g1_policy()->record_thread_age_table(pss.age_table());
_g1h->update_surviving_young_words(pss.surviving_young_words()+1);
{- -------------------------------------------
(1) HeapRegionRemSet::par_cleanup() を呼んで,
GC 処理中に PosParPRT::par_expand() で確保された PerRegionTable オブジェクトを
全て開放しておく.
(See: PerRegionTable)
---------------------------------------- -}
// Clean up any par-expanded rem sets.
HeapRegionRemSet::par_cleanup();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (ParallelGCVerbose) {
MutexLocker x(stats_lock());
pss.print_termination_stats(i);
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(pss.refs()->is_empty(), "should be empty");
{- -------------------------------------------
(1) worker の処理が終了した時間(つまり現在時間)を G1CollectorPolicy に記録する.
---------------------------------------- -}
double end_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_end_time(i, end_time_ms);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.