From 81fbc8d5531be5e61f639c2ee4509017b5e010a0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 13 Aug 2022 23:50:00 +0900 Subject: [PATCH] Move `mjit_exec` to vm.c --- mjit.h | 95 -------------------------------------------------------- vm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 95 deletions(-) diff --git a/mjit.h b/mjit.h index fad18208fb..48790f6617 100644 --- a/mjit.h +++ b/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_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); # ifdef MJIT_HEADER diff --git a/vm.c b/vm.c index 4b1a30e7ca..394fa33388 100644 --- a/vm.c +++ b/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); 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" #ifndef MJIT_HEADER