アサレン

朝早く目覚しに起こされたので再開。
NEXT についてココサブさんからフォロー。NEXT のカラクリについて。run_loop 手続きの先頭部分が以下。

    for (;;) {
        DISPATCH;
        /*VM_DUMP("");*/
        if (vm->queueNotEmpty) goto process_queue;
        FETCH_INSN(code);
        SWITCH(SCM_VM_INSN_CODE(code)) {

NEXT は上記の無限ループの先頭にある DISPATCH に戻るナニ、との事。vm.c にて以下の定義。

/* We take advantage of GCC's `computed goto' feature
   (see gcc.info, "Labels as Values"). */
#ifdef __GNUC__
#define SWITCH(val) goto *dispatch_table[val];
#define CASE(insn)  SCM_CPP_CAT(LABEL_, insn) :
#define DEFAULT     LABEL_DEFAULT :
#define DISPATCH    /*empty*/
#define NEXT                                            \
    do {                                                \
        if (vm->queueNotEmpty) goto process_queue;      \
        FETCH_INSN(code);                               \
        goto *dispatch_table[SCM_VM_INSN_CODE(code)];   \
    } while (0)
#else /* !__GNUC__ */
#define SWITCH(val) switch (val)
#define CASE(insn)  case insn :
#define DISPATCH    dispatch:
#define NEXT        goto dispatch
#endif

dispatch_table は vm.c にて定義。

#ifdef __GNUC__
    static void *dispatch_table[256] = {
#define DEFINSN(insn, name, nargs, type)   && SCM_CPP_CAT(LABEL_, insn),
#include "vminsn.c"
#undef DEFINSN
    };
#endif /* __GNUC__ */

なんか脱線しとるな。(違

まとめ

  • 引数は pop して Scm_VMApply に渡している
  • 手続きは val0 にセットして Scm_VMApply にも渡す
  • TAIL_CALL_INSTRUCTION マクロはスルー?
    • PC が指す命令が RET じゃなかったら
    • 継続フレームを push
    • PC には RET をセット
  • Scm_VMApply 手続き呼び出し
    • エラーチェック略
    • 引数を push
    • PC に TAIL_CALL と RET をセット
    • proc を戻す
  • NEXT1

で、ループの先頭に戻った後 TAIL_CALL なソレに移動して (ry
とゆー事でその先が大変なんですな。

てーコトは RET は push した継続フレームを取り出す処理になるのか。そうなっていますね。