これらは, C2 JIT 生成コード用のランタイム機能を提供するクラス.
HotSpot 内にある Runtime クラスの1つ (= アセンブリでは書くことが難しい複雑な機能(例外ハンドリング, 重量ロック処理, etc)を納めた名前空間(AllStatic クラス)) (See: here for details).
その中でも OptoRuntime クラスには (名前の通り) C2 JIT 生成コードから呼び出されるルーチンが納められている.
OptoRuntime は C2 が前提なので「ランタイムのコード自体も Ideal をコンパイルして作る」という凝った作りになっている (このため1つ1つのメソッドは nmethod として作成され CodeCache で管理されている). それぞれのメソッドは「JIT の calling convention で呼び出されて対応する C++ の関数を呼び出す」という挙動をする.
(わざわざ Ideal で作ることにどれだけ意味があるか分からないが, JIT からのジャンプ範囲が CodeCache 内に絞れるので sparc で 32bit 即値ジャンプが使える, とか色々メリットがあるんだろう #TODO)
((cite: hotspot/src/share/vm/opto/runtime.hpp))
//------------------------------OptoRuntime------------------------------------
// Opto compiler runtime routines
//
// These are all generated from Ideal graphs. They are called with the
// Java calling convention. Internally they call C++. They are made once at
// startup time and Opto compiles calls to them later.
// Things are broken up into quads: the signature they will be called with,
// the address of the generated code, the corresponding C++ code and an
// nmethod.
// The signature (returned by "xxx_Type()") is used at startup time by the
// Generator to make the generated code "xxx_Java". Opto compiles calls
// to the generated code "xxx_Java". When the compiled code gets executed,
// it calls the C++ code "xxx_C". The generated nmethod is saved in the
// CodeCache. Exception handlers use the nmethod to get the callee-save
// register OopMaps.
((cite: hotspot/src/share/vm/opto/runtime.hpp))
class OptoRuntime : public AllStatic {
定義されているメソッドは以下の通り.
なお, 命名規則は以下の通り.
See: here for details
デバッグ用(開発時用)のクラス (#ifndef PRODUCT 時にしか使用されない).
C2 JIT コンパイラが生成した各ロック確保操作について, 実際にそこでロックが行われた回数を蓄積するパフォーマンスカウンタ. 1つの NamedCounter オブジェクトが 1つのロック確保操作に対応する.
なお, このクラスは (デバッグ時であることに加えて) PrintLockStatistics オプションが指定されている場合にしか使用されない.
なお, NamedCounter オブジェクトは JIT コンパイル作業中にだけ使用される一時的なオブジェクトではない (一度生成されると HotSpot の終了時まで永続的にメモリ上に存在する).
((cite: hotspot/src/share/vm/opto/runtime.hpp))
//
// NamedCounters are tagged counters which can be used for profiling
// code in various ways. Currently they are used by the lock coarsening code
//
class NamedCounter : public CHeapObj {
以下の箇所に(のみ)格納されている.
(正確には, このフィールドは NamedCounter (やそのサブクラス) の線形リストを格納するフィールド. NamedCounter オブジェクトは _next フィールドで次の NamedCounter オブジェクトを指せる構造になっている. 生成した NamedCounter オブジェクトは全てこの線形リスト内に格納されている)
その AbstractLockNode のロック確保箇所に対応する NamedCounter オブジェクト (格納している NamedCounter オブジェクト自体は, OptoRuntime::_named_counters が指しているものと重複).
OptoRuntime::new_named_counter() 内で(のみ)生成されている (より正確に言うと NamedCounter::LockCounter 定数を引数としてこの関数が呼び出された場合にのみ生成される).
そして, この関数は現在は以下のパスで(のみ) NamedCounter::LockCounter 定数を引数として呼び出されている.
GraphKit::shared_lock() -> AbstractLockNode::create_lock_counter() (ただし, #ifndef PRODUCT 時かつ PrintLockStatistics 指定時にしか呼び出されない) -> OptoRuntime::new_named_counter()
現在は, GraphKit::increment_counter() が生成するコード内で(のみ)記録されている. そして, この関数は現在は以下のパスで(のみ)呼び出されている.
GraphKit::shared_lock() -> GraphKit::increment_counter()
現在は, OptoRuntime::print_named_counters() 内で(のみ)出力されている.
定義されているフィールドは以下の通り.
const char * _name;
この NamedCounter オブジェクトを示す名前. 現在は "${class_name}.${method_name}@${bci}" という名前が付けられている (See: OptoRuntime::new_named_counter()).
int _count;
実行回数が記録されるフィールド. JIT 生成コードにはここを指すポインタが埋め込まれる.
CounterTag _tag;
この NamedCounter オブジェクトの種別. なお CounterTag は以下の用に定義された enum 値.
((cite: hotspot/src/share/vm/opto/runtime.hpp))
enum CounterTag {
NoTag,
LockCounter,
EliminatedLockCounter,
BiasedLockingCounter
};
NamedCounter* _next;
線形リストを構成するためのポインタ. 次の NamedCounter を指す.
((cite: hotspot/src/share/vm/opto/runtime.hpp))
const char * _name;
int _count;
CounterTag _tag;
NamedCounter* _next;
See: here for details
トラブルシューティング用のクラス (関連する diagnostic オプションが指定されている場合にのみ使用される) (See: PrintPreciseBiasedLockingStatistics).
C2 JIT コンパイラが生成した各 fast-lock 操作について, 実際にそこでロック処理が行われた回数を蓄積するパフォーマンスカウンタ. 1つの NamedCounter オブジェクトが 1つのロック確保操作に対応する.
なお, BiasedLockingNamedCounter オブジェクトは JIT コンパイル作業中にだけ使用される一時的なオブジェクトではない (一度生成されると HotSpot の終了時まで永続的にメモリ上に存在する).
((cite: hotspot/src/share/vm/opto/runtime.hpp))
class BiasedLockingNamedCounter : public NamedCounter {
OptoRuntime クラスの _named_counters フィールド (static フィールド) に(のみ)格納されている.
(正確には, このフィールドは NamedCounter (やそのサブクラス) の線形リストを格納するフィールド. NamedCounter オブジェクトは _next フィールドで次の ... オブジェクトを指せる構造になっている. 生成した NamedCounter オブジェクトは全てこの線形リスト内に格納されている)
OptoRuntime::new_named_counter() 内で(のみ)生成されている (より正確に言うと NamedCounter::BiasedLockingCounter 定数を引数としてこの関数が呼び出された場合にのみ生成される) そして, この関数は現在は以下のパスで(のみ) NamedCounter::BiasedLockingCounter 定数を引数として呼び出されている.
GraphKit::shared_lock() -> FastLockNode::create_lock_counter() (ただし, PrintPreciseBiasedLockingStatistics 指定時にしか呼び出されない) -> OptoRuntime::new_named_counter()
現在は, 以下の箇所で(のみ)記録されている.
enc_class Fast_Lock()
MacroAssembler::compiler_lock_object()
現在は, OptoRuntime::print_named_counters() 内で(のみ)出力されている.
実際の蓄積機能は, BiasedLockingCounters によって実現されている (See: BiasedLockingCounters)
((cite: hotspot/src/share/vm/opto/runtime.hpp))
BiasedLockingCounters _counters;
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.