Hook ZJIT compilation

This commit is contained in:
Takashi Kokubun 2025-02-06 11:35:55 -05:00
parent 26d1aa4029
commit 0bb709718b
Notes: git 2025-04-18 13:49:50 +00:00
4 changed files with 326 additions and 4 deletions

247
common.mk
View File

@ -20927,5 +20927,252 @@ yjit.$(OBJEXT): {$(VPATH)}vm_sync.h
yjit.$(OBJEXT): {$(VPATH)}yjit.c
yjit.$(OBJEXT): {$(VPATH)}yjit.h
yjit.$(OBJEXT): {$(VPATH)}yjit.rbinc
zjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
zjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
zjit.$(OBJEXT): $(CCAN_DIR)/list/list.h
zjit.$(OBJEXT): $(CCAN_DIR)/str/str.h
zjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
zjit.$(OBJEXT): $(top_srcdir)/internal/array.h
zjit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
zjit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
zjit.$(OBJEXT): $(top_srcdir)/internal/bits.h
zjit.$(OBJEXT): $(top_srcdir)/internal/class.h
zjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
zjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
zjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
zjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
zjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
zjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
zjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
zjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
zjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
zjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
zjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
zjit.$(OBJEXT): $(top_srcdir)/internal/string.h
zjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
zjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
zjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
zjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
zjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
zjit.$(OBJEXT): $(top_srcdir)/prism/node.h
zjit.$(OBJEXT): $(top_srcdir)/prism/options.h
zjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
zjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
zjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
zjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
zjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
zjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
zjit.$(OBJEXT): {$(VPATH)}assert.h
zjit.$(OBJEXT): {$(VPATH)}atomic.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
zjit.$(OBJEXT): {$(VPATH)}builtin.h
zjit.$(OBJEXT): {$(VPATH)}config.h
zjit.$(OBJEXT): {$(VPATH)}constant.h
zjit.$(OBJEXT): {$(VPATH)}debug.h
zjit.$(OBJEXT): {$(VPATH)}debug_counter.h
zjit.$(OBJEXT): {$(VPATH)}defines.h
zjit.$(OBJEXT): {$(VPATH)}encoding.h
zjit.$(OBJEXT): {$(VPATH)}id.h
zjit.$(OBJEXT): {$(VPATH)}id_table.h
zjit.$(OBJEXT): {$(VPATH)}insns.def
zjit.$(OBJEXT): {$(VPATH)}insns.inc
zjit.$(OBJEXT): {$(VPATH)}insns_info.inc
zjit.$(OBJEXT): {$(VPATH)}intern.h
zjit.$(OBJEXT): {$(VPATH)}internal.h
zjit.$(OBJEXT): {$(VPATH)}internal/abi.h
zjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
zjit.$(OBJEXT): {$(VPATH)}internal/assume.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
zjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
zjit.$(OBJEXT): {$(VPATH)}internal/cast.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
zjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
zjit.$(OBJEXT): {$(VPATH)}internal/config.h
zjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
zjit.$(OBJEXT): {$(VPATH)}internal/core.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
zjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
zjit.$(OBJEXT): {$(VPATH)}internal/ctype.h
zjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
zjit.$(OBJEXT): {$(VPATH)}internal/dosish.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
zjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
zjit.$(OBJEXT): {$(VPATH)}internal/error.h
zjit.$(OBJEXT): {$(VPATH)}internal/eval.h
zjit.$(OBJEXT): {$(VPATH)}internal/event.h
zjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
zjit.$(OBJEXT): {$(VPATH)}internal/gc.h
zjit.$(OBJEXT): {$(VPATH)}internal/glob.h
zjit.$(OBJEXT): {$(VPATH)}internal/globals.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
zjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
zjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
zjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
zjit.$(OBJEXT): {$(VPATH)}internal/iterator.h
zjit.$(OBJEXT): {$(VPATH)}internal/memory.h
zjit.$(OBJEXT): {$(VPATH)}internal/method.h
zjit.$(OBJEXT): {$(VPATH)}internal/module.h
zjit.$(OBJEXT): {$(VPATH)}internal/newobj.h
zjit.$(OBJEXT): {$(VPATH)}internal/numeric.h
zjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
zjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
zjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
zjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
zjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
zjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
zjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
zjit.$(OBJEXT): {$(VPATH)}internal/value.h
zjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
zjit.$(OBJEXT): {$(VPATH)}internal/variable.h
zjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h
zjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
zjit.$(OBJEXT): {$(VPATH)}iseq.h
zjit.$(OBJEXT): {$(VPATH)}method.h
zjit.$(OBJEXT): {$(VPATH)}missing.h
zjit.$(OBJEXT): {$(VPATH)}node.h
zjit.$(OBJEXT): {$(VPATH)}onigmo.h
zjit.$(OBJEXT): {$(VPATH)}oniguruma.h
zjit.$(OBJEXT): {$(VPATH)}prism/ast.h
zjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
zjit.$(OBJEXT): {$(VPATH)}prism/version.h
zjit.$(OBJEXT): {$(VPATH)}prism_compile.h
zjit.$(OBJEXT): {$(VPATH)}probes.dmyh
zjit.$(OBJEXT): {$(VPATH)}probes.h
zjit.$(OBJEXT): {$(VPATH)}probes_helper.h
zjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
zjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
zjit.$(OBJEXT): {$(VPATH)}rubyparser.h
zjit.$(OBJEXT): {$(VPATH)}shape.h
zjit.$(OBJEXT): {$(VPATH)}st.h
zjit.$(OBJEXT): {$(VPATH)}subst.h
zjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
zjit.$(OBJEXT): {$(VPATH)}thread_native.h
zjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h
zjit.$(OBJEXT): {$(VPATH)}vm_core.h
zjit.$(OBJEXT): {$(VPATH)}vm_debug.h
zjit.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
zjit.$(OBJEXT): {$(VPATH)}vm_opts.h
zjit.$(OBJEXT): {$(VPATH)}vm_sync.h
zjit.$(OBJEXT): {$(VPATH)}zjit.c
# AUTOGENERATED DEPENDENCIES END

