hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
// Call an accessor method (assuming it is resolved, otherwise drop into
// vanilla (slow path) entry
// Generates code to elide accessor methods
// Uses G3_scratch and G1_scratch as scratch
address InterpreterGenerator::generate_accessor_entry(void) {
{- -------------------------------------------
(1) (この関数は, 以下のような典型的なアクセサメソッドの処理を高速化するためのもの.
_aload_0, _(i|a)getfield, _(i|a)return
なお, この高速版のコードが使えるのは
getfield が resolve 済みで有り, 第一引数(this)が NULL ではない場合.
このため, これらの条件を最初にチェックしている)
---------------------------------------- -}
// Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof;
// parameter size = 1
// Note: We can only use this code if the getfield has been resolved
// and if we don't have a null-pointer exception => check for
// these conditions first and use slow path if necessary.
{- -------------------------------------------
(1) (ここからが生成するコードの始まり)
---------------------------------------- -}
address entry = __ pc();
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Label slow_path;
{- -------------------------------------------
(1) UseFastAccessorMethods オプションが指定されている場合には,
以下のコードを生成し, そのエントリポイントのアドレスをリターンする.
(そうでない場合には, 単に NULL をリターンするだけ)
(ただし現状では UseFastAccessorMethods オプションが指定されている場合でも,
UseCompressedOops オプションが指定されていると
コード生成は行わない模様.)
---------------------------------------- -}
// XXX: for compressed oops pointer loading and decoding doesn't fit in
// delay slot and damages G1
if ( UseFastAccessorMethods && !UseCompressedOops ) {
{- -------------------------------------------
(1.1) コード生成:
「Safepoint 処理中かどうかをチェックする (= SafepointSynchronize::address_of_state を確認).
もし Safepoint 停止の要求が出ていれば, slow_path ラベルにジャンプして停止処理を行う.」
---------------------------------------- -}
// Check if we need to reach a safepoint and generate full interpreter
// frame if so.
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
__ load_contents(sync_state, G3_scratch);
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
__ br(Assembler::notEqual, false, Assembler::pn, slow_path);
__ delayed()->nop();
{- -------------------------------------------
(1.1) コード生成:
「第一引数(this)が NULL かどうかを確認する.
もし NULL だった場合は, slow_path ラベルにジャンプして通常処理にフォールバック.」
---------------------------------------- -}
// Check if local 0 != NULL
__ ld_ptr(Gargs, G0, Otos_i ); // get local 0
__ tst(Otos_i); // check if local 0 == NULL and go the slow path
__ brx(Assembler::zero, false, Assembler::pn, slow_path);
__ delayed()->nop();
{- -------------------------------------------
(1.1) コード生成:
「アクセス対象のフィールドが resolve 済みかどうかをチェックする.
まだ resolve されてなかった場合は, slow_path ラベルにジャンプして通常処理にフォールバック.」
---------------------------------------- -}
// read first instruction word and extract bytecode @ 1 and index @ 2
// get first 4 bytes of the bytecodes (big endian!)
__ ld_ptr(G5_method, methodOopDesc::const_offset(), G1_scratch);
__ ld(G1_scratch, constMethodOopDesc::codes_offset(), G1_scratch);
// move index @ 2 far left then to the right most two bytes.
__ sll(G1_scratch, 2*BitsPerByte, G1_scratch);
__ srl(G1_scratch, 2*BitsPerByte - exact_log2(in_words(
ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch);
// get constant pool cache
__ ld_ptr(G5_method, methodOopDesc::constants_offset(), G3_scratch);
__ ld_ptr(G3_scratch, constantPoolOopDesc::cache_offset_in_bytes(), G3_scratch);
// get specific constant pool cache entry
__ add(G3_scratch, G1_scratch, G3_scratch);
// Check the constant Pool cache entry to see if it has been resolved.
// If not, need the slow path.
ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::indices_offset(), G1_scratch);
__ srl(G1_scratch, 2*BitsPerByte, G1_scratch);
__ and3(G1_scratch, 0xFF, G1_scratch);
__ cmp(G1_scratch, Bytecodes::_getfield);
__ br(Assembler::notEqual, false, Assembler::pn, slow_path);
__ delayed()->nop();
{- -------------------------------------------
(1.1) コード生成:
「対応する CPCache entry から, アクセス対象であるフィールドの型とオフセットを取得」
---------------------------------------- -}
// Get the type and return field offset from the constant pool cache
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), G1_scratch);
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), G3_scratch);
{- -------------------------------------------
(1.1) コード生成:
「取得した型に応じて適切なロード命令を実行し, フィールドの値を取得する
(ロード命令のオフセットとして, 上で取得したオフセット値を使用)」
なお, 型は次の順序で調べている.
atos, itos, stos, ctos, btos,
---------------------------------------- -}
Label xreturn_path;
// Need to differentiate between igetfield, agetfield, bgetfield etc.
// because they are different sizes.
// Get the type from the constant pool cache
__ srl(G1_scratch, ConstantPoolCacheEntry::tosBits, G1_scratch);
// Make sure we don't need to mask G1_scratch for tosBits after the above shift
ConstantPoolCacheEntry::verify_tosBits();
__ cmp(G1_scratch, atos );
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ld_ptr(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, itos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ld(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, stos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ldsh(Otos_i, G3_scratch, Otos_i);
__ cmp(G1_scratch, ctos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->lduh(Otos_i, G3_scratch, Otos_i);
#ifdef ASSERT
__ cmp(G1_scratch, btos);
__ br(Assembler::equal, true, Assembler::pt, xreturn_path);
__ delayed()->ldsb(Otos_i, G3_scratch, Otos_i);
__ should_not_reach_here();
#endif
__ ldsb(Otos_i, G3_scratch, Otos_i);
__ bind(xreturn_path);
{- -------------------------------------------
(1.1) コード生成:
「SP を O5_savedSP の値に復帰させつつ, リターン」
---------------------------------------- -}
// _ireturn/_areturn
__ retl(); // return from leaf routine
__ delayed()->mov(O5_savedSP, SP);
{- -------------------------------------------
(1.1) コード生成:
「高速処理が不可能な状況であれば,
InterpreterGenerator::generate_normal_entry() が生成する通常パスにフォールバック」
---------------------------------------- -}
// Generate regular method entry
__ bind(slow_path);
(void) generate_normal_entry(false);
return entry;
}
return NULL;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.