Age | Commit message (Collapse) | Author |
|
Renaming uJIT to YJIT. AKA s/ujit/yjit/g.
|
|
This field was never used and is now covered by jit_mov_gc_ptr.
|
|
For deferred compilation, we sometimes want to care about the order of
the block versions. Use an array instead of a linked list to do that.
|
|
|
|
To allow analyzing sections of the application.
|
|
This allows counting things in generated code such as side exits or
different reasons for failing to compile. Runtime counters are exposed
to Ruby as `UJIT.runtime_stats` for ease of reporting and analysis.
|
|
|
|
|
|
* ujit: implement opt_getinlinecache
Aggressively bet that writes to constants don't happen and invalidate
all opt_getinlinecache blocks on any and all constant writes.
Use alignment padding on block_t to track this assumption. No change to
sizeof(block_t).
* Fix compile warnings when not RUBY_DEBUG
* Fix reversed condition
* Switch to st_table to keep track of assumptions
Co-authored-by: Aaron Patterson <aaron.patterson@gmail.com>
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
|
|
|
|
|
|
|
|
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
|
|
* uJIT: don't compile tailcalls
* Don't compile calls to protected methods
We need to generate extra code to check whether the call goes through if
we want to support these.
* Fix copy pasta
* Update blockids in branches
* Update dependencies
|
|
|
|
|
|
* Tie lifetime of uJIT blocks to iseqs
Blocks weren't being freed when iseqs are collected.
* Add rb_dary. Use it for method dependency table
* Keep track of blocks per iseq
Remove global version_tbl
* Block version bookkeeping fix
* dary -> darray
* free ujit_blocks
* comment about size of ujit_blocks
|
|
|
|
|
|
|
|
shopify/ruby#23
|
|
shopify/ruby#23
|
|
|
|
|
|
This commit adds a callback `rb_ujit_bop_redefined` when a basic
operation is redefined.
|
|
|
|
|
|
shopify/ruby#29
Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
|
|
VM and ujit instruction counting in debug builds.
shopify/ruby#19
|
|
|
|
|
|
|
|
|
|
|
|
This lets us use libcapstone directly from miniruby so we don't need a
Ruby Gem to to dev work.
Example usage:
```ruby
def foo(x)
if x < 1
"wow"
else
"neat"
end
end
iseq = RubyVM::InstructionSequence.of(method(:foo))
puts UJIT.disasm(iseq)
100.times { foo 1 }
puts UJIT.disasm(iseq)
```
Then in the terminal
```
$ ./miniruby test.rb
== disasm: #<ISeq:foo@test.rb:1 (1,0)-(7,3)> (catch: FALSE)
local table (size: 1, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] x@0<Arg>
0000 getlocal_WC_0 x@0 ( 2)[LiCa]
0002 putobject_INT2FIX_1_
0003 opt_lt <calldata!mid:<, argc:1, ARGS_SIMPLE>
0005 branchunless 10
0007 putstring "wow" ( 3)[Li]
0009 leave ( 7)[Re]
0010 putstring "neat" ( 5)[Li]
0012 leave ( 7)[Re]
== ISEQ RANGE: 10 -> 10 ========================================================
0x0: movabs rax, 0x7fe816e2d1a0
0xa: mov qword ptr [rdi], rax
0xd: mov r8, rax
0x10: mov r9, rax
0x13: mov r11, r12
0x16: jmp qword ptr [rax]
== ISEQ RANGE: 0 -> 7 ==========================================================
0x0: mov rax, qword ptr [rdi + 0x20]
0x4: mov rax, qword ptr [rax - 0x18]
0x8: mov qword ptr [rdx], rax
0xb: mov qword ptr [rdx + 8], 3
0x13: movabs rax, 0x7fe817808200
0x1d: test byte ptr [rax + 0x3e6], 1
0x24: jne 0x3ffff7b
0x2a: test byte ptr [rdx], 1
0x2d: je 0x3ffff7b
0x33: test byte ptr [rdx + 8], 1
0x37: je 0x3ffff7b
0x3d: mov rax, qword ptr [rdx]
0x40: cmp rax, qword ptr [rdx + 8]
0x44: movabs rax, 0
0x4e: movabs rcx, 0x14
0x58: cmovl rax, rcx
0x5c: mov qword ptr [rdx], rax
0x5f: test qword ptr [rdx], -9
0x66: jne 0x3ffffd5
```
Make sure to `brew install pkg-config capstone`
|
|
|
|
|
|
This commit adds a module `UJIT`. The module allows you to insert the
initial Micro JIT instruction in to an arbitrary iseq like this:
```ruby
def foo(x)
if x < 1
"less than one"
else
"something else"
end
end
iseq = RubyVM::InstructionSequence.of(method(:foo))
UJIT.insert(iseq) # Add initial jump
```
After the initial jump is added, we can make Micro JIT do some work:
```ruby
100.times { foo(0) }
```
The `UJIT` module also exposes a method for finding all compiled blocks
for a given iseq, like this:
```ruby
blocks = UJIT.blocks_for(iseq)
```
We can sort the blocks by address and use the Crabstone gem (which is a
wrapper around `capstone`) to disassemble the generated code.
Here is the full code example:
```ruby
def foo(x)
if x < 1
"less than one"
else
"something else"
end
end
iseq = RubyVM::InstructionSequence.of(method(:foo))
UJIT.insert(iseq) # Add initial jump
100.times { foo(0) }
blocks = UJIT.blocks_for(iseq)
# brew install capstone
# gem install crabstone
require "crabstone"
cs = Crabstone::Disassembler.new(Crabstone::ARCH_X86, Crabstone::MODE_64)
puts iseq.disasm
blocks.sort_by(&:address).reverse.each do |block|
puts "== ISEQ RANGE: #{block.iseq_start_index} -> #{block.iseq_end_index} ".ljust(80, "=")
cs.disasm(block.code, 0).each do |i|
printf(
"\t0x%<address>x:\t%<instruction>s\t%<details>s\n",
address: i.address,
instruction: i.mnemonic,
details: i.op_str
)
end
end
```
Here is the output:
```
$ ./ruby test.rb
== disasm: #<ISeq:foo@test.rb:1 (1,0)-(7,3)> (catch: FALSE)
local table (size: 1, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] x@0<Arg>
0000 getlocal_WC_0 x@0 ( 2)[LiCa]
0002 putobject_INT2FIX_1_
0003 opt_lt <calldata!mid:<, argc:1, ARGS_SIMPLE>
0005 branchunless 10
0007 putstring "less than one" ( 3)[Li]
0009 leave ( 7)[Re]
0010 putstring "something else" ( 5)[Li]
0012 leave ( 7)[Re]
== ISEQ RANGE: 7 -> 7 ==========================================================
0x0: movabs rax, 0x7fcd014cd518
0xa: mov qword ptr [rdi], rax
0xd: mov r8, rax
0x10: mov r9, rax
0x13: mov r11, r12
0x16: jmp qword ptr [rax]
== ISEQ RANGE: 0 -> 7 ==========================================================
0x0: mov rax, qword ptr [rdi + 0x20]
0x4: mov rax, qword ptr [rax - 0x18]
0x8: mov qword ptr [rdx], rax
0xb: mov qword ptr [rdx + 8], 3
0x13: movabs rax, 0x7fcd0180ac00
0x1d: test byte ptr [rax + 0x3e6], 1
0x24: jne 0x3ffe0da
0x2a: test byte ptr [rdx], 1
0x2d: je 0x3ffe0da
0x33: test byte ptr [rdx + 8], 1
0x37: je 0x3ffe0da
0x3d: mov rax, qword ptr [rdx]
0x40: cmp rax, qword ptr [rdx + 8]
0x44: movabs rax, 0
0x4e: movabs rcx, 0x14
0x58: cmovl rax, rcx
0x5c: mov qword ptr [rdx], rax
0x5f: test qword ptr [rdx], -9
0x66: je 0x3ffe111
0x6c: jmp 0xffffffffffffffa3
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|