hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
// Continuation point for runtime calls returning with a pending
// exception. The pending exception check happened in the runtime
// or native call stub. The pending exception in Thread is
// converted into a Java-level exception.
//
// Contract with Java-level exception handlers:
// rax: exception
// rdx: throwing pc
//
// NOTE: At entry of this stub, exception-pc must be on stack !!
address generate_forward_exception() {
{- -------------------------------------------
(1) (以下, StubCodeMark によるスタブ生成を行う) (See: StubCodeMark)
---------------------------------------- -}
StubCodeMark mark(this, "StubRoutines", "forward exception");
{- -------------------------------------------
(1) (ここからが生成するコードの始まり)
---------------------------------------- -}
address start = __ pc();
{- -------------------------------------------
(1) (このスタブに入ってきた時点では, SP に
Java コードへのリターンアドレス(インタープリタ or JIT 生成コード)が入っている.
例外処理ルーチンからのリターンアドレスなので, つまり例外送出が起こった PC が SP に入っている.)
(なお, ランタイム呼び出しを行う前にスタックに積んだ引数などはそのまま残っているが,
例外ハンドラが SP をリセットするので単に消滅する.
レジスタに入っている結果なども, 同様に消滅する.)
---------------------------------------- -}
// Upon entry, the sp points to the return address returning into
// Java (interpreted or compiled) code; i.e., the return address
// becomes the throwing pc.
//
// Arguments pushed before the runtime call are still on the stack
// but the exception handler will reset the stack pointer ->
// ignore them. A potential result in registers can be ignored as
// well.
{- -------------------------------------------
(1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
コード生成: (デバッグ用の処理)
---------------------------------------- -}
#ifdef ASSERT
// make sure this code is only executed if there is a pending exception
{
Label L;
__ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t) NULL);
__ jcc(Assembler::notEqual, L);
__ stop("StubRoutines::forward exception: no pending exception (1)");
__ bind(L);
}
#endif
{- -------------------------------------------
(1) コード生成:
「SharedRuntime::exception_handler_for_return_address() を呼んで, 対応する例外ハンドラのアドレスを取得する.
---------------------------------------- -}
// compute exception handler into rbx
__ movptr(c_rarg0, Address(rsp, 0));
BLOCK_COMMENT("call exception_handler_for_return_address");
__ call_VM_leaf(CAST_FROM_FN_PTR(address,
SharedRuntime::exception_handler_for_return_address),
r15_thread, c_rarg0);
__ mov(rbx, rax);
{- -------------------------------------------
(1) コード生成:
「カレントスレッドの pending_exception フィールドから exception オブジェクトを取得し, rax レジスタに入れておく.
また, 例外発生時の PC を rdx に入れておく.」
---------------------------------------- -}
// setup rax & rdx, remove return address & clear pending exception
__ pop(rdx);
__ movptr(rax, Address(r15_thread, Thread::pending_exception_offset()));
{- -------------------------------------------
(1) コード生成:
「カレントスレッドの pending_exception フィールドをクリアする」
---------------------------------------- -}
__ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
{- -------------------------------------------
(1) (デバッグ用の処理) (#ifdef ASSERT 時にのみ実行)
コード生成: (デバッグ用の処理)
---------------------------------------- -}
#ifdef ASSERT
// make sure exception is set
{
Label L;
__ testptr(rax, rax);
__ jcc(Assembler::notEqual, L);
__ stop("StubRoutines::forward exception: no pending exception (2)");
__ bind(L);
}
#endif
{- -------------------------------------------
(1) コード生成:
「取得した例外ハンドラのアドレスにジャンプする」
---------------------------------------- -}
// continue at exception handler (return address removed)
// rax: exception
// rbx: exception handler
// rdx: throwing pc
__ verify_oop(rax);
__ jmp(rbx);
{- -------------------------------------------
(1) 以上で生成したコードの先頭アドレスをリターン
---------------------------------------- -}
return start;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.