hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
TosState incoming_state = state;
Label cont;
{- -------------------------------------------
(1) ?? (どこからも使われていないような... #TODO)
---------------------------------------- -}
address compiled_entry = __ pc();
{- -------------------------------------------
(1) (ここからが生成するコードの始まり)
---------------------------------------- -}
address entry = __ pc();
{- -------------------------------------------
(1) コード生成: (ただし, 32bit 環境でかつ C2 利用時でない場合には, 不要なので生成しない)
「32bit 環境では long 値だけは扱いが特殊なので調整しておく.」
(正確に言うと, 32bit 環境では C2 とインタープリタで使うレジスタがずれている.
C2 は G1 を使うがインタープリタは O0 と O1 を使う.)
---------------------------------------- -}
#if !defined(_LP64) && defined(COMPILER2)
// All return values are where we want them, except for Longs. C2 returns
// longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1.
// Since the interpreter will return longs in G1 and O0/O1 in the 32bit
// build even if we are returning from interpreted we just do a little
// stupid shuffing.
// Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to
// do this here. Unfortunately if we did a rethrow we'd see an machepilog node
// first which would move g1 -> O0/O1 and destroy the exception we were throwing.
if (incoming_state == ltos) {
__ srl (G1, 0, O1);
__ srlx(G1, 32, O0);
}
#endif // !_LP64 && COMPILER2
{- -------------------------------------------
(1) ?? (この cont ラベルはどこからも使われていないような... #TODO)
---------------------------------------- -}
__ bind(cont);
{- -------------------------------------------
(1) コード生成:
「SP を Llast_SP の値に復帰させる」
---------------------------------------- -}
// The callee returns with the stack possibly adjusted by adapter transition
// We remove that possible adjustment here.
// All interpreter local registers are untouched. Any result is passed back
// in the O0/O1 or float registers. Before continuing, the arguments must be
// popped from the java expression stack; i.e., Lesp must be adjusted.
__ mov(Llast_SP, SP); // Remove any adapter added stack space.
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Label L_got_cache, L_giant_index;
const Register cache = G3_scratch;
const Register size = G1_scratch;
{- -------------------------------------------
(1) コード生成: (ただし, EnableInvokeDynamic オプションが指定されていない場合には, 不要なので生成しない)
「もしリターンしてきたのが invokedynamic で呼び出されたメソッドからだった場合,
L_giant_index にジャンプする.
(L_giant_index は, get_cache_and_index_at_bcp() で CPCache entry を取得する際に,
通常よりも大きな index size を使う処理パス.
CPCache entry を取得した後は元のパスに合流する.)」
---------------------------------------- -}
if (EnableInvokeDynamic) {
__ ldub(Address(Lbcp, 0), G1_scratch); // Load current bytecode.
__ cmp(G1_scratch, Bytecodes::_invokedynamic);
__ br(Assembler::equal, false, Assembler::pn, L_giant_index);
__ delayed()->nop();
}
{- -------------------------------------------
(1) コード生成:
「Lesp レジスタの値を元に戻す
(メソッド呼び出し後には積んであった引数は消すべきなので,
引数の量を計算し, その分だけ Lesp の値を増やす)」
---------------------------------------- -}
__ get_cache_and_index_at_bcp(cache, G1_scratch, 1);
__ bind(L_got_cache);
__ ld_ptr(cache, constantPoolCacheOopDesc::base_offset() +
ConstantPoolCacheEntry::flags_offset(), size);
__ and3(size, 0xFF, size); // argument size in words
__ sll(size, Interpreter::logStackElementSize, size); // each argument size in bytes
__ add(Lesp, size, Lesp); // pop arguments
{- -------------------------------------------
(1) コード生成:
「dispatch_next() が生成するコードで,
メソッド呼び出しの次のバイトコードに対応するテンプレートへとジャンプする」
---------------------------------------- -}
__ dispatch_next(state, step);
{- -------------------------------------------
(1) コード生成: (ただし, EnableInvokeDynamic オプションが指定されていない場合には, 不要なので生成しない)
「L_giant_index ラベルに対応する飛び先を生成する.
get_cache_and_index_at_bcp() が生成するコードで
CPCache entry を取得した後,
上の L_got_cache 以降のパスに合流」
---------------------------------------- -}
// out of the main line of code...
if (EnableInvokeDynamic) {
__ bind(L_giant_index);
__ get_cache_and_index_at_bcp(cache, G1_scratch, 1, sizeof(u4));
__ ba(false, L_got_cache);
__ delayed()->nop();
}
{- -------------------------------------------
(1) 以上で生成したコードの先頭アドレスをリターン.
---------------------------------------- -}
return entry;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.