スレッド化された forth コードは、 プリミティブ(+
のような単純なマシン・コード・ルーチン)と非プリミティブ(コロン定義、 変数、
定数など)への参照で構成されます。 非プリミティブの特定の種類(変数など)では、 コード・ルーチン(dovar
など) は 1
つだけですが、 各変数は各変数それぞれのデータへの個別の参照が必要です。
伝統的に、 Forth は間接スレッド化コードとして実装されてきました。 これにより、 非プリミティブの参照は 1 つのセルのみの使用で済ませられるためです(基本的に、 データをポイントし、 ポイントした先でコード・アドレスを見つけます)。
しかしながら Gforth (0.6.0 以降) のスレッド化コードは、 非プリミティブに 2 つのセルを使用します。 1 つはコード・アドレス用で、
もう 1 つはデータ・アドレス用です。 データ・ポインターは、 コード・アドレスで表される仮想マシン命令の直接の引数です。
すべてのコード・アドレスが単純なプリミティブを指しているため、 これを「プリミティブ指向」スレッド化コードと呼びます。 たとえば、 変数の場合、
コード・アドレスは lit
用です(99
などの整数リテラルにも使用されます)。
プリミティブ指向スレッド化コードにより、 ディスパッチ手法として(より高速な)直接スレッド化を完全に移植可能な状態で使用できます(0.6.0 より前の Gforth の直接スレッド化コードにはアーキテクチャー固有のコードが必要でした)。 また、386 実装で直接スレッド・コードによる I キャッシュの一貫性に関連するパフォーマンスの問題も解消され、 追加の最適化が可能になります。
ただし、 問題があります。 execute
の xt パラメーターは 1 つのセルしか占有できないため、
「コードとデータ・アドレス」を持つ非プリミティブをどのように渡せばよいのでしょうか? これに対する私達の答えは、 execute
や単一セル xt を使用する他のワードに間接スレッド化ディスパッチを使用することです。 したがって、
コロン定義内の通常のスレッド化コードは直接スレッドを使用し、 データ・スタック上の xt にディスパッチする execute
や同様のワードは間接スレッド化コードを使用します。 これを 「ハイブリッド 直接/間接 スレッド化コード」と呼びます。
gforth
エンジンと gforth-fast
エンジンは、 ハイブリッド 直接/間接
スレッド化コードを使用します。 つまり、 これらのエンジンでは ,
を使用して xt をコンパイルできないことを意味します。
代わりに、 compile,
を使用する必要があります。
,
を使用して xt をコンパイルする場合は、 gforth-itc
エンジンを使用します。 このエンジンは、
単純な古い間接スレッド化コードを使用します。 しかし、 それでもプリミティブ指向のスタイルでコンパイルされるため、 ,
の代わりに
compile,
を使用することはできません(たとえば、 ] word1 word2 ... [
で xt
達のテーブルを生成する場合)。 それを行いたい場合は、 gforth-itc
を使用して ' , is
compile,
を実行する必要があります。 あなたのプログラムでは、 threading-method
を使用して、 ハイブリッド
直接/間接 スレッド化エンジンで実行されているか、 純粋な間接スレッド化エンジンで実行されているかを確認できます。