Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to observe the Ruby bytecode executed by YARV

I would like to observe the Ruby bytecode executed by YARV, post mortem.

How can I get this ?

Someone else here told it was not possible. However, there is the hotruby framework that seems to execute ruby bytecode, so I am puzzled...

Thanks a lot!

like image 915
JCLL Avatar asked Aug 01 '11 09:08

JCLL


2 Answers

You can very well compile a chunk of Ruby code to the bytecode using the interpreter (of course, only the Ruby MRI 1.9 will work, as it is the only implementation which uses the YARV virtual machine), and get its Ruby-ish representation:

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]]]

This is exactly what HotRuby does: it uses MRI as a parser and AST-to-YARV translator, and then just executes the code in JavaScript.

You can get the bytecode for an existing method with the RubyVM::InstructionSequence.disasm method. It expects a Proc as an argument, so first convert your method to a block by using object.method(:name).to_proc.

I'm not quite sure what do you mean by 'post-mortem'. In an exception handler? After Ruby has crashed with SEGV? The latter is hardly possible due to inability of damaged interpreter to run any Ruby code successfully. You'll need to make a C extension for that, and do quite a lot of dirty hacks. Using this trick in the exception handler is perfectly possible, through.

like image 59
whitequark Avatar answered Nov 19 '22 01:11

whitequark


As far as I understand, RubyVM::InstructionSequence.compile is what you need.

like image 2
Victor Deryagin Avatar answered Nov 19 '22 00:11

Victor Deryagin