hotspot/src/share/vm/gc_interface/collectedHeap.cpp
HeapWord* CollectedHeap::allocate_from_tlab_slow(Thread* thread, size_t size) {
{- -------------------------------------------
(1) もし現在の TLAB 内に空き領域がかなり残っていれば, それを捨てるのはもったいないので
今回は TLAB を使わずに slow-path で確保することにする.
この場合, ここでリターン.
(なお, 同じサイズの確保を何度も行うようなプログラムの場合, 閾値が同じだと
ずっとこれに引っかかって slow-path になり続ける恐れがあるので,
ThreadLocalAllocBuffer::record_slow_allocation() で
ThreadLocalAllocBuffer::refill_waste_limit() の値を増加させている.
See: ThreadLocalAllocBuffer::record_slow_allocation())
---------------------------------------- -}
// Retain tlab and allocate object in shared space if
// the amount free in the tlab is too large to discard.
if (thread->tlab().free() > thread->tlab().refill_waste_limit()) {
thread->tlab().record_slow_allocation(size);
return NULL;
}
{- -------------------------------------------
(1) ThreadLocalAllocBuffer::compute_size() で次に確保する TLAB の大きさを計算する.
---------------------------------------- -}
// Discard tlab and allocate a new one.
// To minimize fragmentation, the last TLAB may be smaller than the rest.
size_t new_tlab_size = thread->tlab().compute_size(size);
{- -------------------------------------------
(1) ThreadLocalAllocBuffer::clear_before_allocation() で,
現在の TLAB の残りのスペースを dummy の配列で埋めておく.
---------------------------------------- -}
thread->tlab().clear_before_allocation();
{- -------------------------------------------
(1) もし確保する TLAB の大きさが 0 だったら, ここでリターン.
---------------------------------------- -}
if (new_tlab_size == 0) {
return NULL;
}
{- -------------------------------------------
(1) CollectedHeap::allocate_new_tlab() で新しい TLAB を確保する (以下の obj).
(実際にはこのメソッドはそれぞれのサブクラスでオーバーライドされており, 各 GC アルゴリズムに対応した確保処理が行われる)
もし確保に失敗したら NULL をリターン.
---------------------------------------- -}
// Allocate a new TLAB...
HeapWord* obj = Universe::heap()->allocate_new_tlab(new_tlab_size);
if (obj == NULL) {
return NULL;
}
{- -------------------------------------------
(1) ZeroTLAB オプションが指定されていれば, 確保した TLAB 内全域を 0 クリアする.
そうでなければ, 今回の確保要求に対して返却するオブジェクト分の領域だけを 0 クリアする.
---------------------------------------- -}
if (ZeroTLAB) {
// ..and clear it.
Copy::zero_to_words(obj, new_tlab_size);
} else {
// ...and clear just the allocated object.
Copy::zero_to_words(obj, size);
}
{- -------------------------------------------
(1) ThreadLocalAllocBuffer::fill() を呼んで, 確保した TLAB をカレントスレッドの _tlab にセットする.
(なお, 新しい TLAB は obj から new_tlab_size 分の領域.
ただし, obj から obj + size までの領域は, 確保要求のあったオブジェクトを配置するために使うため,
この時点で既に残り容量は new_tlab_size - size となっている.)
---------------------------------------- -}
thread->tlab().fill(obj, obj + size, new_tlab_size);
{- -------------------------------------------
(1) 確保したオブジェクトへのポインタをリターンする
---------------------------------------- -}
return obj;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.