hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
// This method contains no policy. You should probably
// be calling invoke() instead.
bool PSScavenge::invoke_no_policy() {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
assert(_preserved_mark_stack.is_empty(), "should be empty");
assert(_preserved_oop_stack.is_empty(), "should be empty");
{- -------------------------------------------
(1) (変数宣言など)
(これらはトレース出力用のために使われる)
---------------------------------------- -}
TimeStamp scavenge_entry;
TimeStamp scavenge_midpoint;
TimeStamp scavenge_exit;
{- -------------------------------------------
(1) (トレース出力用の処理)
(GC 開始時の時刻を計測しておく)
---------------------------------------- -}
scavenge_entry.update();
{- -------------------------------------------
(1) もし GC_locker によって GC が禁止されていれば, ここでリターン.
---------------------------------------- -}
if (GC_locker::check_active_before_gc()) {
return false;
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
GCCause::Cause gc_cause = heap->gc_cause();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
{- -------------------------------------------
(1) PSScavenge::should_attempt_scavenge() で, Scavenge GC でいいかどうかを確認する.
もし Scavenge GC では駄目そうなら, ここでリターン.
---------------------------------------- -}
// Check for potential problems.
if (!should_attempt_scavenge()) {
return false;
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
bool promotion_failure_occurred = false;
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
PSAdaptiveSizePolicy* size_policy = heap->size_policy();
{- -------------------------------------------
(1) GC を行うことになったので, CollectedHeap::total_collections() の値を増加させておく.
(See: CollectedHeap::total_collections())
---------------------------------------- -}
heap->increment_total_collections();
{- -------------------------------------------
(1) (トレース出力) (See: AdaptiveSizePolicyOutput)
---------------------------------------- -}
AdaptiveSizePolicyOutput(size_policy, heap->total_collections());
{- -------------------------------------------
(1) MutableSpace::accumulate_statistics() で, 統計情報を更新しておく
(ただし, java.lang.System.gc() で起こされた GC の場合には,
UseAdaptiveSizePolicyWithSystemGC オプションが指定されていないと
この更新処理は行われない)
---------------------------------------- -}
if ((gc_cause != GCCause::_java_lang_system_gc) ||
UseAdaptiveSizePolicyWithSystemGC) {
// Gather the feedback data for eden occupancy.
young_gen->eden_space()->accumulate_statistics();
}
{- -------------------------------------------
(1) #TODO(デバッグ用の処理)?
(ZapUnusedHeapArea オプションが指定されている場合は GC 後にゴミになった領域を明示的に破壊するが,
その際に少しでも処理時間が短くなるよう, GC 開始時点でどこまで使っていたかを記録しておく処理?
(GC 開始時点で未使用だった領域は既に破壊されているので改めて破壊し直す必要は無いため?))
---------------------------------------- -}
if (ZapUnusedHeapArea) {
// Save information needed to minimize mangling
heap->record_gen_tops_before_GC();
}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintHeapAtGC) {
Universe::print_heap_before_gc();
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(!NeverTenure || _tenuring_threshold == markOopDesc::max_age + 1, "Sanity");
assert(!AlwaysTenure || _tenuring_threshold == 0, "Sanity");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
size_t prev_used = heap->used();
assert(promotion_failed() == false, "Sanity");
{- -------------------------------------------
(1) ParallelScavengeHeap::accumulate_statistics_all_tlabs() で, TLAB 関係の統計情報を更新しておく.
---------------------------------------- -}
// Fill in TLABs
heap->accumulate_statistics_all_tlabs();
{- -------------------------------------------
(1) GC 処理の前に各 TLAB に残っている未使用領域を埋めて
オブジェクトでひとつながりの状態にしておく (GC アルゴリズムを簡単にするため).
---------------------------------------- -}
heap->ensure_parsability(true); // retire TLABs
{- -------------------------------------------
(1) (verify) #TODO
---------------------------------------- -}
if (VerifyBeforeGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
gclog_or_tty->print(" VerifyBeforeGC:");
Universe::verify(true);
}
{
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ResourceMark rm;
HandleMark hm;
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
TraceTime t1("GC", PrintGC, !PrintGCDetails, gclog_or_tty);
TraceCollectorStats tcs(counters());
{- -------------------------------------------
(1) (トレース出力用の処理) (DTrace のフック点) (JMM のフック点)
(See: TraceMemoryManagerStats)
---------------------------------------- -}
TraceMemoryManagerStats tms(false /* not full GC */,gc_cause);
{- -------------------------------------------
(1) (トレース出力用の処理)
(New 領域の GC にかかった時間を記録)
---------------------------------------- -}
if (TraceGen0Time) accumulated_time()->start();
{- -------------------------------------------
(1) AdaptiveSizePolicy を更新する
(ここから先が GC 処理の時間になるので,
AdaptiveSizePolicy::minor_collection_begin() を呼んで
PSAdaptiveSizePolicy オブジェクト内の非GC時間情報を更新)
---------------------------------------- -}
// Let the size policy know we're starting
size_policy->minor_collection_begin();
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
// Verify the object start arrays.
if (VerifyObjectStartArray &&
VerifyBeforeGC) {
old_gen->verify_object_start_array();
perm_gen->verify_object_start_array();
}
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
// Verify no unmarked old->young roots
if (VerifyRememberedSets) {
CardTableExtension::verify_all_young_refs_imprecise();
}
{- -------------------------------------------
(1) ScavengeWithObjectsInToSpace オプションが指定されていなければ,
(これは To スペースにオブジェクトが入っている状態で scavenge を許可するかどうか, というオプション)
MutableSpace::clear() で To space の top を空の位置(bottom())に戻しておく.
(なお, ZapUnusedHeapArea オプションが指定されていれば, To space 内の mangle 処理も行っている模様)
---------------------------------------- -}
if (!ScavengeWithObjectsInToSpace) {
assert(young_gen->to_space()->is_empty(),
"Attempt to scavenge with live objects in to_space");
young_gen->to_space()->clear(SpaceDecorator::Mangle);
{- -------------------------------------------
(1) (なお, ScavengeWithObjectsInToSpace オプションが指定されていても
ZapUnusedHeapArea オプションが指定されていれば, To space 内の mangle 処理は行う)
---------------------------------------- -}
} else if (ZapUnusedHeapArea) {
young_gen->to_space()->mangle_unused_area();
}
{- -------------------------------------------
(1) PSScavenge::_to_space_top_before_gc フィールドに現在の使用量(現在の top 位置)を記録しておく.
---------------------------------------- -}
save_to_space_top_before_gc();
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
NOT_PRODUCT(reference_processor()->verify_no_references_recorded());
{- -------------------------------------------
(1) #ifdef COMPILER2 の場合には, (これから GC を行うので) DerivedPointerTable の値をリセットしておく.
(See: DerivedPointerTable)
---------------------------------------- -}
COMPILER2_PRESENT(DerivedPointerTable::clear());
{- -------------------------------------------
(1) これから GC を行うので, ReferenceProcessor オブジェクトをリセットしておく.
---------------------------------------- -}
reference_processor()->enable_discovery();
reference_processor()->setup_policy(false);
{- -------------------------------------------
(1) (変数宣言など)
(old 及び young 領域の現在の使用量を記録しておく)
---------------------------------------- -}
// We track how much was promoted to the next generation for
// the AdaptiveSizePolicy.
size_t old_gen_used_before = old_gen->used_in_bytes();
// For PrintGCDetails
size_t young_gen_used_before = young_gen->used_in_bytes();
{- -------------------------------------------
(1) これから GC を行うので, 「survivor があふれたかどうか」の情報をリセットしておく
---------------------------------------- -}
// Reset our survivor overflow.
set_survivor_overflow(false);
{- -------------------------------------------
(1) (変数宣言など)
(old 及び perm 領域の現在の top 位置を記録しておく)
---------------------------------------- -}
// We need to save the old/perm top values before
// creating the promotion_manager. We pass the top
// values to the card_table, to prevent it from
// straying into the promotion labs.
HeapWord* old_top = old_gen->object_space()->top();
HeapWord* perm_top = perm_gen->object_space()->top();
{- -------------------------------------------
(1) GCTaskManager::release_all_resources() を呼ぶ.
(これにより, 全ての Worker Thread において
GCTaskManager::should_release_resources() が true を返すようになり,
次回の Worker Thread によるタスク処理時にリソースの解放処理も行われる.
See: GCTaskManager::should_release_resources())
---------------------------------------- -}
// Release all previously held resources
gc_task_manager()->release_all_resources();
{- -------------------------------------------
(1) これから GC を行うので, PSPromotionManager の設定をリセットしておく.
---------------------------------------- -}
PSPromotionManager::pre_scavenge();
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// We'll use the promotion manager again later.
PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager();
{- -------------------------------------------
(1) (以下のブロック内が実際の Scavenge GC の処理)
---------------------------------------- -}
{
{- -------------------------------------------
(1.1) nmethod 用の前準備をしておく (See: ParallelScavengeHeap::ParStrongRootsScope)
---------------------------------------- -}
// TraceTime("Roots");
ParallelScavengeHeap::ParStrongRootsScope psrs;
{- -------------------------------------------
(1.1) GCTask を積めるキューを生成.
---------------------------------------- -}
GCTaskQueue* q = GCTaskQueue::create();
{- -------------------------------------------
(1.1) まず「Old 領域から Young 領域を指しているポインタの Scavenge 処理」をキューに登録.
(これは ParallelGCThreads 個分だけ登録)
---------------------------------------- -}
for(uint i=0; i<ParallelGCThreads; i++) {
q->enqueue(new OldToYoungRootsTask(old_gen, old_top, i));
}
{- -------------------------------------------
(1.1) 「Perm 領域から Young 領域を指しているポインタの Scavenge 処理」をキューに登録.
---------------------------------------- -}
q->enqueue(new SerialOldToYoungRootsTask(perm_gen, perm_top));
{- -------------------------------------------
(1.1) 「Universe オブジェクト内から Young 領域を指しているポインタの Scavenge 処理」をキューに登録.
---------------------------------------- -}
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::universe));
{- -------------------------------------------
(1.1) 「JNI Handle から Young 領域を指しているポインタの Scavenge 処理」をキューに登録.
---------------------------------------- -}
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jni_handles));
{- -------------------------------------------
(1.1) Threads::create_thread_roots_tasks() で「各 JavaThread の root の処理」をキューに登録.
(登録される GCTask の種類は ThreadRootsTask)
---------------------------------------- -}
// We scan the thread roots in parallel
Threads::create_thread_roots_tasks(q);
{- -------------------------------------------
(1.1) その他, root となる箇所からの Scavenge 処理をキューに登録.
---------------------------------------- -}
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::object_synchronizer));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::flat_profiler));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::management));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::system_dictionary));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache));
{- -------------------------------------------
(1.1) 最後に, ParallelGCThreads 個分だけ StealTask を追加.
---------------------------------------- -}
ParallelTaskTerminator terminator(
gc_task_manager()->workers(),
(TaskQueueSetSuper*) promotion_manager->stack_array_depth());
if (ParallelGCThreads>1) {
for (uint j=0; j<ParallelGCThreads; j++) {
q->enqueue(new StealTask(&terminator));
}
}
{- -------------------------------------------
(1.1) GCTaskManager::execute_and_wait() で, 以上の GCTask を GCTaskThread 達に実行させる.
---------------------------------------- -}
gc_task_manager()->execute_and_wait(q);
}
{- -------------------------------------------
(1) (トレース出力用の処理)
(この段階での時刻を計測しておく)
---------------------------------------- -}
scavenge_midpoint.update();
{- -------------------------------------------
(1) 次に, さっきの scavenge 処理中に見つかった参照オブジェクト(java.lang.ref オブジェクト)の処理を行う.
(See: [here](no289169tf.html) for details)
(なお, 使用する ReferenceProcessor オブジェクトの _processing_is_mt フィールドが
true である場合は, この処理もマルチスレッドで行う.
その場合には AbstractRefProcTaskExecutor として PSRefProcTaskExecutor が使用される.)
---------------------------------------- -}
{- -------------------------------------------
(1.1) まず, ReferenceProcessor::process_discovered_references() を呼び出して
差し先が生きている参照オブジェクトをリストから除外する.
---------------------------------------- -}
// Process reference objects discovered during scavenge
{
reference_processor()->setup_policy(false); // not always_clear
PSKeepAliveClosure keep_alive(promotion_manager);
PSEvacuateFollowersClosure evac_followers(promotion_manager);
if (reference_processor()->processing_is_mt()) {
PSRefProcTaskExecutor task_executor;
reference_processor()->process_discovered_references(
&_is_alive_closure, &keep_alive, &evac_followers, &task_executor);
} else {
reference_processor()->process_discovered_references(
&_is_alive_closure, &keep_alive, &evac_followers, NULL);
}
}
{- -------------------------------------------
(1.1) 次に, ReferenceProcessor::enqueue_discovered_references() で
リストに残った参照オブジェクト(= 差し先が死んだため特殊な処理が必要な参照オブジェクト)を pending list に追加する.
---------------------------------------- -}
// Enqueue reference objects discovered during scavenge.
if (reference_processor()->processing_is_mt()) {
PSRefProcTaskExecutor task_executor;
reference_processor()->enqueue_discovered_references(&task_executor);
} else {
reference_processor()->enqueue_discovered_references(NULL);
}
{- -------------------------------------------
(1) StringTable 内の文字列(interned string)についても, StringTable::unlink() でゴミであるものは回収しておく.
(ついでに, StringTable::oops_do() で, 生きている interned string に対するポインタを修正しておく(??) #TODO)
(ただし, これらの処理は, StringTable に含まれる interned string が Perm 領域内に確保される場合は行われない.
See: JavaObjectsInPerm)
(<= Perm 領域に確保されている場合は, PSScavenge によってゴミになったり位置が変わったりするわけはないので,
これらの処理を行う意味は無い(??) #TODO)
---------------------------------------- -}
if (!JavaObjectsInPerm) {
// Unlink any dead interned Strings
StringTable::unlink(&_is_alive_closure);
// Process the remaining live ones
PSScavengeRootsClosure root_closure(promotion_manager);
StringTable::oops_do(&root_closure);
}
{- -------------------------------------------
(1) この段階で scavenge 処理は終了になるので, PSPromotionManager 用のメモリを解放する.
---------------------------------------- -}
// Finally, flush the promotion_manager's labs, and deallocate its stacks.
PSPromotionManager::post_scavenge();
{- -------------------------------------------
(1) もし GC が途中で失敗していたら,
(この後 Full GC を行うことになるので)
PSScavenge::clean_up_failed_promotion() を呼んで Full GC が行える状態にしておく
(失敗していた場合には, あわせて(トレース出力)も行っている)
---------------------------------------- -}
promotion_failure_occurred = promotion_failed();
if (promotion_failure_occurred) {
clean_up_failed_promotion();
if (PrintGC) {
gclog_or_tty->print("--");
}
}
{- -------------------------------------------
(1) AdaptiveSizePolicy を更新する
(ここまでが GC の処理時間なので
AdaptiveSizePolicy::minor_collection_end() を呼んで,
PSAdaptiveSizePolicy オブジェクト内の GC 時間情報を更新する)
---------------------------------------- -}
// Let the size policy know we're done. Note that we count promotion
// failure cleanup time as part of the collection (otherwise, we're
// implicitly saying it's mutator time).
size_policy->minor_collection_end(gc_cause);
{- -------------------------------------------
(1) (もし GC が成功していれば, 以下のブロック内で後始末を行う)
---------------------------------------- -}
if (!promotion_failure_occurred) {
// Swap the survivor spaces.
{- -------------------------------------------
(1.1) MutableSpace::clear() で Eden 領域と From 領域の top 位置を空の位置(= bottom())に戻す.
(なお, ZapUnusedHeapArea オプションが指定されていれば,
MutableSpace::clear() 内では未使用になった領域の mangle 処理も行っている模様)
---------------------------------------- -}
young_gen->eden_space()->clear(SpaceDecorator::Mangle);
young_gen->from_space()->clear(SpaceDecorator::Mangle);
{- -------------------------------------------
(1.1) PSYoungGen::swap_spaces() で To 領域と From 領域を入れ替える.
---------------------------------------- -}
young_gen->swap_spaces();
{- -------------------------------------------
(1.1) AdaptiveSizePolicy を更新する
(PSAdaptiveSizePolicy::update_averages() を呼んで, 平均survived量を更新)
---------------------------------------- -}
size_t survived = young_gen->from_space()->used_in_bytes();
size_t promoted = old_gen->used_in_bytes() - old_gen_used_before;
size_policy->update_averages(_survivor_overflow, survived, promoted);
{- -------------------------------------------
(1.1) GC が成功したので, gc_overhead_limit_count の値は 0 にリセットしておく.
(See: UseGCOverheadLimit)
---------------------------------------- -}
// A successful scavenge should restart the GC time limit count which is
// for full GC's.
size_policy->reset_gc_overhead_limit_count();
{- -------------------------------------------
(1.1) (UseAdaptiveSizePolicy オプションが指定されている場合は,
以下のブロック内で GC に関するパラメータ(各ヒープ長及び昇格閾値)を調整する.
See: GC Ergonomics)
---------------------------------------- -}
if (UseAdaptiveSizePolicy) {
// Calculate the new survivor size and tenuring threshold
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
if (PrintAdaptiveSizePolicy) {
gclog_or_tty->print("AdaptiveSizeStart: ");
gclog_or_tty->stamp();
gclog_or_tty->print_cr(" collection: %d ",
heap->total_collections());
if (Verbose) {
gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d"
" perm_gen_capacity: %d ",
old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes(),
perm_gen->capacity_in_bytes());
}
}
{- -------------------------------------------
(1.1.1) (プロファイル情報の記録) (See: PSGCAdaptivePolicyCounters)
---------------------------------------- -}
if (UsePerfData) {
PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters();
counters->update_old_eden_size(
size_policy->calculated_eden_size_in_bytes());
counters->update_old_promo_size(
size_policy->calculated_promo_size_in_bytes());
counters->update_old_capacity(old_gen->capacity_in_bytes());
counters->update_young_capacity(young_gen->capacity_in_bytes());
counters->update_survived(survived);
counters->update_promoted(promoted);
counters->update_survivor_overflowed(_survivor_overflow);
}
{- -------------------------------------------
(1.1.1) PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold() で,
最適な昇格閾値(tenuring threshold)を計算する.
---------------------------------------- -}
size_t survivor_limit =
size_policy->max_survivor_size(young_gen->max_size());
_tenuring_threshold =
size_policy->compute_survivor_space_size_and_threshold(
_survivor_overflow,
_tenuring_threshold,
survivor_limit);
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
if (PrintTenuringDistribution) {
gclog_or_tty->cr();
gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %d (max %d)",
size_policy->calculated_survivor_size_in_bytes(),
_tenuring_threshold, MaxTenuringThreshold);
}
{- -------------------------------------------
(1.1.1) (プロファイル情報の記録) (See: PSGCAdaptivePolicyCounters)
---------------------------------------- -}
if (UsePerfData) {
PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters();
counters->update_tenuring_threshold(_tenuring_threshold);
counters->update_survivor_size_counters();
}
{- -------------------------------------------
(1.1.1) UseAdaptiveGenerationSizePolicyAtMinorCollection オプションが指定されている場合には,
PSAdaptiveSizePolicy::compute_generation_free_space() で最適なヒープ長を計算し,
ParallelScavengeHeap::resize_young_gen() で実際にヒープ長を調整する.
(ただし, java.lang.System.gc() で起こされた GC の場合には,
UseAdaptiveSizePolicyWithSystemGC オプションも指定されていないと
この調整は行われない)
---------------------------------------- -}
// Do call at minor collections?
// Don't check if the size_policy is ready at this
// level. Let the size_policy check that internally.
if (UseAdaptiveSizePolicy &&
UseAdaptiveGenerationSizePolicyAtMinorCollection &&
((gc_cause != GCCause::_java_lang_system_gc) ||
UseAdaptiveSizePolicyWithSystemGC)) {
// Calculate optimial free space amounts
assert(young_gen->max_size() >
young_gen->from_space()->capacity_in_bytes() +
young_gen->to_space()->capacity_in_bytes(),
"Sizes of space in young gen are out-of-bounds");
size_t max_eden_size = young_gen->max_size() -
young_gen->from_space()->capacity_in_bytes() -
young_gen->to_space()->capacity_in_bytes();
size_policy->compute_generation_free_space(young_gen->used_in_bytes(),
young_gen->eden_space()->used_in_bytes(),
old_gen->used_in_bytes(),
perm_gen->used_in_bytes(),
young_gen->eden_space()->capacity_in_bytes(),
old_gen->max_gen_size(),
max_eden_size,
false /* full gc*/,
gc_cause,
heap->collector_policy());
}
// Resize the young generation at every collection
// even if new sizes have not been calculated. This is
// to allow resizes that may have been inhibited by the
// relative location of the "to" and "from" spaces.
// Resizing the old gen at minor collects can cause increases
// that don't feed back to the generation sizing policy until
// a major collection. Don't resize the old gen here.
heap->resize_young_gen(size_policy->calculated_eden_size_in_bytes(),
size_policy->calculated_survivor_size_in_bytes());
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
if (PrintAdaptiveSizePolicy) {
gclog_or_tty->print_cr("AdaptiveSizeStop: collection: %d ",
heap->total_collections());
}
{- -------------------------------------------
(1.1) (ここまでが GC パラメータの調整処理 (GC Ergonomics 処理))
---------------------------------------- -}
}
{- -------------------------------------------
(1.1) NUMA 構成を考慮した Eden の配置最適化を行う
(See: MutableNUMASpace::update(), MutableSpace::update())
---------------------------------------- -}
// Update the structure of the eden. With NUMA-eden CPU hotplugging or offlining can
// cause the change of the heap layout. Make sure eden is reshaped if that's the case.
// Also update() will case adaptive NUMA chunk resizing.
assert(young_gen->eden_space()->is_empty(), "eden space should be empty now");
young_gen->eden_space()->update();
{- -------------------------------------------
(1.1) PSGCAdaptivePolicyCounters::update_counters() で(プロファイル情報の記録) (See: PSGCAdaptivePolicyCounters)
---------------------------------------- -}
heap->gc_policy_counters()->update_counters();
{- -------------------------------------------
(1.1) ParallelScavengeHeap::resize_all_tlabs() で, 各スレッドの TLAB の大きさを最適に調整しておく.
---------------------------------------- -}
heap->resize_all_tlabs();
{- -------------------------------------------
(1.1) (assert)
---------------------------------------- -}
assert(young_gen->to_space()->is_empty(), "to space should be empty now");
{- -------------------------------------------
(1) (ここまでが, GC が成功した場合の処理)
---------------------------------------- -}
}
{- -------------------------------------------
(1) GC が終わったので, 見つかった derived pointer の値を修正しておく.
(See: DerivedPointerTable)
---------------------------------------- -}
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
NOT_PRODUCT(reference_processor()->verify_no_references_recorded());
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
// Re-verify object start arrays
if (VerifyObjectStartArray &&
VerifyAfterGC) {
old_gen->verify_object_start_array();
perm_gen->verify_object_start_array();
}
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
// Verify all old -> young cards are now precise
if (VerifyRememberedSets) {
// Precise verification will give false positives. Until this is fixed,
// use imprecise verification.
// CardTableExtension::verify_all_young_refs_precise();
CardTableExtension::verify_all_young_refs_imprecise();
}
{- -------------------------------------------
(1) (トレース出力用の処理)
---------------------------------------- -}
if (TraceGen0Time) accumulated_time()->stop();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintGC) {
if (PrintGCDetails) {
// Don't print a GC timestamp here. This is after the GC so
// would be confusing.
young_gen->print_used_change(young_gen_used_before);
}
heap->print_heap_change(prev_used);
}
{- -------------------------------------------
(1) (プロファイル情報の記録)(JMM 用) (See: MemoryUsage)
及び (JMM のフック点) でもある (See: LowMemoryDetector)
---------------------------------------- -}
// Track memory usage and detect low memory
MemoryService::track_memory_usage();
{- -------------------------------------------
(1) ParallelScavengeHeap::update_counters()を呼んで, (プロファイル情報の記録)を行う.
(See: SpaceCounter, PSGenerationCounters)
---------------------------------------- -}
heap->update_counters();
}
{- -------------------------------------------
(1) (verify)
---------------------------------------- -}
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
gclog_or_tty->print(" VerifyAfterGC:");
Universe::verify(false);
}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintHeapAtGC) {
Universe::print_heap_after_gc();
}
{- -------------------------------------------
(1) #TODO(デバッグ用の処理)?
(ZapUnusedHeapArea オプションが指定されている場合は ...)
---------------------------------------- -}
if (ZapUnusedHeapArea) {
young_gen->eden_space()->check_mangled_unused_area_complete();
young_gen->from_space()->check_mangled_unused_area_complete();
young_gen->to_space()->check_mangled_unused_area_complete();
}
{- -------------------------------------------
(1) (トレース出力用の処理)
(GC 終了時の時刻を計測しておく)
---------------------------------------- -}
scavenge_exit.update();
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintGCTaskTimeStamps) {
tty->print_cr("VM-Thread " INT64_FORMAT " " INT64_FORMAT " " INT64_FORMAT,
scavenge_entry.ticks(), scavenge_midpoint.ticks(),
scavenge_exit.ticks());
gc_task_manager()->print_task_time_stamps();
}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
#ifdef TRACESPINNING
ParallelTaskTerminator::print_termination_counts();
#endif
{- -------------------------------------------
(1) 結果をリターン
---------------------------------------- -}
return !promotion_failure_occurred;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.