21
vm.c
View File

@ -419,7 +419,7 @@ rb_yjit_threshold_hit(const rb_iseq_t *iseq, uint64_t entry_calls)
#define rb_yjit_threshold_hit(iseq, entry_calls) false
#endif
#if USE_YJIT
#if USE_YJIT || USE_ZJIT
// Generate JIT code that supports the following kinds of ISEQ entries:
// * The first ISEQ on vm_exec (e.g. <main>, or Ruby methods/blocks
// called by a C method). The current frame has VM_FRAME_FLAG_FINISH.
@ -433,12 +433,27 @@ jit_compile(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 = rb_yjit_enabled_p;
extern bool rb_zjit_enabled_p;
bool zjit_enabled = rb_zjit_enabled_p;
if (!(yjit_enabled || zjit_enabled || rb_rjit_call_p)) {
return NULL;
}
// Increment the ISEQ's call counter and trigger JIT compilation if not compiled
if (body->jit_entry == NULL && rb_yjit_enabled_p) {
body->jit_entry_calls++;
if (rb_yjit_threshold_hit(iseq, body->jit_entry_calls)) {
rb_yjit_compile_iseq(iseq, ec, false);
if (zjit_enabled) {
extern void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception);
rb_zjit_compile_iseq(iseq, ec, false);
}
else if (yjit_enabled) {
if (rb_yjit_threshold_hit(iseq, body->jit_entry_calls)) {
rb_yjit_compile_iseq(iseq, ec, false);
}
}
else if (body->jit_entry_calls == rb_rjit_call_threshold()) {
rb_rjit_compile(iseq);
}
}
return body->jit_entry;

48
zjit.c
View File

@ -0,0 +1,48 @@
#include "internal.h"
#include "internal/sanitizers.h"
#include "internal/string.h"
#include "internal/hash.h"
#include "internal/variable.h"
#include "internal/compile.h"
#include "internal/class.h"
#include "internal/fixnum.h"
#include "internal/numeric.h"
#include "internal/gc.h"
#include "internal/vm.h"
#include "vm_core.h"
#include "vm_callinfo.h"
#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
#include "vm_sync.h"
#include "yjit.h"
#include "vm_insnhelper.h"
#include "probes.h"
#include "probes_helper.h"
#include "iseq.h"
#include "ruby/debug.h"
#include "internal/cont.h"
// For mmapp(), sysconf()
#ifndef _WIN32
#include <unistd.h>
#include <sys/mman.h>
#endif
#include <errno.h>
void
rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception)
{
RB_VM_LOCK_ENTER();
rb_vm_barrier();
// Compile a block version starting at the current instruction
uint8_t *rb_zjit_iseq_gen_entry_point(const rb_iseq_t *iseq, rb_execution_context_t *ec); // defined in Rust
uintptr_t code_ptr = (uintptr_t)rb_zjit_iseq_gen_entry_point(iseq, ec);
// TODO: support jit_exception
iseq->body->jit_entry = (rb_jit_func_t)code_ptr;
RB_VM_LOCK_LEAVE();
}

View File

@ -3,10 +3,16 @@
mod cruby;
mod stats;
mod ir;
use crate::cruby::*;
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static mut rb_zjit_enabled_p: bool = false;
#[no_mangle]
pub extern "C" fn rb_zjit_init() {
println!("zjit init");
assert!(unsafe{ !rb_zjit_enabled_p });
unsafe { rb_zjit_enabled_p = true; }
}
#[no_mangle]
@ -14,3 +20,9 @@ pub extern "C" fn rb_zjit_parse_option() -> bool {
println!("parsing zjit options");
false
}
#[no_mangle]
pub extern "C" fn rb_zjit_iseq_gen_entry_point(_iseq: IseqPtr, _ec: EcPtr) -> *const u8 {
println!("compiling zjit");
std::ptr::null()
}