hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
// // Generate a fixed interpreter frame. This is identical setup for interpreted // methods and for native methods hence the shared code.
void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
{- -------------------------------------------
(1) (この関数が生成するコードは, 以下のような処理を行う)
---------------------------------------- -}
//
//
// The entry code sets up a new interpreter frame in 4 steps:
//
// 1) Increase caller's SP by for the extra local space needed:
// (check for overflow)
// Efficient implementation of xload/xstore bytecodes requires
// that arguments and non-argument locals are in a contigously
// addressable memory block => non-argument locals must be
// allocated in the caller's frame.
//
// 2) Create a new stack frame and register window:
// The new stack frame must provide space for the standard
// register save area, the maximum java expression stack size,
// the monitor slots (0 slots initially), and some frame local
// scratch locations.
//
// 3) The following interpreter activation registers must be setup:
// Lesp : expression stack pointer
// Lbcp : bytecode pointer
// Lmethod : method
// Llocals : locals pointer
// Lmonitors : monitor pointer
// LcpoolCache: constant pool cache
//
// 4) Initialize the non-argument locals if necessary:
// Non-argument locals may need to be initialized to NULL
// for GC to work. If the oop-map information is accurate
// (in the absence of the JSR problem), no initialization
// is necessary.
//
// (gri - 2/25/2000)
{- -------------------------------------------
(1) (変数宣言など)
(max_stack は, 呼び出されたメソッドの最大オペランドスタック長(expression stack size))
(extra_space はフレーム中に用意しないといけないプラットフォーム依存な領域の大きさ.
以下の 3つ(ネイティブメソッドでない場合は 2つ)の合計値となっている.
* frame::interpreter_frame_vm_local_words
フレーム内でインタープリタが作業用に使用する領域の大きさ
* frame::memory_parameter_word_sp_offset
window save area と第6引数までを格納できるスペース量
(Sparc の calling convention 通り)
* frame::interpreter_frame_extra_outgoing_argument_words
(ネイティブメソッドでなければ, この値は足されない)
ネイティブメソッドの場合に追加で渡すべき引数の数.
class と JNIEnv の 2つ. )
---------------------------------------- -}
const Address size_of_parameters(G5_method, methodOopDesc::size_of_parameters_offset());
const Address size_of_locals (G5_method, methodOopDesc::size_of_locals_offset());
const Address max_stack (G5_method, methodOopDesc::max_stack_offset());
int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong );
const int extra_space =
rounded_vm_local_words + // frame local scratch space
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
frame::memory_parameter_word_sp_offset + // register save area
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
const Register Glocals_size = G3;
const Register Otmp1 = O3;
const Register Otmp2 = O4;
{- -------------------------------------------
(1) (なお, call_stub が使ってしまっているため Lscratch は一時レジスタとしては使えない, とのこと)
---------------------------------------- -}
// Lscratch can't be used as a temporary because the call_stub uses
// it to assert that the stack frame was setup correctly.
{- -------------------------------------------
(1) (まず, 必要な局所変数領域の大きさを計算し, その分の領域を確保する処理を行う.
この際, 必要であれば呼び出し元の SP をずらす処理を行う)
(局所変数領域は引数を含むので, 呼び出し元のフレーム内に確保する必要がある.
詳細はフレーム構造を参照.)
---------------------------------------- -}
{- -------------------------------------------
(1.1) コード生成:
「引数の数を取得する」
---------------------------------------- -}
__ lduh( size_of_parameters, Glocals_size);
{- -------------------------------------------
(1.1) コード生成:
「Gargs の値を修正しておく」
(この時点では最後の引数を指しているが, 正しくは最初の引数を指すべき.
このため, 引数分だけ増加させておく.)
---------------------------------------- -}
// Gargs points to first local + BytesPerWord
// Set the saved SP after the register window save
//
assert_different_registers(Gargs, Glocals_size, Gframe_size, O5_savedSP);
__ sll(Glocals_size, Interpreter::logStackElementSize, Otmp1);
__ add(Gargs, Otmp1, Gargs);
{- -------------------------------------------
(1.1) (以下で, 新しく確保するスタックフレームの大きさを計算して Gframe_size に格納する.
この処理は, ネイティブメソッドかどうかで生成するコードが異なる.
ネイティブメソッドでない場合には, 呼び出し元の SP をずらす処理も行う.)
---------------------------------------- -}
{- -------------------------------------------
(1.1) コード生成: (これは, ネイティブメソッドの場合のコード)
「新しく確保するスタックフレームの大きさを計算する.
結果は Gframe_size に格納.」
(なお, ここでは大きさは以下の用に計算している.
スタックフレームの大きさ = round_to(レジスタに載らない引数の数 + extra_space) * BytesPerWord)
---------------------------------------- -}
if (native_call) {
__ calc_mem_param_words( Glocals_size, Gframe_size );
__ add( Gframe_size, extra_space, Gframe_size);
__ round_to( Gframe_size, WordsPerLong );
__ sll( Gframe_size, LogBytesPerWord, Gframe_size );
} else {
{- -------------------------------------------
(1.1) コード生成: (これは, ネイティブメソッドでない場合のコード)
「引数分を引いた局所変数領域の大きさを計算しておく.
結果は Glocals_size に格納」
---------------------------------------- -}
//
// Compute number of locals in method apart from incoming parameters
//
__ lduh( size_of_locals, Otmp1 );
__ sub( Otmp1, Glocals_size, Glocals_size );
__ round_to( Glocals_size, WordsPerLong );
__ sll( Glocals_size, Interpreter::logStackElementSize, Glocals_size );
{- -------------------------------------------
(1.1) コード生成: (これは, ネイティブメソッドでない場合のコード)
「新しく確保するスタックフレームの大きさを計算する.
結果は Gframe_size に格納.」
(なお, ここでは大きさは以下の用に計算している.
round_to(max_stack + extra_space) * BytesPerWord)
---------------------------------------- -}
// see if the frame is greater than one page in size. If so,
// then we need to verify there is enough stack space remaining
// Frame_size = (max_stack + extra_space) * BytesPerWord;
__ lduh( max_stack, Gframe_size );
__ add( Gframe_size, extra_space, Gframe_size );
__ round_to( Gframe_size, WordsPerLong );
__ sll( Gframe_size, Interpreter::logStackElementSize, Gframe_size);
{- -------------------------------------------
(1.1) コード生成: (これは, ネイティブメソッドでない場合のコード)
「InterpreterGenerator::generate_stack_overflow_check() が生成するコードにより,
stack overflow のチェックを行う.
もしスタックに空きがなければ, StackOverflowError.」
(なお, この処理の間だけ Gframe_size の値を Glocals_size 分だけ増加させている.
これは, この後で Glocals_size 分だけ SP をずらすことから,
実質的には Gframe_size + Glocals_size 分だけ確保することになるため.
stack banging が終わったら, また元の値に戻している)
---------------------------------------- -}
// Add in java locals size for stack overflow check only
__ add( Gframe_size, Glocals_size, Gframe_size );
const Register Otmp2 = O4;
assert_different_registers(Otmp1, Otmp2, O5_savedSP);
generate_stack_overflow_check(Gframe_size, Otmp1, Otmp2);
__ sub( Gframe_size, Glocals_size, Gframe_size);
{- -------------------------------------------
(1.1) コード生成: (これは, ネイティブメソッドでない場合のコード)
「(引数を除いた)局所変数分だけ, 呼び出し元の SP の値をずらしておく」
(なお, 当然ながら O5_savedSP はずらさない)
---------------------------------------- -}
//
// bump SP to accomodate the extra locals
//
__ sub( SP, Glocals_size, SP );
}
{- -------------------------------------------
(1) (ここまでが, 局所変数領域の大きさの計算処理, 及び局所変数領域の確保処理)
---------------------------------------- -}
{- -------------------------------------------
(1) コード生成:
「save 命令を使ってフレームを確保する(= SPをずらす)
(同時に, レジスタの退避も行う)」
(確保量は, 上で計算した Gframe_size 分)
---------------------------------------- -}
//
// now set up a stack frame with the size computed above
//
__ neg( Gframe_size );
__ save( SP, Gframe_size, SP );
{- -------------------------------------------
(1) コード生成:
「Template Interpreter の実行に必要なレジスタの値をセットする.
(Lesp, Lbcp, Lmethod, Llocals, Lmonitors, LcpoolCache)」
---------------------------------------- -}
//
// now set up all the local cache registers
//
// NOTE: At this point, Lbyte_code/Lscratch has been modified. Note
// that all present references to Lbyte_code initialize the register
// immediately before use
if (native_call) {
__ mov(G0, Lbcp);
} else {
__ ld_ptr(G5_method, methodOopDesc::const_offset(), Lbcp);
__ add(Lbcp, in_bytes(constMethodOopDesc::codes_offset()), Lbcp);
}
__ mov( G5_method, Lmethod); // set Lmethod
__ get_constant_pool_cache( LcpoolCache ); // set LcpoolCache
__ sub(FP, rounded_vm_local_words * BytesPerWord, Lmonitors ); // set Lmonitors
#ifdef _LP64
__ add( Lmonitors, STACK_BIAS, Lmonitors ); // Account for 64 bit stack bias
#endif
__ sub(Lmonitors, BytesPerWord, Lesp); // set Lesp
// setup interpreter activation registers
__ sub(Gargs, BytesPerWord, Llocals); // set Llocals
{- -------------------------------------------
(1) コード生成: (ただし, ProfileInterpreter オプションが指定されていない場合は, 不要なので生成しない)
「InterpreterMacroAssembler::set_method_data_pointer() が生成するコードにより
ImethodDataPtr レジスタの値をセットしておく.
(もし methodDataOop が生成されていれば,
DataLayout へのポインタがセットされる.
まだ methodDataOop が生成されていないメソッドの場合には,
ImethodDataPtr の値は NULL になる) 」
---------------------------------------- -}
if (ProfileInterpreter) {
#ifdef FAST_DISPATCH
// FAST_DISPATCH and ProfileInterpreter are mutually exclusive since
// they both use I2.
assert(0, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive");
#endif // FAST_DISPATCH
__ set_method_data_pointer();
}
{- -------------------------------------------
(1) (上記のコメントには, 最後に「必要があれば, non-argument locals に対して初期値を設定しておく」と書かれていたが,
ここにはそういったコードはない模様)
---------------------------------------- -}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.