Template Interpreter の場合, ループの実行回数のチェックは以下のバイトコード(に対応するテンプレート)で行われる.
Bytecode | Template |
---|---|
ifeq | TemplateTable::if_0cmp() |
ifne | TemplateTable::if_0cmp() |
iflt | TemplateTable::if_0cmp() |
ifge | TemplateTable::if_0cmp() |
ifgt | TemplateTable::if_0cmp() |
ifle | TemplateTable::if_0cmp() |
if_icmpeq | TemplateTable::if_icmp() |
if_icmpne | TemplateTable::if_icmp() |
if_icmplt | TemplateTable::if_icmp() |
if_icmpge | TemplateTable::if_icmp() |
if_icmpgt | TemplateTable::if_icmp() |
if_icmple | TemplateTable::if_icmp() |
if_acmpeq | TemplateTable::if_acmp() |
if_acmpne | TemplateTable::if_acmp() |
goto | TemplateTable::_goto() |
ifnull | TemplateTable::if_nullcmp() |
ifnonnull | TemplateTable::if_nullcmp() |
goto_w | TemplateTable::goto_w() |
アーキテクチャ(sparc, x86)によって若干処理に違いはあるが, どちらも TemplateTable::branch() が生成したコードでカウンタ値をチェックし, 閾値を超えていれば InterpreterRuntime::frequency_counter_overflow() を呼び出す. これにより CompilationPolicy オブジェクトが呼び出され, JIT コンパイル処理が開始される.
なお, 制御の移行に関するバイトコード(See: here for details)のうち, 以下のものについては Template Interpreter は実行回数をチェックしていない.
(<= まぁ実際問題として, tableswitch や lookupswitch でループしたり jsr や ret で再帰するプログラムはほぼないだろ...)
Bytecode | Template |
---|---|
jsr | TemplateTable::jsr() |
ret | TemplateTable::ret() |
tableswitch | TemplateTable::tableswitch() |
lookupswitch | TemplateTable::lookupswitch() |
jsr_w | TemplateTable::jsr_w() |
ret | TemplateTable::wide_ret() |
fast_linearswitch | TemplateTable::fast_linearswitch() |
fast_binaryswitch | TemplateTable::fast_binaryswitch() |
TemplateTable::if_0cmp() が生成したコード -> InterpreterMacroAssembler::if_cmp() が生成したコード -> TemplateTable::branch() が生成したコード (における jsr 以外のためのコード生成パス) (See: here for details) -> * UseCompiler と UseLoopCounter のどちらかが指定されていない場合: -> (1) Lbcp の値を変更する (2) 次のバイトコードに対応するテンプレートへとジャンプする -> InterpreterMacroAssembler::dispatch_next() が生成したコード * UseCompiler と UseLoopCounter の両方が指定されている場合: -> * TieredCompilation が有効な場合: -> (1) ブランチの方向が backward でなければ, (4) に進む (2) カウンタ値をインクリメントしてチェックする. 閾値を超えていれば, (3) に進む. 閾値を超えてなければ, (4) に進む. * methodDataOopDesc が付いていれば (& ProfileInterpreter が有効ならば), methodDataOopDesc 内の _backedge_counter のカウンタ値をインクリメントしてチェックする. -> InterpreterMacroAssembler::increment_mask_and_jump() が生成したコード * そうでなければ, methodOopDesc 内の _backedge_counter のカウンタ値をインクリメントしてチェックする -> InterpreterMacroAssembler::increment_mask_and_jump() が生成したコード (3) JIT コンパイルを行う. あるいは, 既に JIT コンパイル済みのコードがあれば, OSR を行ってそのコードに遷移する. (遷移した場合は以降の処理は実行されない) -> InterpreterRuntime::frequency_counter_overflow() -> InterpreterRuntime::frequency_counter_overflow_inner() -> CompilationPolicy::event() (を各サブクラスがオーバーライドしたもの) -> (See: here for details) -> SharedRuntime::OSR_migration_begin() -> (See: here for details) (4) Lbcp の値を変更する (5) 次のバイトコードに対応するテンプレートへとジャンプする -> InterpreterMacroAssembler::dispatch_next() が生成したコード * TieredCompilation が無効な場合: -> (1) ブランチの方向が backward でなければ, (5) に進む (2) methodOopDesc 内の _backedge_counter のカウンタ値をインクリメントする -> InterpreterMacroAssembler::increment_backedge_counter() が生成したコード (3) ProfileInterpreter が有効ならば, 必要に応じて methodDataOop の生成を行う -> InterpreterMacroAssembler::test_invocation_counter_for_mdp() が生成したコード (4) カウンタ値と閾値を比較し, 閾値を超えていれば JIT コンパイルを行う. あるいは, 既に JIT コンパイル済みのコードがあれば, OSR を行ってそのコードに遷移する (遷移した場合は以降の処理は実行されない) -> InterpreterMacroAssembler::test_backedge_count_for_osr() が生成したコード -> InterpreterRuntime::frequency_counter_overflow() -> (同上) -> SharedRuntime::OSR_migration_begin() -> (See: here for details) (5) Lbcp の値を変更する (6) 次のバイトコードに対応するテンプレートへとジャンプする -> InterpreterMacroAssembler::dispatch_next() が生成したコード TemplateTable::if_icmp() が生成したコード -> InterpreterMacroAssembler::if_cmp() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::if_acmp() が生成したコード -> InterpreterMacroAssembler::if_cmp() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::_goto() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::if_nullcmp() が生成したコード -> InterpreterMacroAssembler::if_cmp() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::goto_w() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上)
TemplateTable::if_0cmp() が生成したコード (See: here for details) -> TemplateTable::branch() が生成したコード (における jsr 以外のためのコード生成パス) (See: here for details) -> * UseLoopCounter が指定されていない場合: -> (1) r13 の値を変更し, rbx に次のバイトコードのセットする (2) 次のバイトコードに対応するテンプレートへとジャンプする -> InterpreterMacroAssembler::dispatch_only() が生成したコード * UseLoopCounter が指定されている場合: -> * TieredCompilation が有効な場合: -> (1) r13 の値を変更する (2) ブランチの方向が backward でなければ, (5) に進む (3) カウンタ値をインクリメントしてチェックする. 閾値を超えていれば, (4) に進む. 閾値を超えてなければ, (5) に進む. * methodDataOopDesc が付いていれば (& ProfileInterpreter が有効ならば), methodDataOopDesc 内の _backedge_counter のカウンタ値をインクリメントしてチェックする. -> InterpreterMacroAssembler::increment_mask_and_jump() が生成したコード * そうでなければ, methodOopDesc 内の _backedge_counter のカウンタ値をインクリメントしてチェックする -> InterpreterMacroAssembler::increment_mask_and_jump() が生成したコード (4) JIT コンパイルを行う. あるいは, 既に JIT コンパイル済みのコードがあれば, OSR を行ってそのコードに遷移する. (遷移した場合は以降の処理は実行されない) -> InterpreterRuntime::frequency_counter_overflow() -> InterpreterRuntime::frequency_counter_overflow_inner() -> CompilationPolicy::event() (を各サブクラスがオーバーライドしたもの) -> (See: here for details) -> SharedRuntime::OSR_migration_begin() -> (See: here for details) (5) rbx に次のバイトコードのセットする (6) 次のバイトコードに対応するテンプレートへとジャンプする -> InterpreterMacroAssembler::dispatch_only() が生成したコード * TieredCompilation が無効な場合: -> (1) r13 の値を変更する (2) ブランチの方向が backward でなければ, (6) に進む (3) methodOopDesc 内の _backedge_counter のカウンタ値をインクリメントする -> InterpreterMacroAssembler::increment_backedge_counter() が生成したコード (4) ProfileInterpreter が有効ならば, 必要に応じて methodDataOop の生成を行う -> InterpreterMacroAssembler::test_invocation_counter_for_mdp() が生成したコード (5) カウンタ値と閾値を比較し, 閾値を超えていれば JIT コンパイルを行う. あるいは, 既に JIT コンパイル済みのコードがあれば, OSR を行ってそのコードに遷移する (遷移した場合は以降の処理は実行されない) -> InterpreterMacroAssembler::test_backedge_count_for_osr() が生成したコード -> InterpreterRuntime::frequency_counter_overflow() -> (同上) -> SharedRuntime::OSR_migration_begin() -> (See: here for details) (6) rbx に次のバイトコードのセットする (7) 次のバイトコードに対応するテンプレートへとジャンプする -> InterpreterMacroAssembler::dispatch_only() が生成したコード TemplateTable::if_icmp() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::if_acmp() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::_goto() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::if_nullcmp() が生成したコード -> InterpreterMacroAssembler::if_cmp() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上) TemplateTable::goto_w() が生成したコード -> TemplateTable::branch() が生成したコード -> (同上)
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.