我想观察 YARV 执行的 Ruby 字节码,事后。
我怎样才能得到这个?
这里的其他人告诉这是不可能的。不过有hotruby框架好像是执行ruby字节码的,所以很纳闷……
非常感谢!
您可以使用解释器很好地将一块 Ruby 代码编译为字节码(当然,只有 Ruby MRI 1.9 可以工作,因为它是唯一使用 YARV 虚拟机的实现),并获得其 Ruby-ish 表示:
ruby-1.9.2-p180 :007 > require 'pp'
=> true
ruby-1.9.2-p180 :008 > pp RubyVM::InstructionSequence.compile('puts "hello world"').to_a
["YARVInstructionSequence/SimpleDataFormat",
1,
2,
1,
{:arg_size=>0, :local_size=>1, :stack_max=>2},
"<compiled>",
"<compiled>",
nil,
1,
:top,
[],
0,
[],
[1,
[:trace, 1],
[:putnil],
[:putstring, "hello world"],
[:send, :puts, 1, nil, 8, 0],
[:leave]]]
这正是 HotRuby 所做的:它使用 MRI 作为解析器和 AST-to-YARV 转换器,然后只执行 JavaScript 中的代码。
您可以使用该方法获取现有方法的字节码RubyVM::InstructionSequence.disasm
。它需要 aProc
作为参数,因此首先使用 . 将您的方法转换为块object.method(:name).to_proc
。
我不太清楚你所说的“验尸”是什么意思。在异常处理程序中?在 Ruby 与 SEGV 崩溃之后?后者几乎不可能,因为损坏的解释器无法成功运行任何 Ruby 代码。你需要为此做一个 C 扩展,并做很多肮脏的 hack。通过在异常处理程序中使用这个技巧是完全可能的。
据我了解,RubyVM::InstructionSequence.compile
是你需要的。
要获得更具可读性的输出,您可以使用disasm
aftercompile
[17] pry(main)> code = <<STR
[17] pry(main)* puts "Hello World"
[17] pry(main)* STR
=> "puts \"Hello World\"\n"
[19] pry(main)> puts RubyVM::InstructionSequence.compile(code).disasm
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace 1 ( 1)
0002 putself
0003 putstring "Hello World"
0005 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>
0007 leave
=> nil
[20] pry(main)>