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>
ちょっと今日も早めに限界です。