バイトコード検証の完了後, 高速化のために一部のバイトコードを書き換える処理 (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.