hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
// Miscelaneous helper routines
// Store an oop (or NULL) at the address described by obj.
// If val == noreg this means store a NULL
static void do_oop_store(InterpreterMacroAssembler* _masm,
Address obj,
Register val,
BarrierSet::Name barrier,
bool precise) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(val == noreg || val == rax, "parameter is just for looks");
{- -------------------------------------------
(1) barrier set の種別 (= GC アルゴリズムの種別) に応じて, 以下の3種類のケースが実装されている.
* G1GC の場合 (BarrierSet::G1SATBCT または BarrierSet::G1SATBCTLogging の場合)
* G1GC 以外の場合 (BarrierSet::CardTableModRef または BarrierSet::CardTableExtension の場合)
* ??の場合 (BarrierSet::ModRef または BarrierSet::Other の場合)
(なお, 正確には上記以外の場合というパスも書かれているが,
Should_Not_Reach_Here() になるだけ.)
(sparc 版では BarrierSet::ModRef や BarrierSet::Other の場合も Should_Not_Reach_Here() だったが, なぜ違う?? #TODO)
---------------------------------------- -}
switch (barrier) {
{- -------------------------------------------
(1) (以下は G1GC の場合のパス)
---------------------------------------- -}
#ifndef SERIALGC
case BarrierSet::G1SATBCT:
case BarrierSet::G1SATBCTLogging:
{
{- -------------------------------------------
(1.1) コード生成:
「rdx レジスタに対象のオブジェクト(obj 引数)のアドレスをセットする」
---------------------------------------- -}
// flatten object address if needed
if (obj.index() == noreg && obj.disp() == 0) {
if (obj.base() != rdx) {
__ movq(rdx, obj.base());
}
} else {
__ leaq(rdx, obj);
}
{- -------------------------------------------
(1.1) コード生成:
「MacroAssembler::g1_write_barrier_pre() が生成するコードにより,
SATB 用の Write Barrier 処理を (その必要があれば) 実行する.」
---------------------------------------- -}
__ g1_write_barrier_pre(rdx /* obj */,
rbx /* pre_val */,
r15_thread /* thread */,
r8 /* tmp */,
val != noreg /* tosca_live */,
false /* expand_call */);
{- -------------------------------------------
(1.1) コード生成:
「MacroAssembler::store_heap_oop() または
MacroAssembler::store_heap_oop_null() が生成するコードにより,
対象のポインタ値の書き換えを行う.
(書き込むポインタ値が NULL でない場合には MacroAssembler::store_heap_oop(),
NULL の場合には MacroAssembler::store_heap_oop_null() を使用)
また, 書き込むポインタ値が NULL でない場合には,
MacroAssembler::g1_write_barrier_post() が生成するコードにより,
書き換え箇所に対応する Barrier Set 中の値を dirty にする」
(NULL の場合には, コード生成時点で記録の必要が無いと保証できる)
---------------------------------------- -}
if (val == noreg) {
__ store_heap_oop_null(Address(rdx, 0));
} else {
__ store_heap_oop(Address(rdx, 0), val);
__ g1_write_barrier_post(rdx /* store_adr */,
val /* new_val */,
r15_thread /* thread */,
r8 /* tmp */,
rbx /* tmp2 */);
}
}
break;
#endif // SERIALGC
{- -------------------------------------------
(1) (以下は G1GC 以外の場合のパス)
---------------------------------------- -}
case BarrierSet::CardTableModRef:
case BarrierSet::CardTableExtension:
{
{- -------------------------------------------
(1.1) コード生成:
「MacroAssembler::store_heap_oop() または
MacroAssembler::store_heap_oop_null() が生成するコードにより,
対象のポインタ値の書き換えを行う.
(書き込むポインタ値が NULL でない場合には MacroAssembler::store_heap_oop(),
NULL の場合には MacroAssembler::store_heap_oop_null() を使用)
また, 書き込むポインタ値が NULL でない場合には,
MacroAssembler::store_check() が生成するコードにより,
書き換え箇所に対応する Barrier Set 中の値を dirty にする」
(NULL の場合には, コード生成時点で記録の必要が無いと保証できる)
(なお, precise 引数が true の場合には,
base で指定された値に offset/index 分も足し込んだ正確なアドレスを記録する.
そうでない場合には base の値だけを記録する)
---------------------------------------- -}
if (val == noreg) {
__ store_heap_oop_null(obj);
} else {
__ store_heap_oop(obj, val);
// flatten object address if needed
if (!precise || (obj.index() == noreg && obj.disp() == 0)) {
__ store_check(obj.base());
} else {
__ leaq(rdx, obj);
__ store_check(rdx);
}
}
}
break;
{- -------------------------------------------
(1) (以下は ?? の場合のパス)
#TODO
---------------------------------------- -}
case BarrierSet::ModRef:
case BarrierSet::Other:
if (val == noreg) {
__ store_heap_oop_null(obj);
} else {
__ store_heap_oop(obj, val);
}
break;
{- -------------------------------------------
(1) (以下のパスに来ることはあり得ない)
(もし来てしまったら HotSpot 内のバグ)
---------------------------------------- -}
default :
ShouldNotReachHere();
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.