私のプロジェクトには、ドメイン固有の言語からコンパイルされたバイトコードを実行するVMがあります。私は、バイトコードの実行時間を改善できる方法を見ています。最初のステップとして、マシンコードのコンパイルに入る前にバイトコードインタープリタを単純に改良する方法があるかどうかを見たいと思います。最適な仮想マシン/バイトコードインタプリタループ
インタプリタのメインループは次のようになります。
while(true)
{
uint8_t cmd = *code++;
switch(cmd)
{
case op_1: ...; break;
...
}
}
QUESTION:は、アセンブラに頼ることなく、このループを実装するためのより高速な方法はありますか?
表示される1つのオプションは、ラベルアドレスで動的なgotoを使用することに特有のGCCです。各ケースの最後にbreak
ではなく、次の命令に直接ジャンプすることができました。私はオプティマイザが私のためにこれを行うことを期待していましたが、逆アセンブリを見れば明らかにそうではありません。ほとんどのop_codesの終わりに繰り返される定数ジャンプがあります。
該当する場合、VMは浮動小数点レジスタと整数レジスタ(それぞれ8個)を持つ単純なレジスタベースのマシンです。スタックはなく、グローバルヒープのみ(その言語はそれほど複雑ではありません)です。
スイッチの代わりに関数呼び出しを行う方が速い(関数呼び出しにかなりのオーバーヘッドがある)ことはほとんどありません。とにかくスイッチはジャンプテーブルに適合するはずです(GCCはこれを少なくとも行います)。 –
クールでは、gccについては分かりませんでしたが、とにかく関数をインラインで定義でき、引数を渡す代わりにグローバル変数にするなど、関数呼び出しのオーバーヘッドを非常に小さくします。もちろん、このレベルになると、アセンブラですべてをコード化する方が簡単かもしれません。 (それを行う方法がわかっている場合) – Cray
ディスパッチテーブル経由でのインラインコールはできません。ここで最も近いオプションはGCCラベルアドレスを使用することです。これは基本的にジャンプテーブルで独自のインライン関数を作ることができます。 –