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>

こーゆー手当たり次第なヤリ方もいかがなものか、とは思うんですが。。