-fno-inline オプション
R5RS の例を最適化抑制 (インライン化しない?) なオプションで disasm してみる。
gosh -fno-inline -E '(disasm (lambda () (let ((x 5)) (letrec ((foo (lambda (y) (bar x y))) (bar (lambda (a b) (+ (* a b) a)))) (foo (+ x 3))))))' main_code (name=#f, code=0x80f7ea0, size=12, const=2, stack=17): args: #f 0 LOCAL-ENV-CLOSURES(2) (#<lambda 0>#<lambda 1>); (letrec ((foo (lambda (y) (bar x y))) (b ... 2 PRE-CALL(2) 8 4 CONSTI-PUSH(5) 5 CONSTI-PUSH(3) 6 GREF-CALL(2) #<identifier user#+>; (+ x 3) 8 PUSH 9 LREF1 ; foo 10 TAIL-CALL(1) ; (foo (+ x 3)) 11 RET internal_closure_1 (name=bar, code=0x80f8fa0, size=10, const=2 stack=12): args: #f 0 PRE-CALL(2) 5 2 LREF1-PUSH ; a 3 LREF0-PUSH-GREF-CALL(2) #<identifier user#*>; (* a b) 5 PUSH 6 LREF1-PUSH ; a 7 GREF-TAIL-CALL(2) #<identifier user#+>; (+ (* a b) a) 9 RET internal_closure_0 (name=foo, code=0x80d7db0, size=5, const=0 stack=5): args: #f 0 CONSTI-PUSH(5) 1 LREF0-PUSH ; y 2 LREF10 ; bar 3 TAIL-CALL(2) ; (bar x y) 4 RET *** ERROR: invalid application: (#<undef>) Stack Trace: _______________________________________ $
最後らへんが微妙ですが、最適化具合がもの凄い事は分かります。オプション略したら以下ですもの。
$ gosh -E '(disasm (lambda () (let ((x 5)) (letrec ((foo (lambda (y) (bar x y))) (bar (lambda (a b) (+ (* a b) a)))) (foo (+ x 3))))))' main_code (name=#f, code=0x80f6f40, size=8, const=0, stack=5): args: #f 0 CONSTI(3) 1 NUMADDI(5) ; (+ x 3) 2 PUSH-LOCAL-ENV(1) ; (foo (+ x 3)) 3 CONSTI-PUSH(5) 4 LREF0 ; y 5 NUMMUL2 ; (* a b) 6 NUMADDI(5) ; (+ (* a b) a) 7 RET *** ERROR: invalid application: (#<undef>) Stack Trace: _______________________________________ $
ちょっと控えておいて別途時間があるときに眺めてみる方向で。