compile/disassemble
なんとなくコードの compile と disassemble についてメモ。
Python では compile と dis module を使えば良い。
>>> code = compile("print 1+2", "<string>", "exec") >>> eval(code) 3 >>> import dis >>> dis.dis(code) 1 0 LOAD_CONST 3 (3) 3 PRINT_ITEM 4 PRINT_NEWLINE 5 LOAD_CONST 2 (None) 8 RETURN_VALUE
compile されたコードだけでなく、method や module も disassemble してくれる。
Ruby 1.9 の場合は VM::InstructionSequence.compile_を使って compile する。compile 結果のオブジェクトに eval メソッドや disasm メソッドがある。
irb(main):001:0> code = VM::InstructionSequence.compile("puts 1+2") => <ISeq:<compiled>@<compiled>> irb(main):002:0> code.eval 3 => nil irb(main):003:0> puts code.disasm == disasm: <ISeq:<compiled>@<compiled>>================================= 0000 putnil ( 1) 0001 putobject 1 0003 putobject 2 0005 opt_plus 0006 send :puts, 1, nil, 8, <ic> 0012 leave => nil
ちなみに VM::InstructionSequence.compile_option= でデフォルトのコンパイルオプションが変更できる。
irb(main):001:0> puts VM::InstructionSequence.compile("def f; f; end").disasm == disasm: <ISeq:<compiled>@<compiled>>================================= 0000 putnil ( 1) 0001 definemethod :f, f, 0 0005 putnil 0006 leave == disasm: <ISeq:f@<compiled>>========================================== 0000 putnil ( 1) 0001 send :f, 0, nil, 24, <ic> 0007 leave => nil irb(main):002:0> VM::InstructionSequence.compile_option = { :tailcall_optimization => true } => {:tailcall_optimization=>true} irb(main):003:0> puts VM::InstructionSequence.compile("def f; f; end").disasm == disasm: <ISeq:<compiled>@<compiled>>================================= 0000 putnil ( 1) 0001 definemethod :f, f, 0 0005 putnil 0006 leave == disasm: <ISeq:f@<compiled>>========================================== 0000 putnil ( 1) 0001 send :f, 0, nil, 56, <ic> 0007 leave => nil
VM::InstructionSequence.compile の第4引数に最適化オプションを指定することもできる(第2引数はファイル名、第3引数は開始行番号)。
irb(main):002:0> puts VM::InstructionSequence.compile("def f; f; end", "<compiled>", 1, { :tailcall_optimization => true }).disasm == disasm: <ISeq:<compiled>@<compiled>>================================= 0000 putnil ( 1) 0001 definemethod :f, f, 0 0005 putnil 0006 leave == disasm: <ISeq:f@<compiled>>========================================== 0000 putnil ( 1) 0001 send :f, 0, nil, 56, <ic> 0007 leave => nil
現在してできるコンパイルオプションは以下。
- inline_const_cache
- peephole_optimization
- tailcall_optimization
- specialized_instruction
- operands_unification
- instructions_unification
- stack_caching
- trace_instruction
まぁ、VM::InstructionSequence は1.9.1で消えるという話なんだけどな。まぁ、今日時点でまだ trunk に残っているけど。