トップ 一覧 Farm 検索 ヘルプ RSS ログイン

Forthを作ってみる / スレッディングの変更の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
私の実装したForth、moiforthは、内部インタプリタをスイッチスレッディングで実装している。

        switch (prog[prog_cnt]) {
        case CODE_PUSH:
            処理
            break;
        case CODE_PLUS:
            処理
            break;

これを、コールスレッディングに変える。
コールスレッディングに変えると、ワード処理は個別の関数に分けられ、それを呼び出すのは次のような処理になる:

        while (1) {
            (*prog[prog_cnt])();
        }

なにがうれしいかと言うと、

* 内部インタプリタがコンパクトになる
* 処理が個々の関数に分けられ、すっきりする

ただ、うれしくない部分もあり、

* 遅くなる。スイッチスレッディングは分岐だが、コールスレッディングはサブルーチンコールになるため

いろいろ悩んだが、コールスレッディングにした。
なぜなら、まだ書いたことがない、から。

スレッディングについては、以下に詳しく書かれている。

* [[ThreadedCode]]
* [langsmith:266|http://www.atdot.net/~ko1/w3ml/w3ml.cgi/langsmith/msg/266]の前後の話
* [YARV Maniacs 【第 3 回】 命令ディスパッチの高速化|http://jp.rubyist.net/magazine/?0008-YarvManiacs]

上記のコールスレッディングは、直接スレッディングなので、ジャンプ先アドレスがそのまま入っているが、これから作るのは間接スレッディングなので、以下のようになる。

        while (1) {
            (*jump_table[prog[prog_cnt++]])();
        }

当然直接スレッディングより遅い。
しかし、prog[]のコードを番地のサイズより小さくすれば、メモリ効率が良くなる。
PCではそんなことは関係ないが、組み込み用途だと意味がある。かも。

実際のコードは、こうなった。

    while (prog[prog_cnt] != CODE_END) {
        (*jump_table[prog[prog_cnt++]])();
    }

ループを抜けるには、プログラムの終了判定をしなければならない。
アセンブラならループの外にジャンプするだけで済むが、コールスレッディングだと、こうせざるを得ない。
そのぶん遅くなる。

つぎに、ワードの処理を関数単位に分ける。doを例にすると、こうなる。

 /** 
  * ワード'do'を実行する
  */
 void call_do(void)
 {
     loop_pos--;
 
     /* スタックの内容をループスタックに入れる */
     loop_cnt_stack[loop_pos] = pop();
     loop_end_stack[loop_pos] = pop();
 }

さらに、ジャンプ先となる関数ポインタの配列を作った。

 void (*jump_table[])(void) = {  /**< ワードのジャンプ先テーブル */
     NULL, call_push, plus, print, word_if, word_else, word_then, call_do,
     call_loop, call_i, call_cr, call_word, proc_ret
 };

新しいスレッディングのmoiforthを、テストする。
testfile以下のプログラムを次々テストしていくが、問題ない。
というわけで、スイッチスレッディングからコールスレッディングの変更が終わった。

[ソースコード|http://moi2.sakura.ne.jp/fswiki/wiki.cgi?page=Forth%A4%F2%BA%EE%A4%C3%A4%C6%A4%DF%A4%EB+%2F+%A5%B9%A5%EC%A5%C3%A5%C7%A5%A3%A5%F3%A5%B0%A4%CE%CA%D1%B9%B9&file=moiforth%2D0%2E8%2Ezip&action=ATTACH]

[[戻る|Forthを作ってみる]] [[前へ|Forthを作ってみる / コンソールの複数行入力対応]] [[次へ|aaa]]
[[戻る|Forthを作ってみる]] [[前へ|Forthを作ってみる / コンソールの複数行入力対応]] [[次へ|Forthを作ってみる / 文字列を表示する]]

{{adsence}}