hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
void TemplateTable::invokeinterface(int byte_no) {
{- -------------------------------------------
(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.