| Age | Commit message (Collapse) | Author |
|
|
|
Follow up for ecb5b383a0c17550b9b27663005049ddac871edb. Now that
YJIT_STATS is defined in yjit.h, it shoudl be the only place that
defines it.
|
|
|
|
This fixes and re-enables invokesuper, replacing the existing guards
with a guard on the method entry for the EP.
|
|
This allows a block version to have dependencies on multiple CMEs.
|
|
For use cases where you want to collect the metrics
for a specific piece of code (typically a web request)
you can have the stats turned off by default and then
turn them on at runtime before executing the code you care
about.
|
|
This change fixes some cases where YJIT fails to fire tracing events.
Most of the situations YJIT did not handle correctly involves enabling
tracing while running inside generated code.
A new operation to invalidate all generated code is added, which uses
patching to make generated code exit at the next VM instruction
boundary. A new routine called `jit_prepare_routine_call()` is
introduced to facilitate this and should be used when generating code
that could allocate, or could otherwise use `RB_VM_LOCK_ENTER()`.
The `c_return` event is fired in the middle of an instruction as opposed
to at an instruction boundary, so it requires special handling. C method
call return points are patched to go to a fucntion which does everything
the interpreter does, including firing the `c_return` event. The
generated code for C method calls normally does not fire the event.
Invalided code should not change after patching so the exits are not
clobbered. A new variable is introduced to track the region of code that
should not change.
|
|
RUBY_DEBUG have a very significant performance overhead. Enough that
YJIT with RUBY_DEBUG is noticeably slower than the interpreter without
RUBY_DEBUG.
This makes it hard to collect yjit-stats in production environments.
By allowing to collect JIT statistics without the RUBy_DEBUG overhead,
I hope to make such use cases smoother.
|
|
return Qnil
|
|
|
|
If `--disable-jit-support` is passed to configure, then `jit_func` is
removed from the iseq body and we can't compile YJIT. This commit
detects when the JIT function pointer is gone and disables YJIT in that
case.
|
|
Now that we're using the jit function entry point, we don't need the
scraper. Thank you for your service, scraper. ❤️
|
|
|
|
Always using `ret` to return to the interpreter means that we never have
to check the VM_FRAME_FLAG_FINISH flag.
In the case that we return `Qundef`, the interpreter will execute the
cfp. We can take advantage of this by setting the PC to the instruction
we can't handle, and let the interpreter pick up the ball from there.
If we return a value other than Qundef, the interpreter will take that
value as the "return value" from the JIT and push that to the SP of the
caller
The leave instruction puts the return value on the top of the calling
frame's stack. YJIT does the same thing for leave instructions.
However, when we're returning back to the interpreter, the leave
instruction _should not_ put the return value on the top of the stack,
but put it in RAX and use RET. This commit pops the last value from the
stack pointer and puts it in RAX so that the interpreter is happy with
SP.
|
|
of RUBY_DEBUG and --yjit-stats/YJIT_STATS settings
|
|
|
|
|
|
The last parameter to rb_struct_define_under needs to be NULL otherwise
we can get a SEGV.
|
|
|
|
|
|
presumably-unneeded strncpy just to be sure.
|
|
|
|
|
|
|
|
|
|
|
|
For use in development for writing `test.rb` and running with `make
run`.
|
|
|
|
This adds a method to blocks to get outgoing ids, then uses the outgoing
ids to generate a graphviz graph. Two methods were added to the Block
object. One method returns an id for the block, which is just the
address of the underlying block. The other method returns a list of
outgoing block ids. We can use Block#id in conjunction with
Block#outgoing_ids to construct a graph of blocks
|
|
|
|
|
|
|
|
* Use builtin_inline_p to skip a frame of C methods
* Fix bugs in primitive cfunc call code
* Remove if (push_frame) {}
* Remove if (push_frame) {}
* Push Aaron's fix to avoid hardcoding insn lengths
Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
|
|
|
|
* Implement send with blocks
Not that much extra work compared to `opt_send_without_block`.
Moved the stack over flow check because it could've exited after changes
are made to cfp.
* rename oswb counters
* Might as well implement sending block to cfuncs
* Disable sending blocks to cfuncs for now
* Reconstruct interpreter sp before calling into cfuncs
In case the callee cfunc calls a method or delegates to a block.
This also has the side benefit of letting call sites that sometimes are
iseq calls and sometimes cfunc call share the same successor.
* only sync with interpreter sp when passing a block
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Aaron Patterson <aaron.patterson@shopify.com>
|
|
|
|
* Use INT32_MIN, INT32_MAX, etc. constants in yjit_asm.c
* Print warning on stderr when code past rel32 jump range
* Fix preprocessor snafu
* Move rel32 warning into --yjit-stats
* Try to allocate within rel32 offset on Linux machines
* Update yjit_asm.c
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
* On Linux, use sysconf to get the page size
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
|
|
* Implement eager versioning. Refactor versioning logic.
* Add --version-limit and --greedy-versioning command-line args
|
|
This commit fixes a build error. If we build in release mode (IOW
*without* RUBY_DEBUG), then this constant isn't defined. Release mode
builds are required by yjit-bench
|
|
* Malloc branch entries
* Add ASM comment for stack overflow check
* WIP
* Fix branch GC code. Add rb_darray_remove_unordered().
* Fix block end_pos after branch rewriting. Remove dst_patched bits.
|
|
Make sure `opt_getinlinecache` is in a block all on its own, and
invalidate it from the interpreter when `opt_setinlinecache`.
It will recompile with a filled cache the second time around.
This lets YJIT runs well when the IC for constant is cold.
|
|
|
|
|
|
Introduce a new macro `ADD_COMMENT(cb, comment)` that records a comment
for the current write position in the code block.
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Aaron Patterson <aaron.patterson@shopify.com>
|
|
|
|
Don't count instructions that take exit to the interpreter.
|
|
This commit collects statistics about how many binding objects are
allocated as well as the number of local variables set on bindings.
Statistics are output along with other YJIT stats. Here is an example
of the output:
```
***YJIT: Printing runtime counters from yjit.rb***
Number of Bindings Allocated: 195
Number of locals modified through binding: 0
opt_send_without_block exit reasons:
ivar_get_method 7515891 (40.4%)
se_cc_klass_differ 3081330 (16.6%)
iseq_argc_mismatch 1564578 ( 8.4%)
se_receiver_not_heap 1557663 ( 8.4%)
ic_empty 1407064 ( 7.6%)
optimized_method 995823 ( 5.4%)
iseq_not_simple 819413 ( 4.4%)
alias_method 706972 ( 3.8%)
bmethod 685253 ( 3.7%)
callsite_not_simple 225983 ( 1.2%)
kw_splat 25999 ( 0.1%)
ivar_set_method 902 ( 0.0%)
cfunc_toomany_args 394 ( 0.0%)
refined_method 42 ( 0.0%)
cfunc_ruby_array_varg 29 ( 0.0%)
invalid_cme 4 ( 0.0%)
leave exit reasons:
se_finish_frame 4067107 (100.0%)
se_interrupt 24 ( 0.0%)
getinstancevariable exit reasons:
undef 121177 (100.0%)
idx_out_of_range 5 ( 0.0%)
opt_aref exit reasons:
(all relevant counters are zero)
compiled_iseq_count: 3944
main_block_code_size: 1.1 MiB
side_block_code_size: 0.6 MiB
vm_insns_count: 1137268516
yjit_exec_insns_count: 414015644
ratio_in_yjit: 26.7%
avg_len_in_yjit: 7.5
total_exit_count: 55491789
most frequent exit op:
opt_send_without_block: 18587628 (33.5%)
opt_getinlinecache: 11075822 (20.0%)
send: 4949300 (8.9%)
leave: 4067131 (7.3%)
defined: 3975196 (7.2%)
setinstancevariable: 3567315 (6.4%)
invokesuper: 2982163 (5.4%)
getblockparamproxy: 2168852 (3.9%)
opt_nil_p: 2104524 (3.8%)
opt_aref: 2013858 (3.6%)
```
Running RailsBench allocates 195 binding objects but doesn't set any
local variables.
|
|
|
|
Replacing the key was only okay if the new key hashes to the same thing
as the old key. That doesn't hold for YJIT's table when the keys move.
|
|
Mostly unused and uninitialized warnings here and there
|