mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Move mjit_exec
to vm.c
This commit is contained in:
parent
ac890ec062
commit
81fbc8d553
Notes:
git
2022-08-17 15:23:33 +09:00
2 changed files with 97 additions and 95 deletions
95
mjit.h
95
mjit.h
|
@ -103,101 +103,6 @@ extern void mjit_cont_free(struct mjit_cont *cont);
|
||||||
extern void mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body);
|
extern void mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body);
|
||||||
extern void mjit_notify_waitpid(int status);
|
extern void mjit_notify_waitpid(int status);
|
||||||
|
|
||||||
# ifdef MJIT_HEADER
|
|
||||||
NOINLINE(static COLDFUNC VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body));
|
|
||||||
# else
|
|
||||||
static inline VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body);
|
|
||||||
# endif
|
|
||||||
static VALUE
|
|
||||||
mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body)
|
|
||||||
{
|
|
||||||
uintptr_t func_i = (uintptr_t)(body->jit_func);
|
|
||||||
ASSUME(func_i <= LAST_JIT_ISEQ_FUNC);
|
|
||||||
switch ((enum rb_mjit_iseq_func)func_i) {
|
|
||||||
case NOT_ADDED_JIT_ISEQ_FUNC:
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_exec_not_added);
|
|
||||||
if (body->total_calls == mjit_opts.min_calls) {
|
|
||||||
rb_mjit_add_iseq_to_process(iseq);
|
|
||||||
if (UNLIKELY(mjit_opts.wait)) {
|
|
||||||
return rb_mjit_wait_call(ec, body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NOT_READY_JIT_ISEQ_FUNC:
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_exec_not_ready);
|
|
||||||
break;
|
|
||||||
case NOT_COMPILED_JIT_ISEQ_FUNC:
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled);
|
|
||||||
break;
|
|
||||||
default: // to avoid warning with LAST_JIT_ISEQ_FUNC
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return Qundef;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to execute the current iseq in ec. Use JIT code if it is ready.
|
|
||||||
// If it is not, add ISEQ to the compilation queue and return Qundef for MJIT.
|
|
||||||
// YJIT compiles on the thread running the iseq.
|
|
||||||
static inline VALUE
|
|
||||||
mjit_exec(rb_execution_context_t *ec)
|
|
||||||
{
|
|
||||||
const rb_iseq_t *iseq = ec->cfp->iseq;
|
|
||||||
struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
|
|
||||||
bool yjit_enabled = false;
|
|
||||||
#ifndef MJIT_HEADER
|
|
||||||
// Don't want to compile with YJIT or use code generated by YJIT
|
|
||||||
// when running inside code generated by MJIT.
|
|
||||||
yjit_enabled = rb_yjit_enabled_p();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mjit_call_p || yjit_enabled) {
|
|
||||||
body->total_calls++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MJIT_HEADER
|
|
||||||
if (yjit_enabled && !mjit_call_p && body->total_calls == rb_yjit_call_threshold()) {
|
|
||||||
// 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 || yjit_enabled))
|
|
||||||
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 (yjit_enabled && func == 0) {
|
|
||||||
return Qundef;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UNLIKELY((uintptr_t)func <= LAST_JIT_ISEQ_FUNC)) {
|
|
||||||
# ifdef MJIT_HEADER
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_frame_JT2VM);
|
|
||||||
# else
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_frame_VM2VM);
|
|
||||||
# endif
|
|
||||||
return mjit_exec_slowpath(ec, iseq, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef MJIT_HEADER
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT);
|
|
||||||
# else
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT);
|
|
||||||
# endif
|
|
||||||
RB_DEBUG_COUNTER_INC(mjit_exec_call_func);
|
|
||||||
// Under SystemV x64 calling convention
|
|
||||||
// ec -> RDI
|
|
||||||
// cfp -> RSI
|
|
||||||
return func(ec, ec->cfp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mjit_child_after_fork(void);
|
void mjit_child_after_fork(void);
|
||||||
|
|
||||||
# ifdef MJIT_HEADER
|
# ifdef MJIT_HEADER
|
||||||
|
|
97
vm.c
97
vm.c
|
@ -377,6 +377,103 @@ extern VALUE rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, V
|
||||||
const rb_callable_method_entry_t *me);
|
const rb_callable_method_entry_t *me);
|
||||||
static VALUE vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE block_handler);
|
static VALUE vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE block_handler);
|
||||||
|
|
||||||
|
#if USE_MJIT
|
||||||
|
# ifdef MJIT_HEADER
|
||||||
|
NOINLINE(static COLDFUNC VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body));
|
||||||
|
# else
|
||||||
|
static inline VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body);
|
||||||
|
# endif
|
||||||
|
static VALUE
|
||||||
|
mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body)
|
||||||
|
{
|
||||||
|
uintptr_t func_i = (uintptr_t)(body->jit_func);
|
||||||
|
ASSUME(func_i <= LAST_JIT_ISEQ_FUNC);
|
||||||
|
switch ((enum rb_mjit_iseq_func)func_i) {
|
||||||
|
case NOT_ADDED_JIT_ISEQ_FUNC:
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_exec_not_added);
|
||||||
|
if (body->total_calls == mjit_opts.min_calls) {
|
||||||
|
rb_mjit_add_iseq_to_process(iseq);
|
||||||
|
if (UNLIKELY(mjit_opts.wait)) {
|
||||||
|
return rb_mjit_wait_call(ec, body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOT_READY_JIT_ISEQ_FUNC:
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_exec_not_ready);
|
||||||
|
break;
|
||||||
|
case NOT_COMPILED_JIT_ISEQ_FUNC:
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled);
|
||||||
|
break;
|
||||||
|
default: // to avoid warning with LAST_JIT_ISEQ_FUNC
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Qundef;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to execute the current iseq in ec. Use JIT code if it is ready.
|
||||||
|
// If it is not, add ISEQ to the compilation queue and return Qundef for MJIT.
|
||||||
|
// YJIT compiles on the thread running the iseq.
|
||||||
|
static inline VALUE
|
||||||
|
mjit_exec(rb_execution_context_t *ec)
|
||||||
|
{
|
||||||
|
const rb_iseq_t *iseq = ec->cfp->iseq;
|
||||||
|
struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
|
||||||
|
bool yjit_enabled = false;
|
||||||
|
# ifndef MJIT_HEADER
|
||||||
|
// Don't want to compile with YJIT or use code generated by YJIT
|
||||||
|
// when running inside code generated by MJIT.
|
||||||
|
yjit_enabled = rb_yjit_enabled_p();
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if (mjit_call_p || yjit_enabled) {
|
||||||
|
body->total_calls++;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifndef MJIT_HEADER
|
||||||
|
if (yjit_enabled && !mjit_call_p && body->total_calls == rb_yjit_call_threshold()) {
|
||||||
|
// 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 || yjit_enabled))
|
||||||
|
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 (yjit_enabled && func == 0) {
|
||||||
|
return Qundef;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY((uintptr_t)func <= LAST_JIT_ISEQ_FUNC)) {
|
||||||
|
# ifdef MJIT_HEADER
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_frame_JT2VM);
|
||||||
|
# else
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_frame_VM2VM);
|
||||||
|
# endif
|
||||||
|
return mjit_exec_slowpath(ec, iseq, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef MJIT_HEADER
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT);
|
||||||
|
# else
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT);
|
||||||
|
# endif
|
||||||
|
RB_DEBUG_COUNTER_INC(mjit_exec_call_func);
|
||||||
|
// Under SystemV x64 calling convention
|
||||||
|
// ec -> RDI
|
||||||
|
// cfp -> RSI
|
||||||
|
return func(ec, ec->cfp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "vm_insnhelper.c"
|
#include "vm_insnhelper.c"
|
||||||
|
|
||||||
#ifndef MJIT_HEADER
|
#ifndef MJIT_HEADER
|
||||||
|
|
Loading…
Reference in a new issue