3

For MRI 1.9+ and Rubinius implementation, Ruby source code is compiled into byte-code, and then that byte-code is interpreted by the VM. I want to know the details of this mechanism when running a Ruby script from command-line using the interpreter.

  • Does the interpreter compile all related source files required in the script first and then it run everything? Or does it execute some code and then compile other files while needed in a lazy way?
  • If it's the latter (which I suspect), is this process done by file or by a block of code?
  • At which point it stops the execution of byte-code and runs the compilation process again?
  • Does this process differ from MRI to Rubinius?

For example, if I run "ruby my_main_script.rb", which requires 3 other rb source files (and this files itself do not have any requirement), the possibility I imagine would be:

  • A: The interpreter parses my_main_script.rb and the 3 files. After parsing then, it compiles all AST trees to byte-code. It then proceeds to run the byte-code using the VM.

  • B: Ruby parses my_main_script.rb and compiles it into byte-code. It then runs the byte-code. When encountering a call to a method in another files, it first parse and compiles that files and the continues with the execution. If this is the case, I would like to understand this in detail.

  • C: Ruby parses and compiles some piece of code from my_main_script.rb according to some (unkwnon to me) criteria, it runs that byte-code and then parses-and-compiles another piece when needed. This process and that "when needed" condition detection method is what would be interesting for me to understand.


Update 30/03/16

I wrote this little experiment script to try to check if B is the right answer:

class RubyVM
  class InstructionSequence
    class << self
      alias :old_compile_file :compile_file
      def compile_file(code, opt)
        puts "Injecting code..."
        old_compile_file(code, opt)
      end
      alias :old_compile :compile
      def compile(code)
        puts "Injecting code..."
        old_compile(code)
      end
    end
  end
end

require_relative 'say_hi'

'say_hi.rb' only contains the line "puts 'hello'". If B is the right answer, shouldn't the output be the following?

Injecting code...
hello

It just outputs "hello"...

lucianolev
  • 519
  • 5
  • 5
  • Can you provide an example script, and then explain how that script would be executed differently in either of your theories? Like, if "the interpreter compiles all related source files required in the script first and then it runs everything", what would that look like? And if "it executes some code and then compiles other files while needed in a lazy way", what would that look like? – Bad Request Dec 20 '15 at 21:55
  • @kitkat done! Hope it helps – lucianolev Dec 20 '15 at 22:17
  • Thanks, that's perfect! – Bad Request Dec 20 '15 at 22:25
  • 1
    I think we can rule A out right off the bat because, how can Ruby know it needs to require 3 other files without executing the 3 `require` calls in `my_main_script.rb`? – Bad Request Dec 21 '15 at 15:22
  • I'm still not super clear how B is different from C. Suppose [these are the files](http://codepad.org/ZdfkjFqW), does B mean "just required required1" will print before "inside required1", and C is the other way round? – Bad Request Dec 21 '15 at 15:28
  • @kitkat: you just stole the main argument from that answer I meant to write for the last 18 hours :-D – Jörg W Mittag Dec 21 '15 at 17:47
  • 1
    Heh, it's not every day I get to beat _the_ @JörgWMittag to the punch! – Bad Request Dec 21 '15 at 17:53
  • @kitkat B can be seen as a special case of C, with "some piece of code" being "entire files". – lucianolev Dec 23 '15 at 00:38

1 Answers1

2

For me B is the right answer.

Ruby allows us to load dynamically our code via autoload and to execute strings as code (eval) so it must be able to parse and execute code at any time.

Therefore first it will transform all the files required by your main program to YARV instructions, but if you use autoload or eval those files/code will be transformed later.

A very good book about that process is Ruby under a microscope

Holin
  • 1,191
  • 10
  • 10
  • I've made a little script to check if this was true but I couldn't confirm it. Please check my update to the question. Btw, I've read Ruby under a microscope but it couldn't find an answer for this. – lucianolev Mar 30 '16 at 22:46