I noticed this while running test_yjit with --mjit-call-threshold=1,
which redefines `Integer#<`. When Ruby is monkey-patched,
MJIT itself could be broken.
Similarly, Ruby scripts could break MJIT in many different ways. I
prepared the same set of hooks as YJIT so that we could possibly
override it and disable it on those moments. Every constant under
RubyVM::MJIT is private and thus it's an unsupported behavior though.
All values should have a MJIT_ prefix. We could address the warning for
the end mark if we just define the macro for the check next to the enum.
It even simplifies some code for checking the enum.
You may use `RUBYOPT=--mjit=pause irb` to play with RubyVM::MJIT::C,
control the boot timing of MJIT, or customize the implementation while
paused. It's an undocumented feature for such experiments.
Use ISEQ_BODY macro to get the rb_iseq_constant_body of the ISeq. Using
this macro will make it easier for us to change the allocation strategy
of rb_iseq_constant_body when using Variable Width Allocation.
We were exporting a couple of symbols in yjit.h because they could be
used by code generated by MJIT. We don't want MJIT calling into YJIT
code anyways so let's stop exporting them to libruby.so.
Also adjust indentation and comments in mjit_exec().
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.
by a race condition by multiple Ractors.
Atmically incrementing body->total_calls may have its own cost, so for
now we intentionally leave the unreliable total_calls. So we allow an
ISeq to be never pushed when you use multiple Ractors. However, if you
enqueue a single ccan node twice, get_from_list loops infinitely. Thus
this patch takes care of such a situation.
Compiling everything seems to contributed to improving the final
performance in general. MJIT's compilation is slow anyway, especially
when you need to wait for JIT compaction.
This might make sense for short-time benchmarks like Optcarrot with
default parameters, but it didn't give benefits in my local environment.
constant cache `IC` is accessed by non-atomic manner and there are
thread-safety issues, so Ruby 3.0 disables to use const cache on
non-main ractors.
This patch enables it by introducing `imemo_constcache` and allocates
it by every re-fill of const cache like `imemo_callcache`.
[Bug #17510]
Now `IC` only has one entry `IC::entry` and it points to
`iseq_inline_constant_cache_entry`, managed by T_IMEMO object.
`IC` is atomic data structure so `rb_mjit_before_vm_ic_update()` and
`rb_mjit_after_vm_ic_update()` is not needed.
to avoid SEGV on mjit_recompile and compact_all_jit_code.
For some reason, ISeqs on stack are sometimes GC-ed (why?) and therefore
it may run mjit_recompile on a GC-ed ISeq, which I expected d07183ec85
to fix but apparently it may refer to random things if already GC-ed.
Marking active_units would workaround the situation.
http://ci.rvm.jp/results/trunk-mjit-wait@phosphorus-docker/3292740
Also, while compact_all_jit_code was executed, we saw some SEGVs where
CCs seemed to be already GC-ed, meaning their owner ISeq was not marked
properly. Even if units are still in active_units, it's not guaranteed
that their ISeqs are in use. So in this case we need to mark active_units
for a legitimate reason.
http://ci.rvm.jp/results/trunk-mjit-wait@phosphorus-docker/3293277http://ci.rvm.jp/results/trunk-mjit-wait@phosphorus-docker/3293090
The original motivation of this marking was https://github.com/k0kubun/yarv-mjit/issues/20.
As wanabe said, there are multiple options to mitigate the issue, and
Eric Wong introduced another fix at 143776f6fe by checking unit->iseq
inside the lock.
Therefore this particular condition has been covered in two ways, and
the script given by wanabe no longer crashes without mjit_mark().
by calling combined functions specialized for each cancel type.
I'm hoping to improve locality of hot code, but this patch's impact should
be insignificant.