hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
void TemplateTable::resolve_cache_and_index(int byte_no,
Register result,
Register Rcache,
Register index,
size_t index_size) {
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
const Register temp = rbx;
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert_different_registers(result, Rcache, index, temp);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
Label resolved;
{- -------------------------------------------
(1) InterpreterMacroAssembler::get_cache_and_index_at_bcp() を呼んで, 以下のようなコードを生成.
「現在箇所のバイトコード(bcp)に対応する CPCache エントリのアドレスを Rcache に取得.
(ただし, まだ対応する CPCache エントリのアドレスを作っていなかった場合は, ...#TODO が取得される)」
---------------------------------------- -}
__ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
{- -------------------------------------------
(1) 引数の byte_no に応じて以下の 2通りのコードを生成する.
どちらの場合も, ...#TODO
* f1_oop の場合:
「取得した CPCache エントリの f1 フィールドをロードし, NULL かどうかチェックする.
NULL でなければ(= 既にそのエントリは作成済みであれば), resolved ラベルまでジャンプする.
そうでなければ, このままフォールスルーして作成処理を行う.」
* それ以外の場合 (f1_byte または f2_byte):
「取得した CPCache エントリの ... かどうかチェックする. #TODO
同じであれば(= 既にそのエントリは作成済みであれば), resolved ラベルまでジャンプする.
そうでなければ, このままフォールスルーして作成処理を行う.」
---------------------------------------- -}
if (byte_no == f1_oop) {
// We are resolved if the f1 field contains a non-null object (CallSite, etc.)
// This kind of CP cache entry does not need to match the flags byte, because
// there is a 1-1 relation between bytecode type and CP entry type.
assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD)
__ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
__ testptr(result, result);
__ jcc(Assembler::notEqual, resolved);
} else {
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
assert(result == noreg, ""); //else change code for setting result
const int shift_count = (1 + byte_no) * BitsPerByte;
__ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
__ shrl(temp, shift_count);
// have we resolved this bytecode?
__ andl(temp, 0xFF);
__ cmpl(temp, (int) bytecode());
__ jcc(Assembler::equal, resolved);
}
{- -------------------------------------------
(1) (変数宣言など)
(entry は, まだ CPCache エントリが生成されてなかった場合に呼び出すべき関数 (CPCache エントリ生成用の関数).
以下の通り, 現在箇所のバイトコードに応じて呼び出す関数は変わる.)
---------------------------------------- -}
// resolve first time through
address entry;
switch (bytecode()) {
case Bytecodes::_getstatic:
case Bytecodes::_putstatic:
case Bytecodes::_getfield:
case Bytecodes::_putfield:
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put);
break;
case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
case Bytecodes::_invokeinterface:
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
break;
case Bytecodes::_invokedynamic:
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
break;
case Bytecodes::_fast_aldc:
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
break;
case Bytecodes::_fast_aldc_w:
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
break;
default:
ShouldNotReachHere();
break;
}
{- -------------------------------------------
(1) コード生成:
「CPCache エントリ生成用の関数(以下の entry)を呼び出す.
その後, 改めて get_cache_and_index_at_bcp() が生成したコードを実行し,
現在箇所のバイトコード(bcp)に対応する CPCache エントリのアドレスを Rcache に取得する.」
(もし...#TODO であれば, 以下のコードも生成しておく.
「取得しなおした CPCache エントリの f1 フィールドを, result レジスタにロードする.」)
---------------------------------------- -}
__ movl(temp, (int) bytecode());
__ call_VM(noreg, entry, temp);
// Update registers with resolved info
__ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
if (result != noreg)
__ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
{- -------------------------------------------
(1) (ここが resolved ラベルの位置.
CPCache エントリが既に生成されていた場合は, この地点まで飛んでくる)
---------------------------------------- -}
__ bind(resolved);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.