hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
Register branch_bcp,
Register Rtmp ) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Label did_not_overflow;
Label overflow_with_error;
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert_different_registers(backedge_count, Rtmp, branch_bcp);
assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
{- -------------------------------------------
(1) コード生成:
「InvocationCounter::InterpreterBackwardBranchLimit と現在の値を比較し,
越えてなければ did_not_overflow ラベルまで飛ぶ.」
---------------------------------------- -}
AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
load_contents(limit, Rtmp);
cmp(backedge_count, Rtmp);
br(Assembler::lessUnsigned, false, Assembler::pt, did_not_overflow);
delayed()->nop();
{- -------------------------------------------
(1) コード生成: (ただし, ProfileInterpreter オプションが指定されていない場合には行わない)
「ProfileInterpreter 指定時には frequency_counter_overflow() がカウンタの値をクリアしないので,
一度しきい値を越えると(既に JIT compiler が作業中なのに)連続してコンパイル要求を出すことになりかねない.
そこで, overflow_frequency という間隔(今は1024)につき1度だけ呼ばれるよう調整しておく.
(それ以外の1023回は, 何もせず did_not_overflow ラベルに飛ぶだけにする)」
---------------------------------------- -}
// When ProfileInterpreter is on, the backedge_count comes from the
// methodDataOop, which value does not get reset on the call to
// frequency_counter_overflow(). To avoid excessive calls to the overflow
// routine while the method is being compiled, add a second test to make sure
// the overflow function is called only once every overflow_frequency.
if (ProfileInterpreter) {
const int overflow_frequency = 1024;
andcc(backedge_count, overflow_frequency-1, Rtmp);
brx(Assembler::notZero, false, Assembler::pt, did_not_overflow);
delayed()->nop();
}
{- -------------------------------------------
(1) コード生成:
「InterpreterRuntime::frequency_counter_overflow() を呼び出して JIT コンパイル処理を開始する.」
---------------------------------------- -}
// overflow in loop, pass branch bytecode
set(6,Rtmp);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), branch_bcp, Rtmp);
{- -------------------------------------------
(1) コード生成:
「もし InterpreterRuntime::frequency_counter_overflow() の返り値が NULL だったら,
(まだ JIT 生成されたコードがないということなので) overflow_with_error ラベルまで飛ぶ.
また, nmethod が既に invalidate されていた場合も, overflow_with_error ラベルまで飛ぶ.」
---------------------------------------- -}
// Was an OSR adapter generated?
// O0 = osr nmethod
tst(O0);
brx(Assembler::zero, false, Assembler::pn, overflow_with_error);
delayed()->nop();
// Has the nmethod been invalidated already?
ld(O0, nmethod::entry_bci_offset(), O2);
cmp(O2, InvalidOSREntryBci);
br(Assembler::equal, false, Assembler::pn, overflow_with_error);
delayed()->nop();
{- -------------------------------------------
(1) (ここまで来たら, JIT 生成された nmethod が得られたということになる)
---------------------------------------- -}
// migrate the interpreter frame off of the stack
{- -------------------------------------------
(1) コード生成:
「SharedRuntime::OSR_migration_begin() を呼んで,
interpreter frame 中の局所変数とモニタを C ヒープ上に取ったバッファに退避する.
(呼び出しの前後で G2_thread や O0(に入っている nmethod) の退避復帰を行っている)」
---------------------------------------- -}
mov(G2_thread, L7);
// save nmethod
mov(O0, L6);
set_last_Java_frame(SP, noreg);
call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), L7);
reset_last_Java_frame();
mov(L7, G2_thread);
{- -------------------------------------------
(1) コード生成:
「nmethod や SharedRuntime::OSR_migration_begin() が返したバッファを I0/I1 に退避してから,
restore 命令で interpreter frame を削除する.」
---------------------------------------- -}
// move OSR nmethod to I1
mov(L6, I1);
// OSR buffer to I0
mov(O0, I0);
// remove the interpreter frame
restore(I5_savedSP, 0, SP);
{- -------------------------------------------
(1) コード生成:
「nmethod からエントリポイントを取得し, osr コードにジャンプする.」
---------------------------------------- -}
// Jump to the osr code.
ld_ptr(O1, nmethod::osr_entry_point_offset(), O2);
jmp(O2, G0);
delayed()->nop();
{- -------------------------------------------
(1) コード生成:
「(ここが overflow_with_error ラベルの位置)」
(nmethod が得られなかった場合はここまでジャンプする)
---------------------------------------- -}
bind(overflow_with_error);
bind(did_not_overflow);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.