PUSH_GREF_CALL
早めに寝る、と言いつつ disasm の旅に着手してしまう。基本的には
- val0 を push
- GLOBAL_REF で束縛を解決して val0 に格納
- val0 を呼び出す
という事で色々試しててようやく出た。
gosh> (disasm (lambda () (+ (x (y)) z))) main_code (name=#f, code=0x80f9ba0, size=12, const=3, stack=16): args: #f 0 PRE-CALL(1) 8 2 PRE-CALL(0) 6 4 GREF-CALL(0) #<identifier user#y>; (y) 6 PUSH-GREF-CALL(1) #<identifier user#x>; (x (y)) 8 PUSH-GREF #<identifier user#z>; z 10 NUMADD2 ; (+ (x (y)) z) 11 RET #<undef> gosh>
こうすると出ない。
gosh> (disasm (lambda () (+ (x y) z))) main_code (name=#f, code=0x8163d98, size=10, const=3, stack=10): args: #f 0 PRE-CALL(1) 6 2 GREF-PUSH #<identifier user#y>; y 4 GREF-CALL(1) #<identifier user#x>; (x y) 6 PUSH-GREF #<identifier user#z>; z 8 NUMADD2 ; (+ (x y) z) 9 RET #<undef> gosh>
例として妥当なのかどうか不明ですが、なんとなく成程なカンジ。ちなみに PUSH_GREF_TAIL_CALL が出てくるのは以下なパターン。
gosh> (disasm (lambda () (x (y)))) main_code (name=#f, code=0x80f8c80, size=7, const=2, stack=10): args: #f 0 PRE-CALL(0) 4 2 GREF-CALL(0) #<identifier user#y>; (y) 4 PUSH-GREF-TAIL-CALL(1) #<identifier user#x>; (x (y)) 6 RET #<undef> gosh>
こうしたら両方出てくるな。
gosh> (disasm (lambda () (x (y (z))))) main_code (name=#f, code=0x80f9a80, size=11, const=3, stack=17): args: #f 0 PRE-CALL(1) 8 2 PRE-CALL(0) 6 4 GREF-CALL(0) #<identifier user#z>; (z) 6 PUSH-GREF-CALL(1) #<identifier user#y>; (y (z)) 8 PUSH-GREF-TAIL-CALL(1) #<identifier user#x>; (x (y (z))) 10 RET #<undef> gosh>
こーゆー手当たり次第なヤリ方もいかがなものか、とは思うんですが。。