Scm_VMPushCC() とか POP_CONT とか

いくつか確認してみて余力があれば VMDynamicWind の流れを見てみる方向。

POP_CONT マクロ

C-continuation は継続フレームの argp が NULL、という事は以下の部分が該当すると思われる。

        if (CONT->argp == NULL) {                                       \
            void *data__[SCM_CCONT_DATA_SIZE];                          \
            ScmCContinuationProc *after__;                              \
            void **d__ = data__;                                        \
            void **s__ = (void**)((ScmObj*)CONT + CONT_FRAME_SIZE);     \
            int i__ = CONT->size;                                       \
            while (i__-- > 0) {                                         \
                *d__++ = *s__++;                                        \
            }                                                           \
            after__ = (ScmCContinuationProc*)CONT->pc;                  \
            if (IN_STACK_P((ScmObj*)CONT)) SP = (ScmObj*)CONT;          \
            ENV = CONT->env;                                            \
            ARGP = SP;                                                  \
            PC = PC_TO_RETURN;                                          \
            CONT = CONT->prev;                                          \
            BASE = CONT->base;                                          \
            VAL0 = CALL_CCONT(after__, VAL0, data__);                   \
        } else if (IN_STACK_P((ScmObj*)CONT)) {                         \

げ。最後のソレがハードル高い。どーゆー意味だ。

とりあえず整理

これって Scm_VMPushCC() を先に確認した方が良いな。という事で

Scm_VMPushCC() 手続き

コメントがナニ。

/* Arrange C function AFTER to be called after the procedure returns.
 * Usually followed by Scm_VMApply* function.
 */

プロタイプが以下なカンジ

void Scm_VMPushCC(ScmCContinuationProc *after,
                  void **data, int datasize)

ちなみに ScmContinuationProc の定義が gauche/vm.h で以下

typedef ScmObj ScmCContinuationProc(ScmObj result, void **data);

ええと after を手続きから戻った後に呼び出されるようにしといて、大抵 Scm_VMapply* が後にナニ、という事かなぁ。Scm_VMDynamicWind() な末端は以下です。

    Scm_VMPushCC(dynwind_before_cc, data, 3);
    return Scm_VMApply0(before);

ひええ。この時点で val0 がどうなってるか、は現時点で微妙かも。とりあえず、Scm_VMPushCC() 手続きはざっくりベースで

  • ScmCContinuationProc な手続きを継続フレームの PC に設定
  • data なソレを引数として stack に積む

な後に VMapply* で何かをした後に上記で push した手続きに戻る、という事かと。

戻ってみる

例えば VMDynamicWind からだと関数定義が以下で

ScmObj Scm_VMDynamicWind(ScmObj before, ScmObj body, ScmObj after)
{
    void *data[3];

    /* NB: we don't check types of arguments, since we allo object-apply
       hooks can be used for them. */
    data[0] = (void*)before;
    data[1] = (void*)body;
    data[2] = (void*)after;

    Scm_VMPushCC(dynwind_before_cc, data, 3);
    return Scm_VMApply0(before);
}

before が適用された後の継続が dynwind_before_cc という事になるのか。val0 は不明なので実際な例が無いと微妙。

明日

アタマを冷して確認して先を検討予定ッス。(とほほ