Scm_VMCallCC (14)

save_cont 手続き、ざっくり確認。確かに_フレームのヒープへのコピー_な文書に書かれている形になるのは理解できました。

ちょっとだけ

環境のセーブに戻って確認とか。

コピーされたフレームを指しているポインタの変更

これは get_env 手続きで言うと save_env した後の処理を指していると見た。

    e = save_env(vm, vm->env);
    if (e != vm->env) {
        vm->env = e;
        for (c = vm->cont; IN_STACK_P((ScmObj*)c); c = c->prev) {
            if (FORWARDED_ENV_P(c->env)) {
                c->env = FORWARDED_ENV(c->env);
            }
        }
    }

_調べるべきは現在のコンティニュエーションチェインのみ_という事で

  • vm->env が退避されたなら
    • vm->env は退避先のポインタ値を格納
    • vm->cont を順に手繰りつつ、env 属性の size が -1 なソレがある度に、退避先の heap なポインタ値に更新

という事をしている風に読めます。これは正に上記の文書に書いてある通り。

ローカル環境をポップした時のspの値

これは let を使ったナニを disasm して確認してみる必要あり。ちょっと先に進めたいのでここではスルー。

save_cont に戻る

ええとどうしよう。ざっくりは理解できてるんですが、まだ

gosh> (list 1 2 3 (call/cc (lambda (c) (set! cont c) 4)) 5 6)
(1 2 3 4 5 6)
gosh> (cont 8)
(1 2 3 8 5 6)
gosh> 

なソレがきちんと説明できるレベルに至ってはいないな。もう少しきちんと全体を見渡す必要あり。

もう少し

ポイントのみ以下に控え。

  • vm->env を save_env して戻りを vm->env にセットしている
  • vm->cont が退避済みだったら終了
  • vm->cont を始点に退避されてない継続フレームなリストについて以下の処理
    • 領域の確保
      • これ、継続フレーム + 引数フレームのサイズ?
      • _フレームのヒープへのコピー_な文書と微妙に違う?
    • c->env の確認とか
      • c->env が heap に退避されてたら c->env を heap なポインタ値に設定
      • c->env がスタック内にあった場合、save_env する
    • 継続フレームのコピィ
      • c->argp が NULL 以外 (通常の継続?) なら継続フレームと c->argp が指す領域を確保した領域にセット
      • そうでない (C continuation の) 場合、ざっくりコピー
      • C continuation って継続フレームな領域と引数な領域が連続している模様
    • リンクの貼り直し
      • ココ参照の事
      • 図のナニは現時点で完全に理解できてない
    • 今、退避した領域を以下が指している場合、退避したソレを指すよう修正
      • vm->cont
      • vm->cstack
      • vm-escapePoint
      • SCM_VM_FLOATING_EP(vm)
      • いっちゃん最後のソレは何でしょ

微妙な部分

  • 作りかけの引数フレームの処理について

あ、どうも以下が参考になるみたい。

gosh> (disasm (lambda () (list 1 2 3 (call/cc (lambda (c) (set! cont c) 4)) 5 6)))
main_code (name=#f, code=0x8117e70, size=14, const=2, stack=13):
args: #f
     0 CONSTI-PUSH(1)
     1 CONSTI-PUSH(2)
     2 CONSTI-PUSH(3)
     3 PRE-CALL(1) 9
     5 CLOSURE #<lambda 0>      ; (lambda (c) (set! cont c) 4)
     7 PUSH-GREF-CALL(1) #<identifier user#call/cc>; (call/cc (lambda (c) (set! cont c) 4))
     9 PUSH
    10 CONSTI-PUSH(5)
    11 CONSTI(6)
    12 LIST(6)                  ; (list 1 2 3 (call/cc (lambda (c) (set! c ...
    13 RET
internal_closure_0 (name=#f, code=0x80d7b70, size=5, const=1 stack=0):
args: #f
     0 LREF0                    ; c
     1 GSET #<identifier user#cont>; cont
     3 CONSTI(4)
     4 RET
#<undef>
gosh> 

ちょっと今日も早めに限界です。