Scm_VMCallCC (12)
ちょっと今日も色々とばたばたしたので進捗は微妙だと思います (を
ブラウザの
履歴をよんどころのない事情にて検索中に_Gauche:YAGHG:VM:フレームのヒープへのコピー_という文書を発見。ちょっと URL のコピペが微妙なのでタイトルのみ、なのが自分的に微妙。
それは良いとして、この資料を見つつへろへろながらも_ひらメソド_方式で控え。
save_env
引用しつつコメントを。
static inline ScmEnvFrame *save_env(ScmVM *vm, ScmEnvFrame *env_begin) { ScmEnvFrame *e = env_begin, *prev = NULL, *next, *head = NULL, *saved;
- 変数をナニ
- e : 処理対象になってる環境フレームを指す
- up を手繰って処理が進む
- スタックの中認定の限り処理続行
- prev : 直前に退避された要素を指す
- next : 環境フレームの次の処理対象の要素を指す
- head : 保存されたフレームの先頭要素を指す (これが戻る)
- saved : ヒープな領域を指すためのポインタ
- 若干微妙なハンドル
- e : 処理対象になってる環境フレームを指す
で、env_begin が指すナニが既に退避済みかどうかを判定
if (!IN_STACK_P((ScmObj*)e)) return e;
繰り返しの先頭でも退避済みかどうかをチェキ
do { int esize = e->size, i; ScmObj *d, *s; if (e->size < 0) { /* forwaded frame */ if (prev) prev->up = FORWARDED_ENV(e); return head; }
基本的に処理対象の e がスタックの中である限り処理が続行される仕様。ただし size 属性が負の値だった場合は既にヒープに退避されたものとなる。
if (prev)
の中の処理はマンガ描く必要あり。ここではスルー。ちょっと気持ち悪いのでざくっと見てみると
A -> B -> C -> end
な環境フレームなリストがあるとして
# 矢印は up なリンクです
ケツまで save_env したら
A -> A' -> B' -> B -> C' ->end C ->
みたいなカンジになる?
# B' は A' と B の up で
# C' は B7 と C の up になる形?
save_env の戻りは A' になるはず。A, B, C の size は -1、info は #f になる?
むむ
_Gauche:YAGHG:VM:フレームのヒープへのコピー_な文書に以下の記述あり。
envレジスタやコンティニュエーションフレームが指す環境フレームを、新しく作られたそれを指すように設定し直すのはsave_envを呼び出す次の環境の仕事である。
- get_env
- save_cont
リンクの関係が微妙、と言いつつ上記の文書を見つつソースを確認。get_env 手続きにて以下なナニ。
static ScmEnvFrame *get_env(ScmVM *vm) { ScmEnvFrame *e; ScmContFrame *c; 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); } } } return e; }
なるほど。別な構造体が指してる可能性があるから残してるのか。
あら?
なんかもの凄く何かを端折ってる気がします。ちゃんと最後までヤッときます。
d = SCM_NEW2(ScmObj*, ENV_SIZE(esize) * sizeof(ScmObj)); for (i=ENV_SIZE(esize), s = (ScmObj*)e - esize; i>0; i--) { *d++ = *s++; }
あら? s にセットされてるナニは一体?
って微妙な思い込みが御座いました。環境フレームは引数が push されて最後に ScmEnvFrame なナニが最後に積まれるのか (FINISH_ENV)。なので始点が
s = (ScmObj*)e - esize;
なんですな。どうもデータ構造をきちんとイメージできてないな。参考になったのは gauche/vm.h の以下のコメント。
/* * Environment frame * * : : * +--------+ * | size=N | * | info | * |...up...|<--- ScmEnvFrame* envp * |arg[N-1]| * |arg[N-2]| * : : * | arg[0] | * +--------+ * : : */
で、
saved = (ScmEnvFrame*)(d - ENV_HDR_SIZE);
なナニで saved は ScmEnvFrame の先頭を指してるはず。d は ScmObj なのでナニ。あとはコード引用略で以下。
- prev が NULL でなければ prev->up に saved をセット
- 直前に saved にセットされた次 (up) を saved に
- A' -> B' というリンクを張ってます
- head が NULL だったら saved をセット (先頭の保存
- next に e->up をセット
- 次、の保存
- e->up と prev に saved をセット
- A -> A' なリンクを直前に saved にセットされたナニの保存
- 属性の設定
- 次の要素の設定
微妙ですが、メモ、という事でそろそろ限界ッス。