(See: JVMTI 仕様) (なお, JVMTI 仕様により, 対象のスレッドは suspend していなければいけないと決められている).
実際の強制復帰処理は, JvmtiEnv::ForceEarlyReturn*() 内では行わず, deopt 処理または suspend 状態から通常状態に復帰するパスの途中で行われる
この処理は以下の流れで行われる.
まず, JvmtiEnv::PopFrame() 内でいくつかのフィールドがセットされる (なお対象のフレームが compiled frame の場合は deopt も行われる).
上記のフィールドがセットされていると, deopt 処理または suspend 状態から通常状態に復帰する処理において, Interpreter::remove_activation_early_entry() が指すコードにジャンプする.
Interpreter::remove_activation_early_entry() 内で実際の強制復帰処理が行われる.
セットされるフィールドは以下の通り.
((cite: hotspot/src/share/vm/prims/jvmtiThreadState.hpp))
// JVMTI ForceEarlyReturn support
// This is set to earlyret_pending to signal that top Java frame
// should be returned immediately
public:
int _earlyret_state;
TosState _earlyret_tos;
jvalue _earlyret_value;
oop _earlyret_oop; // Used to return an oop result into Java code from
((cite: hotspot/src/share/vm/prims/jvmtiThreadState.hpp))
bool _pending_step_for_earlyret;
ジャンプするまでの流れは以下の通り.
処理対象が compiled frame の場合:
JvmtiEnv::ForceEarlyReturn*() 内で対象のフレームが deopt される (正確には, 対象のスレッドが実行を再会し, そのフレームにリターンした際に deopt が走る). この deopt 処理の中で, JvmtiThreadState::earlyret_state フィールドが参照されている. フィールドがセットされている場合, deopt 後の復帰先は Interpreter::removeactivation_early_entry() が返すアドレスになる.
処理対象が template interpreter frame の場合:
suspend する関数呼び出しからの復帰パスで処理が行われる. 具体的には call_VM_base() による VM 呼び出しからのリターン後の処理で (InterpreterMacroAssembler::check_and_handle_popframe() で生成されたコードにより) JvmtiThreadState::earlyret_state フィールドがチェックされ, Interpreter::removeactivation_early_entry() が返すアドレスにジャンプする.
処理は以下のようになる.
なお, SingleStep モードで実行している際には, さらに SingleStep 用の後片付け処理も行われる.
Interpreter::remove_activation_early_entry() が指すコードは TemplateInterpreterGenerator::generate_earlyret_entry_for() により生成されている.
なお, 現状では, C++ Interpreter 使用時には (onload_capabilities に can_force_early_return が含まれないので) ForceEarlyReturn*() は使用できない模様.
See: here for details
内部処理的には, ForceEarlyReturn*() は PopFrame() とかなり似ている (See: here for details).
PopFrame に似てて, 最後の処理だけ違う, とのこと.
((cite: hotspot/src/share/vm/prims/jvmtiEnvBase.cpp))
// ForceEarlyReturn<type> follows the PopFrame approach in many aspects.
// Main difference is on the last stage in the interpreter.
// The PopFrame stops method execution to continue execution
// from the same method call instruction.
// The ForceEarlyReturn forces return from method so the execution
// continues at the bytecode following the method call.
JvmtiEnv::ForceEarlyReturn*() -> JvmtiEnvBase::force_early_return() -> (1) 先頭フレームが compiled frame であれば interpreter frame に戻しておく. -> JvmtiEnvBase::check_top_frame() (2) ForceEarlyReturn* の処理対象になっていることを JvmtiThreadState オブジェクト内に記録しておく -> JvmtiThreadState::set_earlyret_pending() -> JvmtiThreadState::set_earlyret_oop() -> JvmtiThreadState::set_earlyret_value() -> JvmtiThreadState::set_pending_step_for_earlyret()
deopt 処理 (See: ) -> vframeArrayElement::unpack_on_stack() -> JvmtiThreadState::is_earlyret_pending() が true の場合は, 復帰先の PC として Interpreter::remove_activation_early_entry() を選択する (なお, JvmtiThreadState::is_earlyret_pending() は JvmtiThreadState::_earlyret_state フィールドをチェックする関数)
* sparc の場合: (略) (See: here for details) -> MacroAssembler::call_VM_base() が生成するコード -> MacroAssembler::check_and_forward_exception() が生成するコード -> InterpreterMacroAssembler::check_and_handle_earlyret() が生成するコード -> Interpreter::remove_activation_early_entry() が指しているコード (= TemplateInterpreterGenerator::generate_earlyret_entry_for() が生成するコード) * x86 の場合: (略) (See: here for details) -> MacroAssembler::call_VM_base() が生成するコード -> InterpreterMacroAssembler::check_and_handle_earlyret() が生成するコード -> Interpreter::remove_activation_early_entry() が指しているコード (= TemplateInterpreterGenerator::generate_earlyret_entry_for() が生成するコード)
(略) (See: here for details) -> JvmtiExport::at_single_stepping_point() -> JvmtiThreadState::is_pending_step_for_earlyret() が true の場合は, JvmtiThreadState::process_pending_step_for_earlyret() を呼び出す.
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.