hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
// Lock object
//
// Args:
// c_rarg1: BasicObjectLock to be used for locking
//
// Kills:
// rax
// c_rarg0, c_rarg1, c_rarg2, c_rarg3, .. (param regs)
// rscratch1, rscratch2 (scratch regs)
void InterpreterMacroAssembler::lock_object(Register lock_reg) {
{- -------------------------------------------
(1) (この関数では, UseHeavyMonitors オプションの値に応じて 2通りのコードを生成)
---------------------------------------- -}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1");
{- -------------------------------------------
(1) コード生成: (こちらは, UseHeavyMonitors オプションが指定されている場合に生成するコード)
「(この場合は軽量ロック処理(fast-path の処理)は行わないので)
InterpreterRuntime::monitorenter() を呼び出して slow-path のコードにフォールバック」
---------------------------------------- -}
if (UseHeavyMonitors) {
call_VM(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
{- -------------------------------------------
(1) コード生成: (こちらは, UseHeavyMonitors オプションが指定されていない場合に生成するコード)
(この場合は以下で示すように,
まず fast-path の処理を行い, それがダメな場合に
InterpreterRuntime::monitorenter() にフォールバックするコードを生成)
---------------------------------------- -}
} else {
{- -------------------------------------------
(1.1) (変数宣言など)
---------------------------------------- -}
Label done;
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
const Register obj_reg = c_rarg3; // Will contain the oop
const int obj_offset = BasicObjectLock::obj_offset_in_bytes();
const int lock_offset = BasicObjectLock::lock_offset_in_bytes ();
const int mark_offset = lock_offset +
BasicLock::displaced_header_offset_in_bytes();
Label slow_case;
{- -------------------------------------------
(1.1) コード生成:
「ロック対象のオブジェクトの mark field を取得」
---------------------------------------- -}
// Load object pointer into obj_reg %c_rarg3
movptr(obj_reg, Address(lock_reg, obj_offset));
{- -------------------------------------------
(1.1) コード生成: (ただし, UseBiasedLocking オプションが指定されていない場合には, 不要なので生成しない)
「MacroAssembler::biased_locking_enter() が生成するコードにより, biased locking 処理を行う」
(なおこの場合, ロック確保が成功すれば done ラベルに分岐する.
失敗時にはこのままフォールスルーするか slow_case ラベルに分岐する)
---------------------------------------- -}
if (UseBiasedLocking) {
biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, done, &slow_case);
}
{- -------------------------------------------
(1.1) コード生成:
「(mark field | 1) という値を BasicLock に書き込む (mark field の退避処理)」
---------------------------------------- -}
// Load immediate 1 into swap_reg %rax
movl(swap_reg, 1);
// Load (object->mark() | 1) into swap_reg %rax
orptr(swap_reg, Address(obj_reg, 0));
// Save (object->mark() | 1) into BasicLock's displaced header
movptr(Address(lock_reg, mark_offset), swap_reg);
{- -------------------------------------------
(1.1) コード生成:
「まずは neutral だと想定して mark field を CAS で置き換える.
成功すれば (本当に neutral だったということで) ここでロック処理は終了(done ラベルに分岐する)」
---------------------------------------- -}
assert(lock_offset == 0,
"displached header must be first word in BasicObjectLock");
if (os::is_MP()) lock();
cmpxchgptr(lock_reg, Address(obj_reg, 0));
if (PrintBiasedLockingStatistics) {
cond_inc32(Assembler::zero,
ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr()));
}
jcc(Assembler::zero, done);
{- -------------------------------------------
(1.1) コード生成:
「CAS が成功しなかった場合は, 自分がロック済み (かつ stack-locked) かどうかを確認する.
そうだった場合にはここでロック処理は終了(done ラベルに分岐する).
(この場合 BasicLock には NULL を入れておく)」
---------------------------------------- -}
// Test if the oopMark is an obvious stack pointer, i.e.,
// 1) (mark & 7) == 0, and
// 2) rsp <= mark < mark + os::pagesize()
//
// These 3 tests can be done by evaluating the following
// expression: ((mark - rsp) & (7 - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant 3 bits clear.
// NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg
subptr(swap_reg, rsp);
andptr(swap_reg, 7 - os::vm_page_size());
// Save the test result, for recursive case, the result is zero
movptr(Address(lock_reg, mark_offset), swap_reg);
if (PrintBiasedLockingStatistics) {
cond_inc32(Assembler::zero,
ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr()));
}
jcc(Assembler::zero, done);
{- -------------------------------------------
(1.1) コード生成:
「それも成功しなかった場合は,
InterpreterRuntime::monitorenter() を呼び出して slow-path のコードにフォールバック」
(なお, ここが slow_case ラベルの位置)
---------------------------------------- -}
bind(slow_case);
// Call the runtime routine for slow case
call_VM(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
{- -------------------------------------------
(1.1) (ここが done ラベルの位置)
---------------------------------------- -}
bind(done);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.