ランタイムによる Java メソッドの呼び出し処理は JavaCalls クラスに実装されている. より具体的に言うと, JavaCalls クラスの以下の public メソッドが呼び出し処理になっている.
どのメソッドの場合も, 最終的には StubRoutines::call_stub() が指しているスタブコードを用いて Java メソッドの呼び出しが行われる. この StubRoutines::call_stub() は, 初期化時に StubGenerator::generate_call_stub() で作られるスタブで, 以下の処理を行うコードが入っている (1.~3. はダミーの呼び出し元フレーム(Java メソッド風)を構築する処理. スタック上にパラメータを配置し, Gargs などを設定する) (See: here for details).
なお, StubRoutines::call_stub() までの呼び出し処理の流れは以下の通り.
Java メソッドの実行が終わると, 返り値がそのアドレスに格納されて VM ルーチンに渡される.
この変数の値は, 例外処理などでスタックフレームを逆にたどる際に call_stub が生成したフレームかどうかの判定(= VMルーチンへの戻り点の検出)に使用されている.
StubRoutines::call_stub() が作るスタックフレームは以下のような構造になる.
((cite: hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp))
// Call stubs are used to call Java from C
//
// Linux Arguments:
// c_rarg0: call wrapper address address
// c_rarg1: result address
// c_rarg2: result type BasicType
// c_rarg3: method methodOop
// c_rarg4: (interpreter) entry point address
// c_rarg5: parameters intptr_t*
// 16(rbp): parameter size (in words) int
// 24(rbp): thread Thread*
//
// [ return_from_Java ] <--- rsp
// [ argument word n ]
// ...
// -12 [ argument word 1 ]
// -11 [ saved r15 ] <--- rsp_after_call
// -10 [ saved r14 ]
// -9 [ saved r13 ]
// -8 [ saved r12 ]
// -7 [ saved rbx ]
// -6 [ call wrapper ]
// -5 [ result ]
// -4 [ result type ]
// -3 [ method ]
// -2 [ entry point ]
// -1 [ parameters ]
// 0 [ saved rbp ] <--- rbp
// 1 [ return address ]
// 2 [ parameter size ]
// 3 [ thread ]
//
// Windows Arguments:
// c_rarg0: call wrapper address address
// c_rarg1: result address
// c_rarg2: result type BasicType
// c_rarg3: method methodOop
// 48(rbp): (interpreter) entry point address
// 56(rbp): parameters intptr_t*
// 64(rbp): parameter size (in words) int
// 72(rbp): thread Thread*
//
// [ return_from_Java ] <--- rsp
// [ argument word n ]
// ...
// -28 [ argument word 1 ]
// -27 [ saved xmm15 ] <--- rsp_after_call
// [ saved xmm7-xmm14 ]
// -9 [ saved xmm6 ] (each xmm register takes 2 slots)
// -7 [ saved r15 ]
// -6 [ saved r14 ]
// -5 [ saved r13 ]
// -4 [ saved r12 ]
// -3 [ saved rdi ]
// -2 [ saved rsi ]
// -1 [ saved rbx ]
// 0 [ saved rbp ] <--- rbp
// 1 [ return address ]
// 2 [ call wrapper ]
// 3 [ result ]
// 4 [ result type ]
// 5 [ method ]
// 6 [ entry point ]
// 7 [ parameters ]
// 8 [ parameter size ]
// 9 [ thread ]
//
// Windows reserves the callers stack space for arguments 1-4.
// We spill c_rarg0-c_rarg3 to this space.
((cite: hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp))
// +---------------+ <--- sp + 0
// | |
// . reg save area .
// | |
// +---------------+ <--- sp + 0x40
// | |
// . extra 7 slots .
// | |
// +---------------+ <--- sp + 0x5c
// | empty slot | (only if parameter size is even)
// +---------------+
// | |
// . parameters .
// | |
// +---------------+ <--- fp + 0
// | |
// . reg save area .
// | |
// +---------------+ <--- fp + 0x40
// | |
// . extra 7 slots .
// | |
// +---------------+ <--- fp + 0x5c
// | param. size |
// +---------------+ <--- fp + 0x60
// | thread |
// +---------------+
// | |
JavaCalls::call() -> os::os_exception_wrapper() -> JavaCalls::call_helper() -> (1) 必要があれば JIT コンパイルを開始させる. -> CompilationPolicy::must_be_compiled() -> CompileBroker::compile_method() -> (See: here for details) (1) メソッドのエントリポイントを取得する -> methodOopDesc::from_interpreted_entry() -> methodOopDesc::interpreter_entry() (1) スタック上の Yellow Page が無効にされていたら, 有効化しておく -> JavaThread::reguard_stack() (1) スタック上の空き領域が shadow page として十分かどうかを確認し, 十分な物理メモリも割り当てておく (空き領域が足りなければ StackOverflowError) -> os::stack_shadow_pages_available() -> os::bang_stack_shadow_pages() (1) 指定された Java メソッドの呼び出しを行う -> JavaCallWrapper::JavaCallWrapper() -> StubRoutines::call_stub() が指しているコード (= StubGenerator::generate_call_stub() が生成するコード) -> (実際の呼び出し処理) -> (実際の呼び出し処理の後, 引き続いて通常のメソッド呼び出し処理が行われる) (See: here for details) -> JavaCallWrapper::~JavaCallWrapper()
JavaCalls::call_default_constructor() -> JavaCalls::call() -> (同上)
JavaCalls::call_virtual() -> LinkResolver::resolve_virtual_call() -> (See: here for details) -> JavaCalls::call() -> (同上)
JavaCalls::call_special() -> LinkResolver::resolve_special_call() -> (See: here for details) -> JavaCalls::call() -> (同上)
JavaCalls::call_static() -> LinkResolver::resolve_static_call() -> (See: here for details) -> JavaCalls::call() -> (同上)
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
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
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.