hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
void PSParallelCompact::post_compact()
{
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
TraceTime tm("post compact", print_phases(), true, gclog_or_tty);
{- -------------------------------------------
(1) PSParallelCompact::clear_data_covering_space() を呼んで,
今回の GC で使用したオブジェクトの値をクリアしておく.
(具体的には, PSParallelCompact::_mark_bitmap,
PSParallelCompact::_summary_data, 及び
それぞれの Space に対応する SplitInfo オブジェクトの値をクリアする.
なお, _mark_bitmap や _summary_data は
今回の GC 中に使用してない部分までクリアするのは時間の無駄なので,
それぞれの Space ごとに使用した範囲だけをクリアしている)
また, (この段階では各 Space オブジェクトの top 位置が GC 前のままになっているので)
SpaceInfo::publish_new_top() で top を正しいアドレスに修正しておく.
---------------------------------------- -}
for (unsigned int id = perm_space_id; id < last_space_id; ++id) {
// Clear the marking bitmap, summary data and split info.
clear_data_covering_space(SpaceId(id));
// Update top(). Must be done after clearing the bitmap and summary data.
_space_info[id].publish_new_top();
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
MutableSpace* const eden_space = _space_info[eden_space_id].space();
MutableSpace* const from_space = _space_info[from_space_id].space();
MutableSpace* const to_space = _space_info[to_space_id].space();
ParallelScavengeHeap* heap = gc_heap();
bool eden_empty = eden_space->is_empty();
{- -------------------------------------------
(1) もし GC 後にも Eden 領域内にオブジェクトが残っていた場合,
PSParallelCompact::absorb_live_data_from_eden() を呼んで,
領域間の境界をずらすことで, それらを Old 領域内へと移動させることを試みる.
(成功したかどうかが, 以下の eden_empty に格納される)
---------------------------------------- -}
if (!eden_empty) {
eden_empty = absorb_live_data_from_eden(heap->size_policy(),
heap->young_gen(), heap->old_gen());
}
{- -------------------------------------------
(1) Universe::update_heap_info_at_gc() を呼んで,
以下の値を現在のヒープの最大長(capacity)及び使用量(used)に応じた値に変更する.
* Universe::get_heap_capacity_at_last_gc()
* Universe::get_heap_free_at_last_gc()
* Universe::get_heap_used_at_last_gc()
なお, これらの値は ReferencePolicy オブジェクト内で soft reference の消去ポリシーの決定に使用されている.
(See: ReferencePolicy)
---------------------------------------- -}
// Update heap occupancy information which is used as input to the soft ref
// clearing policy at the next gc.
Universe::update_heap_info_at_gc();
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
bool young_gen_empty = eden_empty && from_space->is_empty() &&
to_space->is_empty();
{- -------------------------------------------
(1) もし barrier set として ModRefBarrierSet (もしくはそのサブクラス) を使用している場合,
Perm 領域及び Old 領域に対応する barrier set の値を変更しておく.
* もう New 領域内にオブジェクトがない場合 (以下の young_gen_empty が true):
ModRefBarrierSet::clear() で, 対応する箇所全てをクリアする.
* まだ New 領域内にオブジェクトがある場合 (以下の young_gen_empty が false):
ModRefBarrierSet::invalidate() で, 対応する箇所全てを dirty にする.
---------------------------------------- -}
BarrierSet* bs = heap->barrier_set();
if (bs->is_a(BarrierSet::ModRef)) {
ModRefBarrierSet* modBS = (ModRefBarrierSet*)bs;
MemRegion old_mr = heap->old_gen()->reserved();
MemRegion perm_mr = heap->perm_gen()->reserved();
assert(perm_mr.end() <= old_mr.start(), "Generations out of order");
if (young_gen_empty) {
modBS->clear(MemRegion(perm_mr.start(), old_mr.end()));
} else {
modBS->invalidate(MemRegion(perm_mr.start(), old_mr.end()));
}
}
{- -------------------------------------------
(1) フレーム中の bcp (byte code pointer, バイトコードを指すポインタ) を格納している箇所については
GC 前に Threads::gc_prologue() で
bcp から bci(byte code index, そのバイトコードのメソッド先頭からのオフセット値) へと値を変更していたので,
Threads::gc_epilogue() を呼んで元に戻しておく.
(ついでに, フレーム内の値について環境依存(プラットフォーム依存)な処理が必要であれば, それも行っている)
---------------------------------------- -}
Threads::gc_epilogue();
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
CodeCache::gc_epilogue();
{- -------------------------------------------
(1) JvmtiExport::gc_epilogue() を呼んで,
JvmtiBreakpointCache 内でキャッシュしているブレークポイントを指すポインタも更新しておく.
---------------------------------------- -}
JvmtiExport::gc_epilogue();
{- -------------------------------------------
(1) #ifdef COMPILER2 の場合には, GC が終わったので
見つかった derived pointer の値を修正しておく.
(See: DerivedPointerTable)
---------------------------------------- -}
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
{- -------------------------------------------
(1) 参照オブジェクト(java.lang.ref オブジェクト)に対する後始末を行う.
(ReferenceProcessor::enqueue_discovered_references() で
リストに残った参照オブジェクト(= 差し先が死んだため特殊な処理が必要な参照オブジェクト)を pending list に追加する)
---------------------------------------- -}
ref_processor()->enqueue_discovered_references(NULL);
{- -------------------------------------------
(1) (デバッグ用の処理)
(ZapUnusedHeapArea オプションが指定されている場合は ...#TODO)
---------------------------------------- -}
if (ZapUnusedHeapArea) {
heap->gen_mangle_unused_area();
}
{- -------------------------------------------
(1) PSParallelCompact::reset_millis_since_last_gc() で, _time_of_last_gc フィールドを現在時刻に更新しておく.
(これは sun.misc.GC.maxObjectInspectionAge() メソッドを実現するため(だけ)の処理.
See: JVM_MaxObjectInspectionAge())
---------------------------------------- -}
// Update time of last GC
reset_millis_since_last_gc();
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.