Reduce the number of branches in jit_exec (#6722)

* Reduce the number of branches in jit_exec

* Address build failure in some configurations

* Refactor yjit.h
This commit is contained in:
Takashi Kokubun 2022-11-13 20:35:35 -08:00 коммит произвёл GitHub
Родитель ea278ddd92
Коммит 3dd4e381fe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 24 добавлений и 31 удалений

53
vm.c
Просмотреть файл

@ -378,7 +378,7 @@ 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 #if USE_MJIT || USE_YJIT
# ifdef MJIT_HEADER # ifdef MJIT_HEADER
NOINLINE(static COLDFUNC VALUE mjit_check_iseq(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body)); NOINLINE(static COLDFUNC VALUE mjit_check_iseq(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body));
# else # else
@ -412,46 +412,39 @@ mjit_check_iseq(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_ise
static inline VALUE static inline VALUE
jit_exec(rb_execution_context_t *ec) jit_exec(rb_execution_context_t *ec)
{ {
// Increment the ISEQ's call counter
const rb_iseq_t *iseq = ec->cfp->iseq; const rb_iseq_t *iseq = ec->cfp->iseq;
struct rb_iseq_constant_body *body = ISEQ_BODY(iseq); struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
bool yjit_enabled = false; bool yjit_enabled = rb_yjit_enabled_p();
# ifndef MJIT_HEADER if (yjit_enabled || mjit_call_p) {
// 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++; body->total_calls++;
} }
else {
return Qundef;
}
# ifndef MJIT_HEADER // Trigger JIT compilation as needed
if (yjit_enabled && !mjit_call_p && body->total_calls == rb_yjit_call_threshold()) { jit_func_t func;
// If we couldn't generate any code for this iseq, then return if (yjit_enabled) {
// Qundef so the interpreter will handle the call. if (body->total_calls == rb_yjit_call_threshold()) {
if (!rb_yjit_compile_iseq(iseq, ec)) { // 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;
}
}
// YJIT tried compiling this function once before and couldn't do
// it, so return Qundef so the interpreter handles it.
if ((func = body->jit_func) == 0) {
return Qundef; return Qundef;
} }
} }
# endif else if (UNLIKELY((uintptr_t)(func = body->jit_func) <= LAST_JIT_ISEQ_FUNC)) {
if (!(mjit_call_p || yjit_enabled))
return Qundef;
jit_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)) {
return mjit_check_iseq(ec, iseq, body); return mjit_check_iseq(ec, iseq, body);
} }
// Under SystemV x64 calling convention: ec -> RDI, cfp -> RSI // Call the JIT code
return func(ec, ec->cfp); return func(ec, ec->cfp); // SystemV x64 calling convention: ec -> RDI, cfp -> RSI
} }
#endif #endif

2
yjit.h
Просмотреть файл

@ -15,7 +15,7 @@
# define YJIT_STATS RUBY_DEBUG # define YJIT_STATS RUBY_DEBUG
#endif #endif
#if USE_YJIT #if USE_YJIT && !defined(MJIT_HEADER) // MJIT and YJIT can't be enabled simultaneously
// We generate x86 or arm64 assembly // We generate x86 or arm64 assembly
#if defined(_WIN32) ? defined(_M_AMD64) : (defined(__x86_64__) || defined(__aarch64__)) #if defined(_WIN32) ? defined(_M_AMD64) : (defined(__x86_64__) || defined(__aarch64__))