hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
void PSParallelCompact::marking_phase(ParCompactionManager* cm,
bool maximum_heap_compaction) {
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
// Recursively traverse all live objects and mark them
EventMark m("1 mark object");
TraceTime tm("marking phase", print_phases(), true, gclog_or_tty);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ParallelScavengeHeap* heap = gc_heap();
uint parallel_gc_threads = heap->gc_task_manager()->workers();
TaskQueueSetSuper* qset = ParCompactionManager::region_array();
ParallelTaskTerminator terminator(parallel_gc_threads, qset);
PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
{- -------------------------------------------
(1) (以下のブロックの中で, 全ての生きているオブジェクトに mark を付ける処理を行う)
---------------------------------------- -}
{
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
TraceTime tm_m("par mark", print_phases(), true, gclog_or_tty);
{- -------------------------------------------
(1.1) nmethod 用の前準備をしておく (See: ParallelScavengeHeap::ParStrongRootsScope)
---------------------------------------- -}
ParallelScavengeHeap::ParStrongRootsScope psrs;
{- -------------------------------------------
(1.1) GCTaskQueue::create() で GCTaskQueue を作り,
そこに MarkFromRootsTask や ThreadRootsMarkingTask をつめていく.
---------------------------------------- -}
GCTaskQueue* q = GCTaskQueue::create();
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::universe));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jni_handles));
// We scan the thread roots in parallel
Threads::create_thread_roots_marking_tasks(q);
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::object_synchronizer));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::flat_profiler));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::management));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));
{- -------------------------------------------
(1.1) さらに, ParallelGCThreads 個分だけ StealMarkingTask を追加.
---------------------------------------- -}
if (parallel_gc_threads > 1) {
for (uint j = 0; j < parallel_gc_threads; j++) {
q->enqueue(new StealMarkingTask(&terminator));
}
}
{- -------------------------------------------
(1.1) 最後に, 以上の処理が終了するまで待機するための WaitForBarrierGCTask も追加しておく.
---------------------------------------- -}
WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
q->enqueue(fin);
{- -------------------------------------------
(1.1) GCTaskManager::add_list() で, GCTask をキューに追加して GCTaskThread 達に実行させる.
---------------------------------------- -}
gc_task_manager()->add_list(q);
{- -------------------------------------------
(1.1) WaitForBarrierGCTask::wait_for() で GCTask が全て実行されるまで待機する.
待機が解けたら, WaitForBarrierGCTask::destroy() で WaitForBarrierGCTask オブジェクトを破棄する.
---------------------------------------- -}
fin->wait_for();
// We have to release the barrier tasks!
WaitForBarrierGCTask::destroy(fin);
}
{- -------------------------------------------
(1) (以下のブロックの中で, 上の mark 処理中に見つかった参照オブジェクト(java.lang.ref オブジェクト)の処理を行う)
(See: [here](no289169tf.html) for details)
(なお, 使用する ReferenceProcessor オブジェクトの _processing_is_mt フィールドが
true である場合は, この処理もマルチスレッドで行う.
その場合には AbstractRefProcTaskExecutor として RefProcTaskExecutor が使用される.)
---------------------------------------- -}
// Process reference objects found during marking
{
TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty);
if (ref_processor()->processing_is_mt()) {
RefProcTaskExecutor task_executor;
ref_processor()->process_discovered_references(
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
&task_executor);
} else {
ref_processor()->process_discovered_references(
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL);
}
}
{- -------------------------------------------
(1) (トレース出力)
(これ以降のクラスやコードキャッシュ等のアンロード処理に掛かる時間を出力)
---------------------------------------- -}
TraceTime tm_c("class unloading", print_phases(), true, gclog_or_tty);
{- -------------------------------------------
(1)
---------------------------------------- -}
// Follow system dictionary roots and unload classes.
bool purged_class = SystemDictionary::do_unloading(is_alive_closure());
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
// Follow code cache roots.
CodeCache::do_unloading(is_alive_closure(), &mark_and_push_closure,
purged_class);
cm->follow_marking_stacks(); // Flush marking stack.
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
// Update subklass/sibling/implementor links of live klasses
// revisit_klass_stack is used in follow_weak_klass_links().
follow_weak_klass_links();
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
// Revisit memoized MDO's and clear any unmarked weak refs
follow_mdo_weak_refs();
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
// Visit interned string tables and delete unmarked oops
StringTable::unlink(is_alive_closure());
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
// Clean up unreferenced symbols in symbol table.
SymbolTable::unlink();
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(cm->marking_stacks_empty(), "marking stacks should be empty");
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.