(#Under Construction)
ネイティブメソッドの呼び出し時には, 引数や返値をネイティブの ABI に合わせて変換する関数が用いられる. これらはそれぞれ「シグネチャハンドラ(signature handler)」と「リザルトハンドラ(result handler)」と呼ばれる.
オペランドスタックの引数を ABI にしたがった形に変換する関数
ネイティブメソッドの返り値をオペランドスタックに載せる関数 (Sparc 版ではついでにフレームの開放も行う)
なお, シグネチャハンドラ/リザルトハンドラ はペアで扱われ, シグネチャハンドラ内で Lscratch レジスタ(Sparc の場合) や rax レジスタ(x86_64 の場合)にそのメソッドの返り値に対応するリザルトハンドラのアドレスが格納される.
また, シグネチャハンドラとリザルトハンドラはそれぞれ引数の型/返り値の型が共通の同士は流用できるので, シグネチャ文字列 (= 型を表す文字列. 例: "Ljava/lang/Object") をキーとする hashmap に登録して管理している (See: SignatureHandlerLibrary).
実際のデータ構造上では, 各 methodOop オブジェクト内の signature_handler フィールドに 「そのメソッドを呼ぶ際に使用する signature handler」 が格納されている. InterpreterGenerator::generate_native_entry() が生成したコードは ここから signature handler を取ってきて引数の詰め直しに使用する
slow case では Interpreter::slow_signature_handler() が指しているコードが用いられる. このコードは初期化時に生成される.
また, result handler のコードも初期化時に生成される.
* slow_signature_handler の生成処理 (See: here for details) -> TemplateInterpreterGenerator::generate_all() -> AbstractInterpreterGenerator::generate_all() -> AbstractInterpreterGenerator::generate_slow_signature_handler() * result handler の生成処理 (See: here for details) -> TemplateInterpreterGenerator::generate_all() -> TemplateInterpreterGenerator::generate_result_handler_for() * method entry 部コードの生成処理 (See: here for details) -> AbstractInterpreterGenerator::generate_method_entry() -> InterpreterGenerator::generate_native_entry()
InterpreterGenerator::generate_native_entry() が生成するコード
-> (1) スタック上に新しいフレームを確保する
-> TemplateInterpreterGenerator::generate_fixed_frame() が生成したコード
(1) JIT コンパイラを使う場合は, invocation counter 値を増加させて値をチェックする
-> InterpreterGenerator::generate_counter_incr() が生成したコード
(1) stack overflow をチェックする (stack banging コード)
-> AbstractInterpreterGenerator::bang_stack_shadow_pages() が生成したコード
(1) synchronized method の場合はロックを取得する
-> InterpreterGenerator::lock_method() が生成したコード
-> (See: here for details)
(1) (まだ設定されていなければ) 対応するネイティブ関数のアドレスやシグネチャハンドラを設定しておく
-> InterpreterRuntime::prepare_native_call()
-> (1) (もしまだ終わっていなければ) 呼び出し先の関数へのダイナミックリンクを行う
-> NativeLookup::lookup()
-> (後述) (See: here for details)
(1) (もしまだ終わっていなければ) シグネチャハンドラの設定を行う
-> SignatureHandlerLibrary::add()
-> * 既に (1回以上呼び出されているため) 設定済みの場合:
-> 何もしない
* 何らかの理由で特注のシグネチャハンドラが用意できないメソッドの場合 (引数の数が多すぎる, 等):
-> AbstractInterpreter::slow_signature_handler() (<= デフォルトのハンドラが返される)
* 既に同じ型用のシグネチャハンドラを作ってメモイズしてある場合:
-> それを流用する
* それ以外の場合:
-> InterpreterRuntime::SignatureHandlerGenerator::generate() (<= シグネチャハンドラを作成)
-> SignatureIterator::iterate()
-> SignatureIterator::parse_type()
-> NativeSignatureIterator::do_<type>()
-> InterpreterRuntime::SignatureHandlerGenerator::pass_*()
-> MacroAssembler::store_*_argument()
(1) ダミーフレームを作ってレジスタを待避する
(1) シグネチャハンドラを呼んで引数を詰め直す
(1) native メソッドの呼び出しを行う
-> (native メソッドの処理が実行される)
(1) もし Safepoint 停止が開始されていた場合は, ここで block する.
-> JavaThread::check_special_condition_for_native_trans()
(1) スタック上の yellow page が disabled になっていたら, 元に戻す.
-> SharedRuntime::reguard_yellow_pages()
(1) 例外が起きていれば伝搬させる. この場合は以降の処理は行わない.
-> MacroAssembler::call_VM()
-> (See: here for details)
-> InterpreterRuntime::throw_pending_exception()
-> (See: here for details)
(1) synchronized method の場合はロックを解放する
-> InterpreterGenerator::unlock_method() が生成したコード
-> (See: here for details)
(1) リザルトハンドラを実行する
(1) ダミーフレームを削除する
(1) 呼び出し元にリターン
InterpreterGenerator::generate_native_entry() が生成するコード
-> (1) スタック上に新しいフレームを確保する
-> TemplateInterpreterGenerator::generate_fixed_frame() が生成したコード
(1) JIT コンパイラを使う場合は, invocation counter 値を増加させて値をチェックする
-> InterpreterGenerator::generate_counter_incr() が生成したコード
(1) stack overflow をチェックする (stack banging コード)
-> AbstractInterpreterGenerator::bang_stack_shadow_pages() が生成したコード
(1) synchronized method の場合はロックを取得する
-> InterpreterGenerator::lock_method() が生成したコード
-> (See: here for details)
(1) ダミーフレームを作る
(1) (まだ設定されていなければ) 対応するネイティブ関数のアドレスやシグネチャハンドラを設定しておく
-> InterpreterRuntime::prepare_native_call()
-> (同上)
(1) シグネチャハンドラを呼んで引数を詰め直す
(1) native メソッドの呼び出しを行う
-> (native メソッドの処理が実行される)
(1) もし Safepoint 停止が開始されていた場合は, ここで block する.
-> JavaThread::check_special_condition_for_native_trans()
(1) レジスタの復帰させ, ダミーフレームを削除する
(1) 例外が起きていれば伝搬させる. この場合は以降の処理は行わない.
-> MacroAssembler::call_VM()
-> (See: here for details)
-> InterpreterRuntime::throw_pending_exception()
-> (See: here for details)
(1) synchronized method の場合はロックを解放する
-> InterpreterGenerator::unlock_method() が生成したコード
-> (See: here for details)
(1) リザルトハンドラを実行する
(1) 呼び出し元にリターン
See: here for details
See: here for details
See: here for details
(#Under Construction) See: here for details
(#Under Construction)
(#Under Construction)
(#Under Construction)
(#Under Construction)
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
(See: here for details)
(See: here for details)
(See: here for details)
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
((cite: hotspot/src/share/vm/runtime/signature.hpp))
void do_bool () { pass_int(); _jni_offset++; _offset++; }
void do_char () { pass_int(); _jni_offset++; _offset++; }
void do_float () { pass_float(); _jni_offset++; _offset++; }
#ifdef _LP64
void do_double() { pass_double(); _jni_offset++; _offset += 2; }
#else
void do_double() { pass_double(); _jni_offset += 2; _offset += 2; }
#endif
void do_byte () { pass_int(); _jni_offset++; _offset++; }
void do_short () { pass_int(); _jni_offset++; _offset++; }
void do_int () { pass_int(); _jni_offset++; _offset++; }
#ifdef _LP64
void do_long () { pass_long(); _jni_offset++; _offset += 2; }
#else
void do_long () { pass_long(); _jni_offset += 2; _offset += 2; }
#endif
void do_void () { ShouldNotReachHere(); }
void do_object(int begin, int end) { pass_object(); _jni_offset++; _offset++; }
void do_array (int begin, int end) { pass_object(); _jni_offset++; _offset++; }
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
(#Under Construction) See: here for details
(#Under Construction)
(#Under Construction)
(#Under Construction)
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.