JIT: Move EC offsets to jit_bindgen_constants

Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
This commit is contained in:
John Hawthorn 2025-12-18 12:31:34 -08:00
parent b1c3060bed
commit 73e930f9f9
Notes: git 2025-12-18 21:44:19 +00:00
9 changed files with 36 additions and 32 deletions

9
jit.c
View File

@ -23,7 +23,14 @@ enum jit_bindgen_constants {
ROBJECT_OFFSET_AS_ARY = offsetof(struct RObject, as.ary),
// Field offsets for the RString struct
RUBY_OFFSET_RSTRING_LEN = offsetof(struct RString, len)
RUBY_OFFSET_RSTRING_LEN = offsetof(struct RString, len),
// Field offsets for rb_execution_context_t
RUBY_OFFSET_EC_CFP = offsetof(rb_execution_context_t, cfp),
RUBY_OFFSET_EC_INTERRUPT_FLAG = offsetof(rb_execution_context_t, interrupt_flag),
RUBY_OFFSET_EC_INTERRUPT_MASK = offsetof(rb_execution_context_t, interrupt_mask),
RUBY_OFFSET_EC_THREAD_PTR = offsetof(rb_execution_context_t, thread_ptr),
RUBY_OFFSET_EC_RACTOR_ID = offsetof(rb_execution_context_t, ractor_id),
};
// Manually bound in rust since this is out-of-range of `int`,

View File

@ -232,9 +232,9 @@ fn test_jcc_ptr()
let (mut asm, mut cb) = setup_asm();
let side_exit = Target::CodePtr(cb.get_write_ptr().add_bytes(4));
let not_mask = asm.not(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_MASK));
let not_mask = asm.not(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_MASK as i32));
asm.test(
Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG),
Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG as i32),
not_mask,
);
asm.jnz(side_exit);

View File

