hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
{- -------------------------------------------
(1) (assert) (See: TemplateTable::transition())
---------------------------------------- -}
transition(vtos, vtos);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
const Register cache = rcx;
const Register index = rdx;
const Register obj = c_rarg3;
const Register off = rbx;
const Register flags = rax;
const Register bc = c_rarg3; // uses same reg as obj, so don't mix them
{- -------------------------------------------
(1) TemplateTable::resolve_cache_and_index() を呼んで, 以下のようなコードを生成.
「現在箇所のバイトコード(bcp)に対応する CPCache エントリのアドレスを rcx(以下の cache) に取得する.
もし対応する CPCache エントリがまだ生成されていなければ, その生成も行う.」
---------------------------------------- -}
resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
{- -------------------------------------------
(1) コード生成: (JVMTI のフック点)
---------------------------------------- -}
jvmti_post_field_access(cache, index, is_static, false);
{- -------------------------------------------
(1) TemplateTable::load_field_cp_cache_entry() を呼んで, 以下のようなコードを生成.
「取得した CPCache エントリの中から, 実際のオフセット情報を rbx(以下の off) に取得.
また, 取得した CPCache エントリの中から, フラグ情報を rax(以下の flags) に取得.」
---------------------------------------- -}
load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
{- -------------------------------------------
(1) コード生成: (NULL チェック) & (verify)
---------------------------------------- -}
if (!is_static) {
// obj is on the stack
pop_and_check_object(obj);
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
const Address field(obj, off, Address::times_1);
Label Done, notByte, notInt, notShort, notChar,
notLong, notFloat, notObj, notDouble;
{- -------------------------------------------
(1) CPCache のエントリから型情報を取り出す.
---------------------------------------- -}
__ shrl(flags, ConstantPoolCacheEntry::tosBits);
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(btos == 0, "change code, btos != 0");
{- -------------------------------------------
(1) 以下, 型情報に応じた処理を行う.
(1) まず btos かどうかをチェック.
(1) 次に atos かどうかをチェック.
(1) 次に itos かどうかをチェック.
(1) 次に ctos かどうかをチェック.
(1) 次に stos かどうかをチェック.
(1) 次に ltos かどうかをチェック.
(1) 次に ftos かどうかをチェック.
(1) 以上のどれでもなければ dtos.
なお, それぞれの場合で高速版への rewrite 処理を行っている (See: [here](no7882vBO.html) for details)
そのため, ここのコードはそれぞれの箇所で最初の一回だけ実行される.
(なぜ static は最適化しない?? static は使われる比率が小さいから効果が低い?? #TODO)
---------------------------------------- -}
{- -------------------------------------------
(1.1) (ここが btos チェック)
---------------------------------------- -}
__ andl(flags, 0x0F);
__ jcc(Assembler::notZero, notByte);
{- -------------------------------------------
(1.1) (ここが btos の場合の処理)
---------------------------------------- -}
// btos
__ load_signed_byte(rax, field);
__ push(btos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (ここが atos チェック)
---------------------------------------- -}
__ bind(notByte);
__ cmpl(flags, atos);
__ jcc(Assembler::notEqual, notObj);
{- -------------------------------------------
(1.1) (ここが atos の場合の処理)
---------------------------------------- -}
// atos
__ load_heap_oop(rax, field);
__ push(atos);
if (!is_static) {
patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (ここが itos チェック)
---------------------------------------- -}
__ bind(notObj);
__ cmpl(flags, itos);
__ jcc(Assembler::notEqual, notInt);
{- -------------------------------------------
(1.1) (ここが itos の場合の処理)
---------------------------------------- -}
// itos
__ movl(rax, field);
__ push(itos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (ここが ctos チェック)
---------------------------------------- -}
__ bind(notInt);
__ cmpl(flags, ctos);
__ jcc(Assembler::notEqual, notChar);
{- -------------------------------------------
(1.1) (ここが ctos の場合の処理)
---------------------------------------- -}
// ctos
__ load_unsigned_short(rax, field);
__ push(ctos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (ここが stos チェック)
---------------------------------------- -}
__ bind(notChar);
__ cmpl(flags, stos);
__ jcc(Assembler::notEqual, notShort);
{- -------------------------------------------
(1.1) (ここが stos の場合の処理)
---------------------------------------- -}
// stos
__ load_signed_short(rax, field);
__ push(stos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (ここが ltos チェック)
---------------------------------------- -}
__ bind(notShort);
__ cmpl(flags, ltos);
__ jcc(Assembler::notEqual, notLong);
{- -------------------------------------------
(1.1) (ここが ltos の場合の処理)
---------------------------------------- -}
// ltos
__ movq(rax, field);
__ push(ltos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (ここが ftos チェック)
---------------------------------------- -}
__ bind(notLong);
__ cmpl(flags, ftos);
__ jcc(Assembler::notEqual, notFloat);
{- -------------------------------------------
(1.1) (ここが ftos の場合の処理)
---------------------------------------- -}
// ftos
__ movflt(xmm0, field);
__ push(ftos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
}
__ jmp(Done);
{- -------------------------------------------
(1.1) (以上のどれでもなければ dtos)
---------------------------------------- -}
__ bind(notFloat);
#ifdef ASSERT
__ cmpl(flags, dtos);
__ jcc(Assembler::notEqual, notDouble);
#endif
{- -------------------------------------------
(1.1) (ここが dtos の場合の処理)
---------------------------------------- -}
// dtos
__ movdbl(xmm0, field);
__ push(dtos);
// Rewrite bytecode to be faster
if (!is_static) {
patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
}
#ifdef ASSERT
__ jmp(Done);
__ bind(notDouble);
__ stop("Bad state");
#endif
{- -------------------------------------------
(1) (ここで終了)
(なお, 現状の x86 ではメモリバリアは不要なので張っていない)
---------------------------------------- -}
__ bind(Done);
// [jk] not needed currently
// volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadLoad |
// Assembler::LoadStore));
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.