JITコンパイラ
JITコンパイラの分類
(1) JITコンパイルの制御
(2) JITコンパイルの対象
(3) 多段コンパイルの仕方
(1) JITコンパイルの制御
(1-1) インタプリタ実行しており、条件に合致したらバックグラウンドでJITコンパイルする。
(1-2) 実行直前にJITコンパイルする。
起動時はインタプリタ実行しているが、メソッドをx回呼び出したらとか、ループをn回回ったらJITコンパイルを始める。
インタプリタ実行時に様々な情報を収集しておき、JITコンパイル時に活用できる。
インタプリタ実行と並行して、別スレッドでJITコンパイルするものがほとんどのはず。
代表例として
xxx monkeyやHotspotやchakra
実行直前型は、インタプリタ実行せず、実行をブロッキングしてJITコンパイルする。
この方式の場合、JITコンパイル時間そのものが実行時間に反映される。
実行直前のコンパイルを行うものの代表例として
LLVMやV8やDart VM
(2) JITコンパイルの対象
(2-1) メソッド単位
(2-2) Tracing単位
(2-3) インタプリタ
対象のプログラミング言語のメソッド単位でJITコンパイルする。
メソッド単位なのは、
Hotspot, IonMonkey, JaegerMonkey, LLVM, V8, DartVM
インタプリタ実行時にTracingを収集し、収集したTracing単位でJITコンパイルする。
TracingはBasicBlockの集合で、よく実行されるパスごとにまとめたもの。
Tracing単位なのは、
TraceMonkey, DalvikVM
インタプリタをJITコンパイルするのは、
pypy (これは俗にMetaTracingJITと呼ばれるが)
pypyはRPythonでインタプリタを記述し、そのインタプリタ自体をJITコンパイルする。
インタプリタを丸ごとJITコンパイルするのではなく、インタプリタのよく実行される単位をTracingするのが特徴。
(3) 多段コンパイルの仕方
(3-1) 軽量->重量
(3-2) 汎用->最適化
軽量->重量なのは、最初に軽量なJITコンパイルを行い、起動時のJITコンパイルの遅延を少なくする場合に使用する。
JVMなんかが代表的で、1回目はClientJIT + Profile情報収集を埋め込み、2回目はServerJITでProfile情報収集を埋め込み、3回目はServerJITでフルコンパイル。
汎用->最適化は、主にインタプリタ実行しない場合に使用する。主に動的型付けの場合が多いかも。
汎用的なJITコンパイルは、動的型付けでどんな型でも動作するコードをJITコンパイルしておき、型情報の収集を埋め込む。
最適化JITコンパイルでは、収集した型情報を使用して型を特化させた高速に動作するコードを生成する。
主にV8とDart VMが採用。
V8 Codegen -> Crankshaft
Dart VM FlowGraphCompiler -> FlowGraphCompiler + FlowGraphOptimizer
実装に関して
LLVM
LLVMのJITはおまけです。
bitcodeのstub呼び出しのあたりが見どころかも。
OpenJDK
IBM
IBMのJVMにtraceJITを実装した場合の効果に関して。
測定結果が速くなったり遅くなったり、コードサイズがバカでかくなったりでおもしろい。
Dynamic Scripting LanguageのJITコンパイルに関してまとめられた資料。
pythonの処理系を掘り下げて説明している。pypyのことも出てくる。
JavaScript処理系
JavaScriptの処理系や高速化の歴史に関して
goto conference 2012のスライド。IEのJavaScriptのエンジンの解説。
PyPy
SPUR
- 最終更新:2013-10-21 23:20:38