hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp
address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
{- -------------------------------------------
(1) 型に応じた名前の BufferBlob を新規に作成し, そこにマシン語を書き出すための MacroAssembler も作成する.
---------------------------------------- -}
const char *name;
switch (type) {
case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
case T_BYTE: name = "jni_fast_GetByteField"; break;
case T_CHAR: name = "jni_fast_GetCharField"; break;
case T_SHORT: name = "jni_fast_GetShortField"; break;
case T_INT: name = "jni_fast_GetIntField"; break;
case T_LONG: name = "jni_fast_GetLongField"; break;
default: ShouldNotReachHere();
}
ResourceMark rm;
BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE);
CodeBuffer cbuf(blob);
MacroAssembler* masm = new MacroAssembler(&cbuf);
{- -------------------------------------------
(1) (ここからが生成するコードの始まり)
---------------------------------------- -}
address fast_entry = __ pc();
{- -------------------------------------------
(1) コード生成:
「SafepointSynchronize::safepoint_counter の値を取得し, 奇数かどうかをチェック.
奇数であれば slow までジャンプして slow case にフォールバック.」
---------------------------------------- -}
Label slow;
ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr());
__ mov32 (rcounter, counter);
__ mov (robj, c_rarg1);
__ testb (rcounter, 1);
__ jcc (Assembler::notZero, slow);
{- -------------------------------------------
(1) コード生成:
「(MP 環境であれば, ) robj を "robj ^ rcounter ^ rcounter" という値に更新する.」
(実質上何も変わらないが, rcounter に対する data dependency が生じる)
---------------------------------------- -}
if (os::is_MP()) {
__ xorptr(robj, rcounter);
__ xorptr(robj, rcounter); // obj, since
// robj ^ rcounter ^ rcounter == robj
// robj is data dependent on rcounter.
}
{- -------------------------------------------
(1) コード生成:
「(SafepointSynchronize::safepoint_counter が奇数でなかった場合には)
引数の Handle から実際のオブジェクトへのポインタを取得し,
計算したオフセット位置からのロードを行う.
ロードする bit 幅は, 型に応じて適切なものを選ぶ.」
(なお, ここのロード命令アドレスを speculative_load_pclist に登録する)
---------------------------------------- -}
__ movptr(robj, Address(robj, 0)); // *obj
__ mov (roffset, c_rarg2);
__ shrptr(roffset, 2); // offset
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
speculative_load_pclist[count] = __ pc();
switch (type) {
case T_BOOLEAN: __ movzbl (rax, Address(robj, roffset, Address::times_1)); break;
case T_BYTE: __ movsbl (rax, Address(robj, roffset, Address::times_1)); break;
case T_CHAR: __ movzwl (rax, Address(robj, roffset, Address::times_1)); break;
case T_SHORT: __ movswl (rax, Address(robj, roffset, Address::times_1)); break;
case T_INT: __ movl (rax, Address(robj, roffset, Address::times_1)); break;
case T_LONG: __ movq (rax, Address(robj, roffset, Address::times_1)); break;
default: ShouldNotReachHere();
}
{- -------------------------------------------
(1) コード生成:
「(MP 環境であれば SafepointSynchronize::safepoint_counter フィールドのアドレスを
ロードしてきたフィールド値と2回 xorptr した後)
再度 SafepointSynchronize::safepoint_counter の値を取得する.
値が変わっていれば, slow にジャンプして slow case へフォールバック.
変わっていなければ, このままリターンする.」
(この xorptr も実質上何も変わらないが, ロードしてきたフィールド値に対する data dependency が生じる)
---------------------------------------- -}
if (os::is_MP()) {
__ lea(rcounter_addr, counter);
// ca is data dependent on rax.
__ xorptr(rcounter_addr, rax);
__ xorptr(rcounter_addr, rax);
__ cmpl (rcounter, Address(rcounter_addr, 0));
} else {
__ cmp32 (rcounter, counter);
}
__ jcc (Assembler::notEqual, slow);
__ ret (0);
{- -------------------------------------------
(1) (ここから先は jni_GetXXXField() にフォールバックする処理)
(なお, slowcase_entry_pclist にはここのアドレスを登録する)
---------------------------------------- -}
slowcase_entry_pclist[count++] = __ pc();
__ bind (slow);
{- -------------------------------------------
(1) コード生成:
「対応する jni_Get<Primitive>Field_addr を末尾呼び出しする.」
---------------------------------------- -}
address slow_case_addr;
switch (type) {
case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
case T_BYTE: slow_case_addr = jni_GetByteField_addr(); break;
case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break;
case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break;
case T_INT: slow_case_addr = jni_GetIntField_addr(); break;
case T_LONG: slow_case_addr = jni_GetLongField_addr();
}
// tail call
__ jump (ExternalAddress(slow_case_addr));
{- -------------------------------------------
(1) 以上のコードを flush() し, 生成したコードのエントリポイントをリターン.
---------------------------------------- -}
__ flush ();
return fast_entry;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.