diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2021-07-07 11:15:40 -0700 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:37 -0400 |
commit | d0174d99c6fcbeae2d5cdaa34908b9ac117bb9c3 (patch) | |
tree | b36938eeb96470dcdf339a59a872fd37687badc8 /mjit.h | |
parent | b70383fbea8d4acc49eceed24c83d87637412ff4 (diff) |
Always use `ret` to return to the interpreter
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.
Diffstat (limited to 'mjit.h')
-rw-r--r-- | mjit.h | 18 |
1 files changed, 15 insertions, 3 deletions
@@ -150,17 +150,27 @@ mjit_exec(rb_execution_context_t *ec) #ifndef MJIT_HEADER if (rb_yjit_enabled_p() && !mjit_call_p && body->total_calls == rb_yjit_call_threshold()) { - rb_yjit_compile_iseq(iseq, ec); - return Qundef; + // If we couldn't generate any code for this iseq, then return + // Qundef so the interpreter will handle the call. + if (!rb_yjit_compile_iseq(iseq, ec)) { + return Qundef; + } } #endif - if (!mjit_call_p) + if (!(mjit_call_p || rb_yjit_enabled_p())) return Qundef; RB_DEBUG_COUNTER_INC(mjit_exec); mjit_func_t func = body->jit_func; + + // YJIT tried compiling this function once before and couldn't do + // it, so return Qundef so the interpreter handles it. + if (rb_yjit_enabled_p() && func == 0) { + return Qundef; + } + if (UNLIKELY((uintptr_t)func <= LAST_JIT_ISEQ_FUNC)) { # ifdef MJIT_HEADER RB_DEBUG_COUNTER_INC(mjit_frame_JT2VM); @@ -176,6 +186,8 @@ mjit_exec(rb_execution_context_t *ec) RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT); # endif RB_DEBUG_COUNTER_INC(mjit_exec_call_func); + // ec -> RDI + // cfp -> RSI return func(ec, ec->cfp); } |