うーん
へろへろなので、と信じたいんですがよく分からん。
VMのスタック操作(未完) なるドキュメントをニラミつつナニ。
_通常の関数呼び出し_なマンガ見ながら色々検討した記憶があるような無いような。
とりあえず色々見てたんですが CALL なインストラクションは今の理解では微妙。きっかけが何かは忘れましたが、とりあえず PUSH_CONT マクロ。
/* Push a continuation frame. next_pc is the PC from where execution will be resumed. */ #define PUSH_CONT(next_pc) \ do { \ ScmContFrame *newcont = (ScmContFrame*)SP; \ newcont->prev = CONT; \ newcont->env = ENV; \ newcont->argp = ARGP; \ newcont->size = SP - ARGP; \ newcont->pc = next_pc; \ newcont->base = BASE; \ CONT = newcont; \ SP += CONT_FRAME_SIZE; \ ARGP = SP; \ } while (0)
これは正に_1. push cont_なソレですな。ええと、vm.c で M-x occur PUSH_CONT したら以下なナニが列挙 (ちなみに Gauche-0.8.11)。
TAIL_CALL_INSTRUCTION マクロ
以下。
/* used for the inlined instruction which is supposed to be called at tail position (e.g. SLOT-REF). This checks whether we're at the tail position or not, and if not, push a cont frame to make the operation a tail call. */ #define TAIL_CALL_INSTRUCTION() \ do { \ if (!TAIL_POS()) { \ CHECK_STACK(CONT_FRAME_SIZE); \ PUSH_CONT(PC); \ PC = PC_TO_RETURN; \ } \ } while (0)
コメントは後で見るとして、このマクロをナニしてるのが以下のインストラクション。
- APPLY
- SLOT_REF
- SLOT_SET
- SLOT_REFC
- SLOT_SETC
うーん。なんなんだ。SLOT_* は略として APPLY されて末尾呼び出しでなければ、
- スタックに継続フレーム push するナニがあるかチェキ
- 継続フレーム push
- PC に RET をナニ
という事ッスか。末尾呼び出しでなければ apply する時には継続フレームが push される、ってとりあえず参考コンテンツに書いてある通り?
# 問題になってるのは次以降なんですが ...
PRE_CALL インストラクション
CASE(SCM_VM_PRE_CALL) { ScmWord *next; CHECK_STACK_PARANOIA(CONT_FRAME_SIZE); FETCH_LOCATION(next); PUSH_CONT(next); INCR_PC; NEXT; }
むむ。PRE_CALL は CALL した直後にある命令のための継続の処理?
次
色々雑念が入ってワケワカんなくなり始めてるので機械的に。以下、簡単に PUSH_CONT マクロをナニしているインストラクションとか。
- RECEIVE
- IS_A
- run_loop のいっちゃんケツ
いっちゃんケツのソレが微妙。
process_queue: CHECK_STACK(CONT_FRAME_SIZE); PUSH_CONT(PC); process_queued_requests(vm); POP_CONT(); NEXT; } } /* End of run_loop */
正に末端。しかもぱっと見ワケワカ。
を
PUSH_ENV_HDR ぽいナニを見つけた。
/* push environment header to finish the environment frame. env, sp, argp is updated. */ #define FINISH_ENV(info_, up_) \ do { \ ScmEnvFrame *e__ = (ScmEnvFrame*)SP; \ e__->up = up_; \ e__->info = info_; \ e__->size = SP - ARGP; \ SP += ENV_HDR_SIZE; \ ARGP = SP; \ ENV = e__; \ } while (0)
あ、引数とかツむのってこの後になるのか。ちょっと限界気味なんで、明日これを見つつ復習予定ですが、時間が確保できるかどうかは微妙ッス。