hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
void G1CollectedHeap::evacuate_collection_set() {
{- -------------------------------------------
(1) GC 開始前に _evacuation_failed フィールドを初期化しておく.
---------------------------------------- -}
set_evacuation_failed(false);
{- -------------------------------------------
(1)
---------------------------------------- -}
g1_rem_set()->prepare_for_oops_into_collection_set_do();
{- -------------------------------------------
(1)
---------------------------------------- -}
concurrent_g1_refine()->set_use_cache(false);
concurrent_g1_refine()->clear_hot_cache_claimed_index();
{- -------------------------------------------
(1) G1CollectedHeap::set_par_threads() で
使用する GC スレッド数を登録しておく.
---------------------------------------- -}
int n_workers = (ParallelGCThreads > 0 ? workers()->total_workers() : 1);
set_par_threads(n_workers);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
G1ParTask g1_par_task(this, n_workers, _task_queues);
{- -------------------------------------------
(1)
---------------------------------------- -}
init_for_evac_failure(NULL);
rem_set()->prepare_for_younger_refs_iterate(true);
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
{- -------------------------------------------
(1) (変数宣言など)
(GC 開始時の時刻を記録しておく)
---------------------------------------- -}
double start_par = os::elapsedTime();
{- -------------------------------------------
(1) 実際の GC 処理を行う.
(複数スレッドを使用して並列に行うなら(= G1CollectedHeap::use_parallel_gc_threads() が true なら), WorkGang::run_task() で G1ParTask を並列実行する.
そうでなければ, 直接 G1ParTask::work() を呼び出すだけ.)
---------------------------------------- -}
if (G1CollectedHeap::use_parallel_gc_threads()) {
// The individual threads will set their evac-failure closures.
StrongRootsScope srs(this);
if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
workers()->run_task(&g1_par_task);
} else {
StrongRootsScope srs(this);
g1_par_task.work(0);
}
{- -------------------------------------------
(1) GC に掛かった時間を計算し, g1_policy()->record_par_time() で g1_policy() 内に記録.
---------------------------------------- -}
double par_time = (os::elapsedTime() - start_par) * 1000.0;
g1_policy()->record_par_time(par_time);
{- -------------------------------------------
(1) G1CollectedHeap::set_par_threads() で, GC スレッド数情報をリセットしておく.
---------------------------------------- -}
set_par_threads(0);
{- -------------------------------------------
(1)
---------------------------------------- -}
// Is this the right thing to do here? We don't save marks
// on individual heap regions when we allocate from
// them in parallel, so this seems like the correct place for this.
retire_all_alloc_regions();
{- -------------------------------------------
(1) Weak global JNI references に対して処理を行う.
---------------------------------------- -}
// Weak root processing.
// Note: when JSR 292 is enabled and code blobs can contain
// non-perm oops then we will need to process the code blobs
// here too.
{
G1IsAliveClosure is_alive(this);
G1KeepAliveClosure keep_alive(this);
JNIHandles::weak_oops_do(&is_alive, &keep_alive);
}
{- -------------------------------------------
(1)
---------------------------------------- -}
release_gc_alloc_regions(false /* totally */);
g1_rem_set()->cleanup_after_oops_into_collection_set_do();
concurrent_g1_refine()->clear_hot_cache();
concurrent_g1_refine()->set_use_cache(true);
finalize_for_evac_failure();
// Must do this before removing self-forwarding pointers, which clears
// the per-region evac-failure flags.
concurrent_mark()->complete_marking_in_collection_set();
{- -------------------------------------------
(1) Minor GC が途中で失敗していた場合,
G1CollectedHeap::remove_self_forwarding_pointers() を呼んで
コピーに失敗したオブジェクトの後始末処理を行う
(markbit に生きていると印をつける,
そのオブジェクト内のポインタフィールドから指されている先の Remembered Set を修正する,
saved mark を戻す,
etc)
(ついでに(トレース出力)も出している)
---------------------------------------- -}
if (evacuation_failed()) {
remove_self_forwarding_pointers();
if (PrintGCDetails) {
gclog_or_tty->print(" (to-space overflow)");
} else if (PrintGC) {
gclog_or_tty->print("--");
}
}
{- -------------------------------------------
(1) G1CollectedHeap::dirty_card_queue_set() 内の各 card について
(= 処理が遅延されていた各 card について),
card の dirty 化を行い, JavaThread クラスの _dirty_card_queue_set フィールドにマージしておく.
(ただし develop オプションである G1DeferredRSUpdate がセットされている場合は何もしない)
---------------------------------------- -}
if (G1DeferredRSUpdate) {
RedirtyLoggedCardTableEntryFastClosure redirty;
dirty_card_queue_set().set_closure(&redirty);
dirty_card_queue_set().apply_closure_to_all_completed_buffers();
DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
dcq.merge_bufferlists(&dirty_card_queue_set());
assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
}
{- -------------------------------------------
(1) #ifdef COMPILER2 の場合には, GC が終わったので
見つかった derived pointer の値を修正しておく.
(See: DerivedPointerTable)
---------------------------------------- -}
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.