Top


定義場所(file name)

hotspot/src/share/vm/runtime/sharedRuntime.cpp

説明(description)

// 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.

名前(function name)

address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) {

本体部(body)

  {- -------------------------------------------
  (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.