Skip to content

Instantly share code, notes, and snippets.

@barnaby
Created February 22, 2013 17:20
Show Gist options
  • Save barnaby/5015096 to your computer and use it in GitHub Desktop.
Save barnaby/5015096 to your computer and use it in GitHub Desktop.
Compile & execute Ruby as bytecode. Works in 1.9.3
#
#
# Compile & execute Ruby as bytecode
#
#
require 'rbconfig'
require 'dl'
require 'fiddle'
require 'strscan'
# This monkey patch allows us to load arbitrary byte code with
# Ruby's VM. Originally from: https://gist.github.com/cstrahan/3552903
class RubyVM
class InstructionSequence
handle = DL::Handle::DEFAULT
address = handle['rb_iseq_load']
func = Fiddle::Function.new(address, [DL::TYPE_VOIDP] * 3,
DL::TYPE_VOIDP)
define_singleton_method(:load) do |data, parent = nil, opt = nil|
func.call(DL.dlwrap(data), parent, opt).to_value
end
end
end
class Compiler
class << self
# Compile .rb file to .rbc file
def compile input, output
seq = RubyVM::InstructionSequence.compile(open(input).read)
File.write(output, Marshal.dump(seq.to_a))
end
# Require a .rbc file
def require_compiled file
seq = Marshal.load(File.read(file))
RubyVM::InstructionSequence.load(seq).eval
end
end
end
Compiler.compile('in.rb', 'out.rbc')
Compiler.require_compiled('out.rbc')
@thomthom
Copy link

Have you tried this is Ruby 2.0?

I keep getting an error:

unknown symbol "rb_iseq_load" (DL::DLError)

I see the function is in the source, but maybe it's been hidden since 1.9?
http://rxr.whitequark.org/mri/source/iseq.c?v=2.0.0-p481#579

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment