Hatena::ブログ(Diary)

西尾泰和のはてなダイアリー

2010-08-03

Ruby|Pythonバイトコードをディスアセンブル

RubyにはPythonのdisみたいなものはないのかなぁと言っていたら、ささださんに教えてもらった。

irb(main):017:0> def facto(n)
irb(main):018:1>   if n == 0 then 1 else facto(n - 1) * n end
irb(main):019:1> end
=> nil
irb(main):020:0> puts RubyVM::InstructionSequence.disasm(Object.method(:facto))
== disasm: <RubyVM::InstructionSequence:facto@(irb)>====================
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] n<Arg>     
0000 trace            8                                               (  17)
0002 trace            1                                               (  18)
0004 getlocal         n
0006 putobject        0
0008 opt_eq           <ic:4>
0010 branchunless     18
0012 trace            1
0014 putobject        1
0016 jump             37
0018 trace            1
0020 putnil           
0021 getlocal         n
0023 putobject        1
0025 opt_minus        <ic:5>
0027 send             :facto, 1, nil, 8, <ic:2>
0033 getlocal         n
0035 opt_mult         <ic:6>
0037 trace            16                                              (  19)
0039 leave                                                            (  18)
=> nil

Pythonだとこう

>>> import dis
>>> def facto(n):
...   if n == 0:
...     return 1
...   else:
...     return facto(n - 1) * n
... 
>>> dis.dis(facto)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (0)
              6 COMPARE_OP               2 (==)
              9 JUMP_IF_FALSE            5 (to 17)
             12 POP_TOP             

  3          13 LOAD_CONST               2 (1)
             16 RETURN_VALUE        
        >>   17 POP_TOP             

  5          18 LOAD_GLOBAL              0 (facto)
             21 LOAD_FAST                0 (n)
             24 LOAD_CONST               2 (1)
             27 BINARY_SUBTRACT     
             28 CALL_FUNCTION            1
             31 LOAD_FAST                0 (n)
             34 BINARY_MULTIPLY     
             35 RETURN_VALUE        
             36 LOAD_CONST               0 (None)
             39 RETURN_VALUE