Project

jit_buffer

0.0
The project is in a healthy, maintained state
A JIT Buffer object for Ruby.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 5.15
~> 13.0

Runtime

~> 1.1
 Project Readme

JIT Buffer

This is a general purpose JIT Buffer object for building JITs in Ruby.

Usage

Create a JIT Buffer, then specify the size. The JIT Buffer can only be writeable or executable, but not both at the same time.

It starts life as executable, so you need to mark it writeable before writing.

# Make a buffer of size 4096
buffer = JITBuffer.new 4096

# Make writeable
buffer.writeable!

# Write some stuff
buffer.write "hello"

If you want to execute the JIT instructions, you need to mark it executable again.

Here is a full example that only works on ARM64:

require "jit_buffer"

# ARM instructions
def movz reg, imm
  insn = 0b0_10_100101_00_0000000000000000_00000
  insn |= (1 << 31)  # 64 bit
  insn |= (imm << 5) # immediate
  insn |= reg        # reg
end

def ret xn = 30
  insn = 0b1101011_0_0_10_11111_0000_0_0_00000_00000
  insn |= (xn << 5)
  insn
end

buffer = JITBuffer.new 4096

# Assemble some instructions
insns = [
  movz(0, 42),  # mov X0, 42
  ret           # ret
].pack("L<L<")

# Write the instructions to the JIT buffer
buffer.writeable!
buffer.write insns
buffer.executable!

# Call the instructions.  We JIT'd a function that
# returns an integer "42"
func = buffer.to_function([], Fiddle::TYPE_INT)
puts func.call # returns 42