Top


定義場所(file name)

hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp

名前(function name)

void TemplateTable::invokeinterface(int byte_no) {

本体部(body)

  {- -------------------------------------------
  (1) (assert) (See: TemplateTable::transition())
      ---------------------------------------- -}

      transition(vtos, vtos);

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

      assert(byte_no == f1_byte, "use this argument");

  {- -------------------------------------------
  (1) コード生成:
      「呼び出しに必要な前準備を行う」
      ---------------------------------------- -}

      prepare_invoke(rax, rbx, byte_no);

  {- -------------------------------------------
  (1) (この時点では, 各レジスタには以下の値が入っているはず)
      ---------------------------------------- -}

      // rax: Interface
      // rbx: index
      // rcx: receiver
      // rdx: flags

  {- -------------------------------------------
  (1) コード生成:
      「仕様上は, invokeinterface で java.lang.Object のメソッドを呼び出すことが可能なので, 
        そのケースについて確認しておく.
        (なお, javac を使った場合には, そういったコードが出されることはない)

        このケースに該当する場合は, TemplateTable::invokevirtual_helper() で
        生成するコードによって呼び出し処理を行う.」

      (該当する JavaVM 仕様の記述箇所は?? #TODO)
      ---------------------------------------- -}

      // Special case of invokeinterface called for virtual method of
      // java.lang.Object.  See cpCacheOop.cpp for details.
      // This code isn't produced by javac, but could be produced by
      // another compliant java compiler.
      Label notMethod;
      __ movl(r14, rdx);
      __ andl(r14, (1 << ConstantPoolCacheEntry::methodInterface));
      __ jcc(Assembler::zero, notMethod);

      invokevirtual_helper(rbx, rcx, rdx);
      __ bind(notMethod);

  {- -------------------------------------------
  (1) コード生成:
      「r14 の値を (上の処理で潰してしまったので) 元に戻しておく.
        また, receiver のクラスオブジェクトを rdx レジスタにロードしておく.」
      ---------------------------------------- -}

      // Get receiver klass into rdx - also a null check
      __ restore_locals(); // restore r14
      __ load_klass(rdx, rcx);

  {- -------------------------------------------
  (1) コード生成: (verify)
      ---------------------------------------- -}

      __ verify_oop(rdx);

  {- -------------------------------------------
  (1) コード生成:
      「method data pointer (mdp) の値を更新しておく」
      ---------------------------------------- -}

      // profile this call
      __ profile_virtual_call(rdx, r13, r14);

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

      Label no_such_interface, no_such_method;

  {- -------------------------------------------
  (1) コード生成:
      「呼び出し先となる methodOop を取得する.
        (なお, 処理途中で _interface フィールドが NULL の itableOffsetEntry を
         見つけた場合には, IncompatibleClassChangeError を出す.」
      ---------------------------------------- -}

      __ lookup_interface_method(// inputs: rec. class, interface, itable index
                                 rdx, rax, rbx,
                                 // outputs: method, scan temp. reg
                                 rbx, r13,
                                 no_such_interface);

  {- -------------------------------------------
  (1) (この時点では, 各レジスタには以下の値が入っているはず)
      ---------------------------------------- -}

      // rbx,: methodOop to call
      // rcx: receiver
      // Check for abstract method error
      // Note: This should be done more efficiently via a throw_abstract_method_error
      //       interpreter entry point and a conditional jump to it in case of a null
      //       method.

  {- -------------------------------------------
  (1) コード生成:
      「もし取得した methodOop が NULL だったら, no_such_method ラベルまでジャンプ
        (no_such_method ラベルは AbstractMethodError を出す処理パス. 後述)」
      ---------------------------------------- -}

      __ testptr(rbx, rbx);
      __ jcc(Assembler::zero, no_such_method);

  {- -------------------------------------------
  (1) コード生成:
      「実際の呼び出し処理を行う」
      ---------------------------------------- -}

      // do the call
      // rcx: receiver
      // rbx,: methodOop
      __ jump_from_interpreted(rbx, rdx);
      __ should_not_reach_here();

  {- -------------------------------------------
  (1) (以降は, 呼び出し処理中で例外が発生した場合の処理)
      (なお, きちんと例外ハンドリング処理ができるよう, 
       インタープリタ用のレジスタを正常な状態に戻しておくこと.)
      ---------------------------------------- -}

      // exception handling code follows...
      // note: must restore interpreter registers to canonical
      //       state for exception handling to work correctly!

  {- -------------------------------------------
  (1) (以下は, 取得した methodOop が NULL だった場合の処理)
      コード生成:
      「リターンアドレスや BCP 等を元に戻した後, AbstractMethodError を送出する」
      ---------------------------------------- -}

      __ bind(no_such_method);
      // throw exception
      __ pop(rbx);           // pop return address (pushed by prepare_invoke)
      __ restore_bcp();      // r13 must be correct for exception handler   (was destroyed)
      __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
      // the call_VM checks for exception, so we should never return here.
      __ should_not_reach_here();

  {- -------------------------------------------
  (1) (以下は, _interface フィールドが NULL の itableOffsetEntry があった場合の処理)
      コード生成:
      「リターンアドレスや BCP 等を元に戻した後, IncompatibleClassChangeError を送出する」
      ---------------------------------------- -}

      __ bind(no_such_interface);
      // throw exception
      __ pop(rbx);           // pop return address (pushed by prepare_invoke)
      __ restore_bcp();      // r13 must be correct for exception handler   (was destroyed)
      __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
      __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                       InterpreterRuntime::throw_IncompatibleClassChangeError));
      // the call_VM checks for exception, so we should never return here.
      __ should_not_reach_here();

  {- -------------------------------------------
  (1) リターン
      ---------------------------------------- -}

      return;
    }

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