Scm_VMDynamicWind

起点が何だったのか、が段々微妙になってきていますがどんどん続ける。
shiro さんからご教示頂いたナニも参考にしつつ

gosh> (disasm (lambda () (dynamic-wind a b c)))
main_code (name=#f, code=0x8163f78, size=9, const=4, stack=6):
args: #f
     0 GREF-PUSH #<identifier user#a>; a
     2 GREF-PUSH #<identifier user#b>; b
     4 GREF-PUSH #<identifier user#c>; c
     6 GREF-TAIL-CALL(3) #<identifier user#dynamic-wind>; (dynamic-wind a b c)
     8 RET
#<undef>
gosh> 

を元に掘削。途中は略で

  • 一旦 dynamic-wind に束縛されてる関数ポインタ値が val0 格納
  • PC に RET を仕込んで val0 な関数 (stdlib_dynamic_wind) 呼び出して戻りを val0 格納
  • 末尾呼び出しなので継続を pop して NEXT

という流れ。もう少し細かく見てみる。上記二番目以降の処理が以下。

                if (proctype == SCM_PROC_SUBR) {
                    /* We don't need to complete environment frame.
                       Just need to adjust sp, so that stack-operating
                       procs called from subr won't be confused. */
                    ADJUST_ARGUMENT_FRAME(VAL0, argc);
                    SP = ARGP;
                    PC = PC_TO_RETURN;
                    
                    SCM_PROF_COUNT_CALL(vm, VAL0);
                    VAL0 = SCM_SUBR(VAL0)->func(ARGP, argc,
                                                SCM_SUBR(VAL0)->data);
                    /* the subr may substituted pc, so we need to check
                       if we can pop the continuation immediately. */
                    if (TAIL_POS()) RETURN_OP();
                    NEXT;
                }

で、Scm_VMDynamicWind() の戻りが val0 に格納されるんですが shiro さんからのフォローの通り、

Scm_VMPushCC(dynamic_before_cc...); // 次のRETでdynamic_before_ccを呼んでね
return Scm_VMApply0(before); // 戻ったらbeforeを呼んでね

したがってこのルーチンからVM loopに戻った後に、

  • beforeが呼ばれ
  • beforeがRETする際にdynamic_before_ccが呼ばれる

という事になるのか。作成者な shiro さんからのフォローですがツッコんで確認してみると

  • 次のRETでdynamic_before_ccを呼んでね
    • 継続フレームに_dynamic_before_ccを呼んでね_なナニを push
  • 戻ったらbeforeを呼んでね
    • PC レジスタに TAIL_CALL と RET な配列の先頭ポインタをセット
    • proc (before ですね) を return して val0 に格納

という事でまず_before が呼ばれ_るんですね。で、RET する時に継続フレームが pop されるので_beforeがRETする際にdynamic_before_ccが呼ばれる_という事になる、と。

だらだら見てたら月曜になった。ここから先、順ぐりにめくってく感じなのはイメージできてるんですが、dynwind_before_cc あたりで vm->handlers を弄ってるのが微妙。あ、でも dynwind_body_cc で戻してますな。
うー。このあたり色々な操作を見越してるんでしょうが、意図しているナニを読み切れないのがとても腹立たしいカンジ。ってか引数に何が渡るか、も含めてきちんと精査した方が良さげ。