hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
HeapWord*
G1CollectedHeap::mem_allocate(size_t word_size,
bool is_noref,
bool is_tlab,
bool* gc_overhead_limit_was_exceeded) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert_heap_not_locked_and_not_at_safepoint();
assert(!is_tlab, "mem_allocate() this should not be called directly "
"to allocate TLABs");
{- -------------------------------------------
(1) 以下, メモリ確保が成功するかあるいは成功しないと判断するまで, 以下のループで処理を続ける
(以下のループを抜けるのは return する時だけ)
---------------------------------------- -}
// Loop until the allocation is satisified, or unsatisfied after GC.
for (int try_count = 1; /* we'll return */; try_count += 1) {
unsigned int gc_count_before;
{- -------------------------------------------
(1.1) まず, G1CollectedHeap::attempt_allocation() または G1CollectedHeap::attempt_allocation_humongous() で確保を試みる.
(確保要求のサイズがあまりに大きくなければ (= G1CollectedHeap::isHumongous() が false), G1CollectedHeap::attempt_allocation() を使う.
大きければ G1CollectedHeap::attempt_allocation_humongous() を使う.)
確保が成功すれば, ここでリターン.
---------------------------------------- -}
HeapWord* result = NULL;
if (!isHumongous(word_size)) {
result = attempt_allocation(word_size, &gc_count_before);
} else {
result = attempt_allocation_humongous(word_size, &gc_count_before);
}
if (result != NULL) {
return result;
}
{- -------------------------------------------
(1.1) VM_G1CollectForAllocation で GC を実行する
---------------------------------------- -}
// Create the garbage collection operation...
VM_G1CollectForAllocation op(gc_count_before, word_size);
// ...and get the VM thread to execute it.
VMThread::execute(&op);
{- -------------------------------------------
(1.1) もし自分が要求を出した GC が実行され (See: prologue_succeeded),
かつそれが GC_locker によって中断されなかった場合(See: pause_succeeded)は,
確保が成功したかどうかに関わらず, 結果をリターンする.
(なお, pause_succeeded は GC_locker によって中断されたかどうかを示す.
(See: G1CollectedHeap::do_collection_pause_at_safepoint()))
(なお, 確保が成功し, かつサイズが大きすぎない場合 (isHumongous() ではない場合) には,
ここで barrier set の dirtying を行っている.)
---------------------------------------- -}
if (op.prologue_succeeded() && op.pause_succeeded()) {
// If the operation was successful we'll return the result even
// if it is NULL. If the allocation attempt failed immediately
// after a Full GC, it's unlikely we'll be able to allocate now.
HeapWord* result = op.result();
if (result != NULL && !isHumongous(word_size)) {
// Allocations that take place on VM operations do not do any
// card dirtying and we have to do it here. We only have to do
// this for non-humongous allocations, though.
dirty_young_block(result, word_size);
}
return result;
{- -------------------------------------------
(1.1) もし自分が要求を出した GC が実行されなかったか,
GC_locker によって中断されていた場合には,
このままループの次の周回にフォールスルー.
---------------------------------------- -}
} else {
assert(op.result() == NULL,
"the result should be NULL if the VM op did not succeed");
}
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
// Give a warning if we seem to be looping forever.
if ((QueuedAllocationWarningCount > 0) &&
(try_count % QueuedAllocationWarningCount == 0)) {
warning("G1CollectedHeap::mem_allocate retries %d times", try_count);
}
}
{- -------------------------------------------
(1) (以下は決して到達しないパス)
---------------------------------------- -}
ShouldNotReachHere();
return NULL;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.