A tail-call interpreter in (nightly) Rust
> Source: Hacker_News
Execute Primary Source
// Problem
従来のループを用いたVM実装では、命令ディスパッチのオーバーヘッドや分岐予測の失敗がボトルネックとなる。一方で、高速な「スレッド化コード」をアセンブリで実装すると、保守性が極めて低く、メモリ安全性も確保できないという課題があった。
// Approach
Rustのnightly機能である`become`を活用し、テールコール(末尾再帰最適化)によるインタプリタを構築した。命令の実行後に次の命令を呼び出す際、スタックフレームを破棄して直接ジャンプさせることで、アセンブリのスレッド化コードに近い挙動を安全なRustコードで実現した。
// Result
ARM64環境では、手書きのアセンブリ実装を上回るパフォーマンスを達成した。しかし、x86-64ではコンパイラのコード生成の問題でレジスタの退避(spill)が発生しアセンブリに劣り、WASM環境では標準的なVM実装よりも大幅に低速となる結果となった。
Senior Engineer Insight
> 本記事の核心は、言語機能(`become`)を用いて「低レイヤの制御(スレッド化コード)」を「高レイヤの安全性(Safe Rust)」で抽象化した点にある。ARM64での成功は、コンパイラが命令の連続性を適切に最適化できたことを示している。一方で、x86でのレジスタ・スピリングやWASMでの性能低下は、コンパイラのコード生成能力やターゲット環境のスタックマシン特性への依存を浮き彫りにしている。特に、`extern "rust-preserve-none"`のような呼び出し規約の制御が、レジスタ割り当てに決定的な影響を与える点は、高パフォーマンスなインタプリタを設計する上で極めて重要な知見である。