Ruby 4.1.0dev (2026-03-30 revision 3379c7efbdc34b7936f322a6bc2de4834c8c65fc)
zjit.h (3379c7efbdc34b7936f322a6bc2de4834c8c65fc)
1#ifndef ZJIT_H
2#define ZJIT_H 1
3//
4// This file contains definitions ZJIT exposes to the CRuby codebase
5//
6
7// ZJIT_STATS controls whether to support runtime counters in the interpreter
8#ifndef ZJIT_STATS
9# define ZJIT_STATS (USE_ZJIT && RUBY_DEBUG)
10#endif
11
12// JITFrame is defined here as the single source of truth and imported into
13// Rust via bindgen. C code reads fields directly; Rust uses an impl block.
14typedef struct zjit_jit_frame {
15 // Program counter for this frame, used for backtraces and GC.
16 // NULL for C frames (they don't have a Ruby PC).
17 const VALUE *pc;
18 // The ISEQ this frame belongs to. Marked via rb_execution_context_mark.
19 // NULL for C frames.
20 const rb_iseq_t *iseq;
21 // Whether to materialize block_code when this frame is materialized.
22 // True when the ISEQ doesn't contain send/invokesuper/invokeblock
23 // (which write block_code themselves), so we must restore it.
24 // Always false for C frames.
25 bool materialize_block_code;
27
28#if USE_ZJIT
29extern void *rb_zjit_entry;
30extern uint64_t rb_zjit_call_threshold;
31extern uint64_t rb_zjit_profile_threshold;
32void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception);
33void rb_zjit_profile_insn(uint32_t insn, rb_execution_context_t *ec);
34void rb_zjit_profile_enable(const rb_iseq_t *iseq);
35void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
36void rb_zjit_cme_invalidate(const rb_callable_method_entry_t *cme);
37void rb_zjit_cme_free(const rb_callable_method_entry_t *cme);
38void rb_zjit_klass_free(VALUE klass);
39void rb_zjit_invalidate_no_ep_escape(const rb_iseq_t *iseq);
40void rb_zjit_constant_state_changed(ID id);
41void rb_zjit_iseq_mark(void *payload);
42void rb_zjit_iseq_update_references(void *payload);
43void rb_zjit_iseq_free(const rb_iseq_t *iseq);
44void rb_zjit_before_ractor_spawn(void);
45void rb_zjit_tracing_invalidate_all(void);
46void rb_zjit_invalidate_no_singleton_class(VALUE klass);
47void rb_zjit_invalidate_root_box(void);
48void rb_zjit_jit_frame_update_references(zjit_jit_frame_t *jit_frame);
49#else
50#define rb_zjit_entry 0
51static inline void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception) {}
52static inline void rb_zjit_profile_insn(uint32_t insn, rb_execution_context_t *ec) {}
53static inline void rb_zjit_profile_enable(const rb_iseq_t *iseq) {}
54static inline void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
55static inline void rb_zjit_cme_invalidate(const rb_callable_method_entry_t *cme) {}
56static inline void rb_zjit_invalidate_no_ep_escape(const rb_iseq_t *iseq) {}
57static inline void rb_zjit_constant_state_changed(ID id) {}
58static inline void rb_zjit_before_ractor_spawn(void) {}
59static inline void rb_zjit_tracing_invalidate_all(void) {}
60static inline void rb_zjit_invalidate_no_singleton_class(VALUE klass) {}
61static inline void rb_zjit_invalidate_root_box(void) {}
62static inline void rb_zjit_jit_frame_update_references(zjit_jit_frame_t *jit_frame) {}
63#endif // #if USE_ZJIT
64
65#define rb_zjit_enabled_p (rb_zjit_entry != 0)
66
67enum zjit_poison_values {
68 // Poison value used on frame push when runtime checks are enabled
69 ZJIT_JIT_RETURN_POISON = 2,
70};
71
72// Return the JITFrame pointer from cfp->jit_return, or NULL if not present.
73// YJIT also uses jit_return (as a return address), so this must only return
74// non-NULL when ZJIT is enabled and has set jit_return to a JITFrame pointer.
75static inline void *
76CFP_JIT_RETURN(const rb_control_frame_t *cfp)
77{
78 if (!rb_zjit_enabled_p) return NULL;
79#if USE_ZJIT
80 RUBY_ASSERT_ALWAYS(cfp->jit_return != (void *)ZJIT_JIT_RETURN_POISON);
81#endif
82 return cfp->jit_return;
83}
84
85static inline const VALUE*
86CFP_PC(const rb_control_frame_t *cfp)
87{
88 if (CFP_JIT_RETURN(cfp)) {
89 return ((const zjit_jit_frame_t *)cfp->jit_return)->pc;
90 }
91 return cfp->pc;
92}
93
94static inline const rb_iseq_t*
95CFP_ISEQ(const rb_control_frame_t *cfp)
96{
97 if (CFP_JIT_RETURN(cfp)) {
98 return ((const zjit_jit_frame_t *)cfp->jit_return)->iseq;
99 }
100 return cfp->_iseq;
101}
102
103#endif // #ifndef ZJIT_H
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
Definition assert.h:199
Definition method.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40