@ -1208,7 +1208,7 @@ fn gen_check_ints(
// Not checking interrupt_mask since it's zero outside finalize_deferred_heap_pages,
// signal_exec, or rb_postponed_job_flush.
let interrupt_flag = asm.load(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG));
let interrupt_flag = asm.load(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG as i32));
asm.test(interrupt_flag, interrupt_flag);
asm.jnz(Target::side_exit(counter));
@ -6659,7 +6659,7 @@ fn jit_thread_s_current(
asm.stack_pop(1);
// ec->thread_ptr
let ec_thread_opnd = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_THREAD_PTR));
let ec_thread_opnd = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_THREAD_PTR as i32));
// thread->self
let thread_self = Opnd::mem(64, ec_thread_opnd, RUBY_OFFSET_THREAD_SELF);
@ -7124,7 +7124,7 @@ fn gen_send_cfunc(
asm_comment!(asm, "set ec->cfp");
let new_cfp = asm.lea(Opnd::mem(64, CFP, -(RUBY_SIZEOF_CONTROL_FRAME as i32)));
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), new_cfp);
if !kw_arg.is_null() {
// Build a hash from all kwargs passed
@ -7220,7 +7220,7 @@ fn gen_send_cfunc(
// Pop the stack frame (ec->cfp++)
// Instead of recalculating, we can reuse the previous CFP, which is stored in a callee-saved
// register
let ec_cfp_opnd = Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP);
let ec_cfp_opnd = Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32);
asm.store(ec_cfp_opnd, CFP);
// cfunc calls may corrupt types
@ -7399,7 +7399,7 @@ fn gen_send_bmethod(
if !procv.shareable_p() {
let ractor_serial = unsafe { rb_yjit_cme_ractor_serial(cme) };
asm_comment!(asm, "guard current ractor == {}", ractor_serial);
let current_ractor_serial = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_RACTOR_ID));
let current_ractor_serial = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_RACTOR_ID as i32));
asm.cmp(current_ractor_serial, ractor_serial.into());
asm.jne(Target::side_exit(Counter::send_bmethod_ractor));
}
@ -8359,7 +8359,7 @@ fn gen_send_iseq(
asm_comment!(asm, "switch to new CFP");
let new_cfp = asm.sub(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
// Directly jump to the entry point of the callee
gen_direct_jump(
@ -9937,7 +9937,7 @@ fn gen_leave(
asm_comment!(asm, "pop stack frame");
let incr_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, incr_cfp);
asm.mov(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.mov(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
// Load the return value
let retval_opnd = asm.stack_pop(1);

View File

@ -772,13 +772,6 @@ mod manual_defs {
pub const RUBY_OFFSET_CFP_JIT_RETURN: i32 = 48;
pub const RUBY_SIZEOF_CONTROL_FRAME: usize = 56;
// Constants from rb_execution_context_t vm_core.h
pub const RUBY_OFFSET_EC_CFP: i32 = 16;
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48;
pub const RUBY_OFFSET_EC_RACTOR_ID: i32 = 64;
// Constants from rb_thread_t in vm_core.h
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;

View File

@ -978,6 +978,11 @@ pub type rb_seq_param_keyword_struct =
pub const ROBJECT_OFFSET_AS_HEAP_FIELDS: jit_bindgen_constants = 16;
pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_RSTRING_LEN: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_EC_CFP: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: jit_bindgen_constants = 32;
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: jit_bindgen_constants = 36;
pub const RUBY_OFFSET_EC_THREAD_PTR: jit_bindgen_constants = 48;
pub const RUBY_OFFSET_EC_RACTOR_ID: jit_bindgen_constants = 64;
pub type jit_bindgen_constants = u32;
pub type rb_iseq_param_keyword_struct =
rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword;

View File

@ -229,9 +229,9 @@ fn test_jcc_ptr()
let (mut asm, mut cb) = setup_asm();
let side_exit = Target::CodePtr(cb.get_write_ptr().add_bytes(4));
let not_mask = asm.not(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_MASK));
let not_mask = asm.not(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_MASK as i32));
asm.test(
Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG),
Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG as i32),
not_mask,
);
asm.jnz(side_exit);

View File

@ -841,7 +841,7 @@ fn gen_ccall_with_frame(
asm_comment!(asm, "switch to new CFP");
let new_cfp = asm.sub(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
let mut cfunc_args = vec![recv];
cfunc_args.extend(args);
@ -851,7 +851,7 @@ fn gen_ccall_with_frame(
asm_comment!(asm, "pop C frame");
let new_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
asm_comment!(asm, "restore SP register for the caller");
let new_sp = asm.sub(SP, sp_offset.into());
@ -926,7 +926,7 @@ fn gen_ccall_variadic(
asm_comment!(asm, "switch to new CFP");
let new_cfp = asm.sub(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
let argv_ptr = gen_push_opnds(asm, &args);
asm.count_call_to(&name.contents_lossy());
@ -936,7 +936,7 @@ fn gen_ccall_variadic(
asm_comment!(asm, "pop C frame");
let new_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
asm_comment!(asm, "restore SP register for the caller");
let new_sp = asm.sub(SP, sp_offset.into());
@ -1051,7 +1051,7 @@ fn gen_check_interrupts(jit: &mut JITState, asm: &mut Assembler, state: &FrameSt
asm_comment!(asm, "RUBY_VM_CHECK_INTS(ec)");
// Not checking interrupt_mask since it's zero outside finalize_deferred_heap_pages,
// signal_exec, or rb_postponed_job_flush.
let interrupt_flag = asm.load(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG));
let interrupt_flag = asm.load(Opnd::mem(32, EC, RUBY_OFFSET_EC_INTERRUPT_FLAG as i32));
asm.test(interrupt_flag, interrupt_flag);
asm.jnz(side_exit(jit, state, SideExitReason::Interrupt));
}
@ -1382,7 +1382,7 @@ fn gen_send_without_block_direct(
asm_comment!(asm, "switch to new CFP");
let new_cfp = asm.sub(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, new_cfp);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.store(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
// Set up arguments
let mut c_args = vec![recv];
@ -1741,7 +1741,7 @@ fn gen_return(asm: &mut Assembler, val: lir::Opnd) {
asm_comment!(asm, "pop stack frame");
let incr_cfp = asm.add(CFP, RUBY_SIZEOF_CONTROL_FRAME.into());
asm.mov(CFP, incr_cfp);
asm.mov(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
asm.mov(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP as i32), CFP);
// Order here is important. Because we're about to tear down the frame,
// we need to load the return value, which might be part of the frame.

View File

@ -1073,12 +1073,6 @@ mod manual_defs {
pub const RUBY_OFFSET_CFP_JIT_RETURN: i32 = 48;
pub const RUBY_SIZEOF_CONTROL_FRAME: usize = 56;
// Constants from rb_execution_context_t vm_core.h
pub const RUBY_OFFSET_EC_CFP: i32 = 16;
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48;
// Constants from rb_thread_t in vm_core.h
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;

View File

@ -1828,6 +1828,11 @@ pub type zjit_struct_offsets = u32;
pub const ROBJECT_OFFSET_AS_HEAP_FIELDS: jit_bindgen_constants = 16;
pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_RSTRING_LEN: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_EC_CFP: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: jit_bindgen_constants = 32;
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: jit_bindgen_constants = 36;
pub const RUBY_OFFSET_EC_THREAD_PTR: jit_bindgen_constants = 48;
pub const RUBY_OFFSET_EC_RACTOR_ID: jit_bindgen_constants = 64;
pub type jit_bindgen_constants = u32;
pub const rb_invalid_shape_id: shape_id_t = 4294967295;
pub type rb_iseq_param_keyword_struct =