Top


定義場所(file name)

hotspot/src/share/vm/interpreter/linkResolver.cpp

説明(description)

// throws runtime exceptions

名前(function name)

void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
                                                  methodHandle resolved_method,
                                                  KlassHandle resolved_klass,
                                                  Handle recv,
                                                  KlassHandle recv_klass,
                                                  bool check_null_and_abstract,
                                                  TRAPS) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      // setup default return values
      int vtable_index = methodOopDesc::invalid_vtable_index;
      methodHandle selected_method;

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      assert(recv.is_null() || recv->is_oop(), "receiver is not an oop");

  {- -------------------------------------------
  (1) check_null_and_abstract 引数が true の場合はチェックを行う.
      レシーバーが null であれば NullPointerException.
      ---------------------------------------- -}

      // runtime method resolution
      if (check_null_and_abstract && recv.is_null()) { // check if receiver exists
        THROW(vmSymbols::java_lang_NullPointerException());
      }

  {- -------------------------------------------
  (1) (assert)
      ---------------------------------------- -}

      // Virtual methods cannot be resolved before its klass has been linked, for otherwise the methodOop's
      // has not been rewritten, and the vtable initialized.
      assert(instanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");

      // Virtual methods cannot be resolved before its klass has been linked, for otherwise the methodOop's
      // has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since
      // a missing receiver might result in a bogus lookup.
      assert(instanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");

  {- -------------------------------------------
  (1) (局所変数の初期化)
      #TODO
      ---------------------------------------- -}

      // do lookup based on receiver klass using the vtable index
      if (resolved_method->method_holder()->klass_part()->is_interface()) { // miranda method
        vtable_index = vtable_index_of_miranda_method(resolved_klass,
                               resolved_method->name(),
                               resolved_method->signature(), CHECK);
        assert(vtable_index >= 0 , "we should have valid vtable index at this point");

        instanceKlass* inst = instanceKlass::cast(recv_klass());
        selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
      } else {
        // at this point we are sure that resolved_method is virtual and not
        // a miranda method; therefore, it must have a valid vtable index.
        vtable_index = resolved_method->vtable_index();
        // We could get a negative vtable_index for final methods,
        // because as an optimization they are they are never put in the vtable,
        // unless they override an existing method.
        // If we do get a negative, it means the resolved method is the the selected
        // method, and it can never be changed by an override.
        if (vtable_index == methodOopDesc::nonvirtual_vtable_index) {
          assert(resolved_method->can_be_statically_bound(), "cannot override this method");
          selected_method = resolved_method;
        } else {
          // recv_klass might be an arrayKlassOop but all vtables start at
          // the same place. The cast is to avoid virtual call and assertion.
          instanceKlass* inst = (instanceKlass*)recv_klass()->klass_part();
          selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index));
        }
      }

  {- -------------------------------------------
  (1) もし対象のメソッドが定義されていなければ AbstractMethodError.
      ---------------------------------------- -}

      // check if method exists
      if (selected_method.is_null()) {
        ResourceMark rm(THREAD);
        THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
                  methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
                                                          resolved_method->name(),
                                                          resolved_method->signature()));
      }

  {- -------------------------------------------
  (1) check_null_and_abstract 引数が true の場合はチェックを行う.
      解決結果が abstract method であれば AbstractMethodError.
      ---------------------------------------- -}

      // check if abstract
      if (check_null_and_abstract && selected_method->is_abstract()) {
        ResourceMark rm(THREAD);
        THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
                  methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
                                                          selected_method->name(),
                                                          selected_method->signature()));
      }

  {- -------------------------------------------
  (1) CallInfo::set_virtual() を呼んで, 
      引数で渡された CallInfo オブジェクト内に
      解決結果をセットする
      ---------------------------------------- -}

      // setup result
      result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.