バイトコード検証の完了後, 高速化のために一部のバイトコードを書き換える処理 (rewrite 処理) が行われる. この処理は Rewriter::rewrite() で行われる.
また以上の rewrite 処理後には, jsr バイトコードに関する再配置処理と, 各メソッドにエントリポイントを設定する処理が行われる. この処理は Rewriter::relocate_and_link() で行われる.
なお, rewrite 処理で行われる処理は以下の通り.
java.lang.Object のコンストラクタ (= <init>()
メソッド) 中の return 命令を,
HotSpot独自のバイトコード命令に変更する (return_register_finalizer 命令)
これは Finalizer の処理を補佐するバイトコード命令 (See: here for details). 実行したオブジェクトを Finalizer に登録してからリターンする (See: here for details).
lookupswitch 命令を, HotSpot独自のバイトコード命令に変更する (fast_linearswitch 命令または fast_binaryswitch 命令).
飛び先の候補数に応じた2種類が用意されており, 候補数が閾値(※)未満であれば fast_linearswitch, それ以上であれば fast_binaryswith になる. fast_linearswitch は線形にサーチし, fast_binaryswith はバイナリサーチを行う (See: here for details).
(※) 閾値は develop オプションである BinarySwitchThreshold オプションの値. デフォルトでは 5.
ロード対象が method handle もしくは method type である ldc 命令及び ldc_w 命令を, HotSpot独自のバイトコード命令に変更する (fast_aldc 命令, fast_aldc_w 命令). (See: here for details)
constant pool の index をオペランドとするバイトコード命令に対し, index 部分を constant pool cache の index に置き換える
(対象のバイトコード命令は, getstatic, getfield, putstatic, putfield, invokestatic, invokespecial, invokevirtual, invokeinterface, invokedynamic)
なお, この時点では constantPoolCacheOopDesc の中は空であり, シンボルの解決時にそれぞれの中身が作成される (See: here for details).
constant pool cache (constantPoolCacheOop オブジェクト) を作成する
以下のコマンドラインオプションが rewrite 処理に影響する.
java.lang.Object.<init>()
中の return 命令を書き換えるかどうかを制御する.
オプションをオフにした場合は return 命令の書き換えは行わない.
なお, オプションをオフにした場合は, オブジェクトのメモリを確保する際に (= instanceKlass::allocate_instance() 内で) Finalizer に登録している模様. (See: here for details)
Rewriter::rewrite(instanceKlassHandle klass, TRAPS) -> Rewriter::Rewriter() -> (1) 対象が java.lang.Object の場合は, コンストラクタ(<init>()) 中の return 命令を return_register_finalizer 命令に書き換える. (なお, RegisterFinalizersAtInit オプションがセットされていない場合は, この処理は行わない) -> Rewriter::rewrite_Object_init() (1) 処理対象クラス内の各メソッドに対して, 上記以外のバイトコード書き換え処理を行う. -> Rewriter::scan_method() -> 全てのメソッド内の各バイトコードに対して書き換えを行う. * lookupswitch 命令の場合: -> fast_linearswitch 命令または fast_binaryswitch 命令に書き換える * fast_linearswitch 命令または fast_binaryswitch 命令の場合: -> lookupswitch 命令に書き換える (元に戻す) * {get|put}{static|field} 命令や invoke* 命令(invokedynamic除く) の場合: -> Rewriter::rewrite_member_reference() (バイトコード命令中の Constant Pool index が埋まっている 2byte を Constant Pool Cache の index に書き換える) * invokedynamic 命令の場合: -> Rewriter::rewrite_invokedynamic() (バイトコード命令中の Constant Pool index が埋まっている 4byte を Constant Pool Cache の index に書き換える) * ldc 命令または ldc_w 命令の場合: -> Rewriter::maybe_rewrite_ldc() (ロード対象が method handle もしくは method type の場合, fast_aldc 命令または fast_aldc_w 命令に置き換える) (1) 収集した constant pool cache index の情報を元に constant pool cache (constantPoolCacheOop オブジェクト) を生成する. -> Rewriter::make_constant_pool_cache() -> oopFactory::new_constantPoolCache() -> constantPoolCacheKlass::allocate()
Rewriter::relocate_and_link(instanceKlassHandle this_oop, TRAPS) -> Rewriter::relocate_and_link(instanceKlassHandle this_oop, objArrayHandle methods, TRAPS) -> (1) jsr バイトコードに関する再配置処理を行う -> Rewriter::rewrite_jsrs() -> ResolveOopMapConflicts::do_potential_rewrite() -> GenerateOopMap::compute_map() -> (1) 対象のメソッドにエントリポイントを設定する (これにより, このメソッドはインタープリタ/JIT生成コードから呼び出せるようになる) -> methodOopDesc::link_method() -> (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
(#Under Construction) See: here for details
(#Under Construction) See: here for details
See: here for details
(#Under Construction) See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.