■
なんか行き詰まったので休憩。集中力が一時間ぐらいしか続かないらしい。
■
おおざっぱに、現在構想中のvmまわりについてメモ。楽しい話題なのかどうかは知らない。
今のVMがこんな感じ
struct vm_state GTY(()) { VEC(tree) *stack; // tree スタック VEC(tree) *consts; // 定数テーブル VEC(tree) *functions; // 関数テーブル tree cur_func; ilog_mod cur_mod; tree env; unsigned int pc; unsigned int fp_i; VEC(char) *code; VEC(int) *i_stack; // 整数スタック tree *GTY((skip))fp; };
スタックがtree用とint用の二本あってもったいないんだけど、GCCのGC(garbage collecterね)の構造上仕方がない。ポインタと整数を混ぜられない。
VECでスタック参照すると、毎回ポインタを参照しないといけなくなるので、VECまわりはもうちょっとなんとかしたほうがいい。でも、ひょっとしたらそんなにオーバーヘッドではないかもしれない。VECは、GCCの可変長配列ライブラリなのだけど、変態マクロでテンプレートしてるので、そういうのが好きな人は読んでみると良いかと。(gcc/vec.h)
GCCはver. 3系列までは配列の先とか、ポインタの先とか、構造体の先とかの解析が弱い。ような気がする。
// arr[0]にスタックが割り当てられる int func() { int arr[4]; arr[0] = 3; call(); return arr[0]; } // return 40になる。 int func2() { int x = 40; call(); return x; }
だから、アレ。VECだとアレかもしんない。別にいいけど。そのうち考える。
継続も例外も考えてないのでフレーム構造は簡単。のはず。例外は…どうするか。よくわからん。そのうち考える。
callでスタックに詰むのは、PC、FP、CUR_FUNC…だけ、か。少ないな。いや、そんなもんか。現在呼び出してる関数があるので、それを辿っていけば、どうにでもなる。はず。RET命令のアレはいらないよ>自分。あー、FPを積まないと。いやFPは積んでるんだけど、FPが。
前のループ問題は
function func() { for ( var i=0; i<20; i++ ) { var x; return function () { return x; } } }
こういうのがあったら、
LOAD_CONST 0 SET_LOCAL 0 ; i = 0 label: BIND 1 CLOSURE1 <anon func> LOAD_CONST 20 LOAD_LOCAL 0 JLT labale
こんな感じにする、BINDすると、フレーム作る。anon funcが
LOAD_OUTER 1,0 ; 一個外側のloacal0 RET
こんな感じ。
けど、これ、ループで作ったフレームがこの関数以外で使われることが無いんだから、このループのフレームと関数呼び出された時のフレームを一緒にしてしまえば、LOAD_LOCALになるんじゃないの?あー。無理無理。再帰してると無理。気付いてよかった。
■
げー、こんな時間だ。休憩してたつもりが、なんか時間無くなっちゃったよ。