Forthの共有スタックをJITが最適化できる形にする
RPyForth: Exposing a Call-Shared Data Stack to a Meta-Tracing JIT Compiler
この論文をやさしく読む
ひとことで言うと
呼び出し間で共有されるForthのスタックの上端だけを固定サイズで見せ、JITが不要なアクセスを減らせるようにします。
何に役立つ?
動的なスタックを持つ言語の処理系を設計し、実行時コンパイラに情報を渡す方法を検討する際に役立ちます。
この研究の面白いところ
キャッシュを置くだけではなく、それをコンパイラが認識できるようにする効果を、配置と方策を固定して分離しています。
どこまで分かった?
計測は読み込み済みプログラムの反復実行です。VFX Forthとの比較では小規模カーネルで速い一方、アプリケーションは0.68〜0.76倍で遅く、すべての用途で高速ではありません。
v1のアブストラクトに基づくAI解説。日本語訳とは別に、用途の解釈を含みます。
アブストラクトの日本語訳
Forthは連接的な言語であり、ワードが呼び出しをまたいで1つのデータスタックを共有する。その深さと、呼び出しがスタックに及ぼす効果は、実行前には分からなくてもよい。このため、メタトレーシングJITコンパイラには名前を付けて扱えるスタック位置がない。セルにはスタックポインタを介して到達するため、そのアクセスがコンパイル後のコードにも残る。一方、スタック配列のすべてのセルを宣言すると、コンパイラが保持するものはプログラムが使う深さではなく、配列の予約容量に結びついてしまう。 本研究では、スタック上端の固定幅ウィンドウ、より深いセルをすべて保持する共有退避領域、両者を結合する復号関数によって対処する。その上に、呼び出し入口での正規化と適応的な入口処理を方策として置く。復号によって、これらの方式がすべて論理的なスタックを保存し、トレース終了時に再構築するデータスタック状態の大きさが、スタックの深さではなくウィンドウ幅で制限されることを示す。 RPyForthは、ForthのCoreワード集合を扱うRPythonインタプリタでこれを実装する。2つのスカラー場と8つのフレーム位置を用い、静的なスタック効果解析は行わない。RPyFactorはFactorの一部に同じウィンドウを実装する。効果を生むのは、単にウィンドウ内でセルをキャッシュすることではなく、ウィンドウをコンパイラに公開することである。配置と呼び出し方策を固定すると、ウィンドウの場に注釈を付けることで、2台のx86-64機で18個のShootoutカーネルが1.44〜1.45倍、6個のAppbenchアプリケーションが約1.60倍高速になり、RPyFactorでは1.42〜1.56倍となった。ウィンドウの形や呼び出し時に正規化するかどうかの影響はずっと小さく、プログラムによって異なり、どの設定も常に最良とはならない。 システム全体として、RPyForthは両方のテスト群でgforth-fastとSwiftForthより高速で、カーネルではVFX Forthの1.90〜2.36倍の速度に達する。一方、スタックが深く呼び出しもはるかに多いアプリケーションは弱点として残り、VFX Forthに対して0.68〜0.76倍の速度にとどまる。すべての計時は、読み込み済みプログラムの反復実行を測定している。
v1の要旨から自動生成。本文の精読・人による確認は未実施。
- 初稿
- 2026-09-20(UTC)
- 最新改訂
- 2026-09-20 · v1
- 査読・掲載
- 査読状況未確認
更新履歴
- v1 2026-09-20 この版を読む
取得できた版を表示。版の更新は査読済みを意味しません。過去版の本文差分は未解析です。
原文の要旨
Forth is a concatenative language whose words share one data stack across calls, with a depth and call effects that need not be known before execution. That leaves a meta-tracing JIT compiler with no stack location it can name: a cell is reached through the stack pointer, so its accesses stay in the compiled code, and declaring every cell of the stack array instead ties what the compiler carries to the capacity the array reserves rather than to the depth a program uses. We answer with a fixed-width window over the top of the stack, a shared spill holding every deeper cell, and a decoding function that joins the two, on top of which call-entry normalization and adaptive entry are policies. Decoding shows that all of them preserve the logical stack and that a trace exit rebuilds data-stack state bounded by the window's width, not by the stack's depth. RPyForth realizes this in an RPython interpreter covering Forth's Core word set, with two scalar fields and eight frame positions and no static stack-effect analysis, and RPyFactor realizes the same window for a subset of Factor. Exposing the window to the compiler, rather than merely caching cells in it, is what pays. With the layout and the call policy held fixed, annotating the window's fields makes eighteen Shootout kernels 1.44-1.45x faster and six Appbench applications about 1.60x faster on two x86-64 machines, and 1.42-1.56x in RPyFactor. How the window is shaped and whether calls normalize it matter much less, varying by program with no setting winning everywhere. As a complete system, RPyForth is faster than gforth-fast and SwiftForth on both suites and reaches 1.90-2.36x the speed of VFX Forth on the kernels, while the applications, whose stacks are deeper and whose calls are far more frequent, remain its weak point at 0.68-0.76x. All timings measure repeated execution of an already-loaded program.
著者のコメント
33 pages, 15 figures
arXiv ID: 2609.23759 / 要約の誤りについて