hotspot/src/share/vm/runtime/virtualspace.cpp
ReservedSpace::ReservedSpace(const size_t prefix_size,
const size_t prefix_align,
const size_t suffix_size,
const size_t suffix_align,
char* requested_address,
const size_t noaccess_prefix)
{
{- -------------------------------------------
(1) (なお, 引数の noaccess_prefix は,
UseCompressedOop 時に Null Check を暗黙的に行うために
ヒープの先頭にアクセス禁止のメモリプロテクションを張る場合のプロテクション領域の大きさを示す.
プロテクションが不要なら 0.
See: ReservedSpace::protect_noaccess_prefix())
---------------------------------------- -}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(prefix_size != 0, "sanity");
assert(prefix_align != 0, "sanity");
assert(suffix_size != 0, "sanity");
assert(suffix_align != 0, "sanity");
assert((prefix_size & prefix_align - 1) == 0,
"prefix_size not divisible by prefix_align");
assert((suffix_size & suffix_align - 1) == 0,
"suffix_size not divisible by suffix_align");
assert((suffix_align & prefix_align - 1) == 0,
"suffix_align not divisible by prefix_align");
// Assert that if noaccess_prefix is used, it is the same as prefix_align.
assert(noaccess_prefix == 0 ||
noaccess_prefix == prefix_align, "noaccess prefix wrong");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// Add in noaccess_prefix to prefix_size;
const size_t adjusted_prefix_size = prefix_size + noaccess_prefix;
const size_t size = adjusted_prefix_size + suffix_size;
{- -------------------------------------------
(1) もし, Large Page を使用することが指定されているが (= UseLargePages),
OS の制約により large page については reserve と commit は同時に行わなくてはいけない場合
(= os::can_commit_large_page_memory() が false) には,
ReservedSpace::initialize() での確保を試みる.
成功しても失敗してもここでリターン.
---------------------------------------- -}
// On systems where the entire region has to be reserved and committed up
// front, the compound alignment normally done by this method is unnecessary.
const bool try_reserve_special = UseLargePages &&
prefix_align == os::large_page_size();
if (!os::can_commit_large_page_memory() && try_reserve_special) {
initialize(size, prefix_align, true, requested_address, noaccess_prefix,
false);
return;
}
{- -------------------------------------------
(1) フィールドの初期化
(まだメモリ領域が確保できていないのでいくつかのフィールドの値は適当.
領域の reserve 後に正式な値を入れる)
---------------------------------------- -}
_base = NULL;
_size = 0;
_alignment = 0;
_special = false;
_noaccess_prefix = 0;
_executable = false;
{- -------------------------------------------
(1) メモリ領域の reserve を試みる.
確保するアドレスが指定されているかどうかで確保処理が少し異なる.
* 確保するアドレスが指定されている場合には(= requested_address が 0 でなければ),
確保するアドレスを noaccess_prefix 分だけ調整した後,
os::attempt_reserve_memory_at() で確保を試みる.
もし指定のアドレスに確保できていなければ (= failed_to_reserve_as_requested() が true),
reserve は失敗しているので, ここでリターンする.
* 確保するアドレスが指定されていなければ(= requested_address が 0 ならば),
os::reserve_memory() で確保を試みる.
reserve が失敗していれば (= addr が NULL), ここでリターン
---------------------------------------- -}
// Optimistically try to reserve the exact size needed.
char* addr;
if (requested_address != 0) {
requested_address -= noaccess_prefix; // adjust address
assert(requested_address != NULL, "huge noaccess prefix?");
addr = os::attempt_reserve_memory_at(size, requested_address);
if (failed_to_reserve_as_requested(addr, requested_address, size, false)) {
// OS ignored requested address. Try different address.
addr = NULL;
}
} else {
addr = os::reserve_memory(size, NULL, prefix_align);
}
if (addr == NULL) return;
{- -------------------------------------------
(1) 確保した領域のアラインメントが正しいかどうかを確認する.
(先頭から adjusted_prefix_size 足したアドレス(= 第2の領域の先頭)が suffix_align でアラインされているか, を確認)
もしアラインされていなければ, 確保した領域は os::release_memory() でいったん解放し,
確保サイズを少し大きくして ReservedSpace::reserve_and_align() でアライン条件にあうアドレスを取り直す.
(もしこれも失敗すれば, 確保サイズをもう少し大きくして ReservedSpace::reserve_and_align() で再度取り直す.
それでも駄目なら確保は失敗したことにする.)
---------------------------------------- -}
// Check whether the result has the needed alignment (unlikely unless
// prefix_align == suffix_align).
const size_t ofs = size_t(addr) + adjusted_prefix_size & suffix_align - 1;
if (ofs != 0) {
// Wrong alignment. Release, allocate more space and do manual alignment.
//
// On most operating systems, another allocation with a somewhat larger size
// will return an address "close to" that of the previous allocation. The
// result is often the same address (if the kernel hands out virtual
// addresses from low to high), or an address that is offset by the increase
// in size. Exploit that to minimize the amount of extra space requested.
if (!os::release_memory(addr, size)) {
fatal("os::release_memory failed");
}
const size_t extra = MAX2(ofs, suffix_align - ofs);
addr = reserve_and_align(size + extra, adjusted_prefix_size, prefix_align,
suffix_size, suffix_align);
if (addr == NULL) {
// Try an even larger region. If this fails, address space is exhausted.
addr = reserve_and_align(size + suffix_align, adjusted_prefix_size,
prefix_align, suffix_size, suffix_align);
}
}
{- -------------------------------------------
(1) フィールドの初期化 (メモリ領域が確保できたので, 正式な値で初期化)
---------------------------------------- -}
_base = addr;
_size = size;
_alignment = prefix_align;
_noaccess_prefix = noaccess_prefix;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.