hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
void SignatureHandlerLibrary::add(methodHandle method) {
{- -------------------------------------------
(1) (既に signature handler を生成済みであれば
(= methodOopDesc::signature_handler() が NULL でない値を返すならば),
何もしない)
---------------------------------------- -}
if (method->signature_handler() == NULL) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// use slow signature handler if we can't do better
int handler_index = -1;
{- -------------------------------------------
(1) (以下で signature handler を生成する.
作成処理のパスは以下のように何通りか存在する.
A. UseFastSignatureHandlers オプションが指定されていない場合:
Interpreter::slow_signature_handler() が指す先のコードで生成.
B. メソッドの引数の数が多すぎる場合 (Fingerprinter::max_size_of_parameters を超えている場合):
Interpreter::slow_signature_handler() で生成.
C. 上記以外の場合:
* 同じ型の signature handler を既に作成済みの場合:
それを流用する.
* 〃 未作成の場合:
InterpreterRuntime::SignatureHandlerGenerator::generate() で作成.
(ただし, この場合は作成に失敗したら Interpreter::slow_signature_handler() が指す先のコードでの生成にフォールバック))
---------------------------------------- -}
{- -------------------------------------------
(1) (以下は, 上の "C." のケース)
---------------------------------------- -}
// check if we can use customized (fast) signature handler
if (UseFastSignatureHandlers && method->size_of_parameters() <= Fingerprinter::max_size_of_parameters) {
// use customized signature handler
MutexLocker mu(SignatureHandlerLibrary_lock);
{- -------------------------------------------
(1.1) SignatureHandlerLibrary::initialize() を呼んで,
(もし SignatureHandlerLibrary の初期化が終わっていなければ) 初期化しておく.
---------------------------------------- -}
// make sure data structure is initialized
initialize();
{- -------------------------------------------
(1.1) メソッドの型情報から fingerprint を作成し, 既に作成済みの signature handler かどうかを調べる.
---------------------------------------- -}
// lookup method signature's fingerprint
uint64_t fingerprint = Fingerprinter(method).fingerprint();
handler_index = _fingerprints->find(fingerprint);
{- -------------------------------------------
(1.1) まだ作成したことがない signature であれば, 以下の if ブロック内で作成を試みる.
(逆に, 既に作成済みの signature handler であれば,
その結果を流用すればいいので以下の if ブロックの処理は省略)
---------------------------------------- -}
// create handler if necessary
if (handler_index < 0) {
{- -------------------------------------------
(1.1.1) (変数宣言など)
---------------------------------------- -}
ResourceMark rm;
ptrdiff_t align_offset = (address)
round_to((intptr_t)_buffer, CodeEntryAlignment) - (address)_buffer;
CodeBuffer buffer((address)(_buffer + align_offset),
SignatureHandlerLibrary::buffer_size - align_offset);
{- -------------------------------------------
(1.1.1) InterpreterRuntime::SignatureHandlerGenerator::generate() を呼び出して, signature handler の生成を行う.
---------------------------------------- -}
InterpreterRuntime::SignatureHandlerGenerator(method, &buffer).generate(fingerprint);
{- -------------------------------------------
(1.1.1) もし signature handler の生成に成功したら,
SignatureHandlerLibrary::set_handler() を呼んで内側のバッファにコピーしておく.
---------------------------------------- -}
// copy into code heap
address handler = set_handler(&buffer);
{- -------------------------------------------
(1.1.1) コピーが失敗した場合は, このまま slow signature handler を作る処理へとフォールバック.
---------------------------------------- -}
if (handler == NULL) {
// use slow signature handler
{- -------------------------------------------
(1.1.1) コピーが成功した場合は, 次回以降にも流用するため,
生成した signature handler (及び対応する finterprint) を _fingerprints と _handlers 内にメモイズしておく.
---------------------------------------- -}
} else {
{- -------------------------------------------
(1.1.1.1) (トレース出力)
---------------------------------------- -}
// debugging suppport
if (PrintSignatureHandlers) {
tty->cr();
tty->print_cr("argument handler #%d for: %s %s (fingerprint = " UINT64_FORMAT ", %d bytes generated)",
_handlers->length(),
(method->is_static() ? "static" : "receiver"),
method->name_and_sig_as_C_string(),
fingerprint,
buffer.insts_size());
Disassembler::decode(handler, handler + buffer.insts_size());
#ifndef PRODUCT
tty->print_cr(" --- associated result handler ---");
address rh_begin = Interpreter::result_handler(method()->result_type());
address rh_end = rh_begin;
while (*(int*)rh_end != 0) {
rh_end += sizeof(int);
}
Disassembler::decode(rh_begin, rh_end);
#endif
}
{- -------------------------------------------
(1.1.1.1) メモイズ処理
---------------------------------------- -}
// add handler to library
_fingerprints->append(fingerprint);
_handlers->append(handler);
// set handler index
assert(_fingerprints->length() == _handlers->length(), "sanity check");
handler_index = _fingerprints->length() - 1;
}
}
{- -------------------------------------------
(1.1) (以下で実際に signature handler を登録する.
登録処理は methodOopDesc::set_signature_handler() で行う.
この処理は SignatureHandlerLibrary_lock によって排他されている.)
---------------------------------------- -}
// Set handler under SignatureHandlerLibrary_lock
{- -------------------------------------------
(1.1) この時点で signature handler が作成できていない場合は,
Interpreter::slow_signature_handler() が指しているコードで signature handler を作成して登録.
---------------------------------------- -}
if (handler_index < 0) {
// use generic signature handler
method->set_signature_handler(Interpreter::slow_signature_handler());
{- -------------------------------------------
(1.1) 逆に, signature handler が作成できていれば, その signature handler を登録.
---------------------------------------- -}
} else {
// set handler
method->set_signature_handler(_handlers->at(handler_index));
}
{- -------------------------------------------
(1) (以下は, 上の "A." 又は "B." のケース)
Interpreter::slow_signature_handler() が指しているコードで signature handler を作成して登録する.
---------------------------------------- -}
} else {
CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
// use generic signature handler
method->set_signature_handler(Interpreter::slow_signature_handler());
}
}
{- -------------------------------------------
(1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
---------------------------------------- -}
#ifdef ASSERT
int handler_index = -1;
int fingerprint_index = -2;
{
// '_handlers' and '_fingerprints' are 'GrowableArray's and are NOT synchronized
// in any way if accessed from multiple threads. To avoid races with another
// thread which may change the arrays in the above, mutex protected block, we
// have to protect this read access here with the same mutex as well!
MutexLocker mu(SignatureHandlerLibrary_lock);
if (_handlers != NULL) {
handler_index = _handlers->find(method->signature_handler());
fingerprint_index = _fingerprints->find(Fingerprinter(method).fingerprint());
}
}
assert(method->signature_handler() == Interpreter::slow_signature_handler() ||
handler_index == fingerprint_index, "sanity check");
#endif // ASSERT
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.