私はJITingを実装する予定のVM(およびそのためのスクリプト言語)に取り組んでいます。現在はその「配管」にのみ取り組んでいますが、私はしていません。 JITコンパイラを後から付け加えたいと思っていますが、その基本は理解していますが、JITが正確に何をすべきかについて少し混乱しています。
それが実装されていると私が考えることができる2つの方法があります:
最初の方法は、本格的なコンパイラを構築するだけでなく、通常はVM機能に依存する高水準言語をコンパイルできる)に関する知識が必要なため、実装が困難です。ネイティブコードにコンパイルされます。
2番目の方法は、実際にプログラムをコンパイルしていないため、実装がはるかに簡単です。対応するオペランドを使用して(内部VMへの)C関数呼び出しのリストを動的に作成し、x86命令を使用して同じ順序で呼び出します。そうでなければ、「デコード」するためにインタプリタが必要になります。
ただし、2番目の実装は明らかに正気のように見えますが、プログラムのパフォーマンスにどれだけ影響するか(または少なくなるか)はわかりません。どの方向を目指すべきですか?注目すべき長所と短所はありますか?
確かに、メソッド2では、単純なバイトコードインタープリターループよりもパフォーマンスが大幅に向上することはありません。本当の利益は方法1を使用することによって得られることになっています。とはいえ、方法1は、役立つライブラリがあるため、最近は以前ほど難しくはありません。
比較的東にあり、優れたパフォーマンスが得られる可能性のある興味深いアプローチの1つは、LLVMを使用してメソッド2を実装し、既存のLLVMコンパイラ(clangなど)を使用して、ネイティブではなくLLVMコードに呼び出す関数をコンパイルすることです。結果、特に関数呼び出しインラインの最適化ステップ。これにより、複雑さをあまり気にすることなく、適度に優れたネイティブコードが得られるはずです。
[〜#〜] gccjit [〜#〜] 、 libjit 、 [〜#〜] llvm [〜 #〜] 、 asmjit 、...バイトコードをCに変換し、実行時にそのCコードを共有ライブラリに動的にコンパイルしてdlopen
-ingすることも検討できます。そのプラグインなど...
そのためには、いくつかのコンパイルと最適化の手法を理解する必要があります(特に、バイトコードが、使用するJITライブラリで必要な内部表現から意味的に遠い場合があるため)。