hotspot/src/share/vm/runtime/sharedRuntime.cpp
// Exception handling accross interpreter/compiler boundaries
//
// exception_handler_for_return_address(...) returns the continuation address.
// The continuation address is the entry point of the exception handler of the
// previous frame depending on the return address.
address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address));
{- -------------------------------------------
(1) #TODO
---------------------------------------- -}
// Reset method handle flag.
thread->set_is_method_handle_return(false);
{- -------------------------------------------
(1) 例外が発生したアドレスが nmethod 内を指している場合 (= CodeCache::find_blob() で NULL ではない値が返される場合),
以下のどちらかが例外ハンドラになる.
適切な方をリターン.
* ...#TODO の場合:
(deopt 用の処理)
(これは new_array_C のような gen_stub で作った stub の中で例外が起きた際にくるパスっぽい. (他にもここにくるパスはある??) #TODO)
SharedRuntime::deopt_blob()->unpack_with_exception()
* それ以外の場合:
nmethod::exception_begin() が返すアドレス.
---------------------------------------- -}
// The fastest case first
CodeBlob* blob = CodeCache::find_blob(return_address);
nmethod* nm = (blob != NULL) ? blob->as_nmethod_or_null() : NULL;
if (nm != NULL) {
// Set flag if return address is a method handle call site.
thread->set_is_method_handle_return(nm->is_method_handle_return(return_address));
// native nmethods don't have exception handlers
assert(!nm->is_native_method(), "no exception handler");
assert(nm->header_begin() != nm->exception_begin(), "no exception handler");
if (nm->is_deopt_pc(return_address)) {
return SharedRuntime::deopt_blob()->unpack_with_exception();
} else {
return nm->exception_begin();
}
}
{- -------------------------------------------
(1) 例外が発生したアドレスがコールスタブ内 (= StubRoutines::call_stub() が指しているコード内) の場合は,
StubRoutines::catch_exception_entry() が指しているアドレスをリターン.
---------------------------------------- -}
// Entry code
if (StubRoutines::returns_to_call_stub(return_address)) {
return StubRoutines::catch_exception_entry();
}
{- -------------------------------------------
(1) 例外が発生したアドレスがインタープリタ内を指している場合は,
Interpreter::rethrow_exception_entry() が指しているアドレスをリターン.
---------------------------------------- -}
// Interpreted code
if (Interpreter::contains(return_address)) {
return Interpreter::rethrow_exception_entry();
}
{- -------------------------------------------
(1) #TODO
(Ricochet_Blob は, SharedRuntime::generate_ricochet_blob() で生成されているスタブ.
何に使われるもの?? MethodHandle 系のような気もするが... #TODO)
---------------------------------------- -}
// Ricochet frame unwind code
if (SharedRuntime::ricochet_blob() != NULL && SharedRuntime::ricochet_blob()->returns_to_bounce_addr(return_address)) {
return SharedRuntime::ricochet_blob()->exception_addr();
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
guarantee(blob == NULL || !blob->is_runtime_stub(), "caller should have skipped stub");
guarantee(!VtableStubs::contains(return_address), "NULL exceptions in vtables should have been handled already!");
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
#ifndef PRODUCT
{ ResourceMark rm;
tty->print_cr("No exception handler found for exception at " INTPTR_FORMAT " - potential problems:", return_address);
tty->print_cr("a) exception happened in (new?) code stubs/buffers that is not handled here");
tty->print_cr("b) other problem");
}
#endif // PRODUCT
{- -------------------------------------------
(1) (以下のパスに来ることはあり得ない)
(もし来てしまったら HotSpot 内のバグ)
---------------------------------------- -}
ShouldNotReachHere();
return NULL;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.