hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
// This method iterates over all objects in the young generation,
// unforwarding markOops. It then restores any preserved mark oops,
// and clears the _preserved_mark_stack.
void PSScavenge::clean_up_failed_promotion() {
{- -------------------------------------------
(1) (Minor GC が失敗した場合は, しょうがないので Full GC で回収を試みることになる.
Minor GC が失敗した直後の状態では, Eden や From 領域に
(メモリ不足により)コピーできなかったオブジェクトが一部残っている.
が, これらの領域には, コピーが成功したオブジェクトも含まれている(かもしれない).
また, コピーが成功したものも失敗したものも, mark フィールドの下2bitは marked の状態になっているので,
そのままでは Full GC を実行することが出来ない
(Full GC のアルゴリズムが混乱する)
というわけで, Full GC が実行できるように, 以下のような状態まで持って行く.
* コピーが成功したもの:
mark フィールドの下2bitを, 通常のオブジェクトとしてあり得る状態にする.
(なおコピーが成功したものは, (みんなコピー先を参照していて)
コピー元はもう誰も参照していないはずなので, あまり丁寧に処理しなくていいはず.
Full GC 時にはゴミだと判定される)
* コピーが失敗したもの:
mark フィールドを Minor GC 実行前の状態に復元する.)
---------------------------------------- -}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
assert(promotion_failed(), "Sanity");
PSYoungGen* young_gen = heap->young_gen();
{
ResourceMark rm;
{- -------------------------------------------
(1) PSPromotionFailedClosure で,
New 領域中の全てのオブジェクトの mark フィールドを, 初期状態の値にリセットする.
---------------------------------------- -}
// Unforward all pointers in the young gen.
PSPromotionFailedClosure unforward_closure;
young_gen->object_iterate(&unforward_closure);
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (PrintGC && Verbose) {
gclog_or_tty->print_cr("Restoring %d marks", _preserved_oop_stack.size());
}
{- -------------------------------------------
(1) コピーが失敗したオブジェクトについては
PSPromotionManager::oop_promotion_failed() で mark フィールドの値を待避していたはずなので,
その待避していた値をオブジェクトの mark フィールドに書き戻す.
---------------------------------------- -}
// Restore any saved marks.
while (!_preserved_oop_stack.is_empty()) {
oop obj = _preserved_oop_stack.pop();
markOop mark = _preserved_mark_stack.pop();
obj->set_mark(mark);
}
{- -------------------------------------------
(1)
---------------------------------------- -}
// Clear the preserved mark and oop stack caches.
_preserved_mark_stack.clear(true);
_preserved_oop_stack.clear(true);
_promotion_failed = false;
}
{- -------------------------------------------
(1) (デバッグ用の処理)
---------------------------------------- -}
// Reset the PromotionFailureALot counters.
NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.