diff --git a/bignum.c b/bignum.c index fb4714307e6375..ac86951372f4d4 100644 --- a/bignum.c +++ b/bignum.c @@ -6346,7 +6346,7 @@ bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y) BDIGIT hibitsy; if (y == 0) return INT2FIX(0); - if (xn == 0) return hibitsx ? LONG2NUM(y) : 0; + if (xn == 0) return hibitsx ? LONG2NUM(y) : INT2FIX(0); hibitsy = 0 <= y ? 0 : BDIGMAX; xds = BDIGITS(x); #if SIZEOF_BDIGIT >= SIZEOF_LONG diff --git a/symbol.c b/symbol.c index c66e7f067d0a21..9c5f9a11718d47 100644 --- a/symbol.c +++ b/symbol.c @@ -881,10 +881,7 @@ rb_intern3(const char *name, long len, rb_encoding *enc) VALUE str = rb_setup_fake_str(&fake_str, name, len, enc); OBJ_FREEZE(str); - VALUE sym; - GLOBAL_SYMBOLS_LOCKING(symbols) { - sym = sym_find_or_insert_static_symbol(symbols, str); - } + VALUE sym = sym_find_or_insert_static_symbol(&ruby_global_symbols, str); return rb_sym2id(sym); } @@ -904,10 +901,7 @@ rb_intern(const char *name) ID rb_intern_str(VALUE str) { - VALUE sym; - GLOBAL_SYMBOLS_LOCKING(symbols) { - sym = sym_find_or_insert_static_symbol(symbols, str); - } + VALUE sym = sym_find_or_insert_static_symbol(&ruby_global_symbols, str); return SYM2ID(sym); } @@ -957,9 +951,7 @@ rb_gc_free_dsymbol(VALUE sym) VALUE str = RSYMBOL(sym)->fstr; if (str) { - GLOBAL_SYMBOLS_LOCKING(symbols) { - rb_concurrent_set_delete_by_identity(symbols->sym_set, sym); - } + rb_concurrent_set_delete_by_identity(ruby_global_symbols.sym_set, sym); RSYMBOL(sym)->fstr = 0; } diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index 69c440f5f08fba..0dcdb8e4cb8275 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -811,6 +811,12 @@ def a(n1,n2,n3,n4,n5,n6,n7,n8,n9) = n1+n9 def a(n1,n2,n3,n4,n5,n6,n7,n8) = n8 a(1,1,1,1,1,1,1,0) } + + # self param with spilled param + assert_compiles '"main"', %q{ + def a(n1,n2,n3,n4,n5,n6,n7,n8) = self + a(1,0,0,0,0,0,0,0).to_s + } end def test_opt_aref_with diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index fee6537c375d49..c460dddfb82ce1 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -187,6 +187,10 @@ fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function, function_pt asm.frame_teardown(); asm.cret(C_RET_OPND); + if get_option!(dump_lir) { + println!("LIR:\nJIT entry for {}:\n{:?}", iseq_name(iseq), asm); + } + let result = asm.compile(cb).map(|(start_ptr, _)| start_ptr); if let Some(start_addr) = result { if get_option!(perf) { @@ -584,16 +588,16 @@ fn gen_entry_prologue(asm: &mut Assembler, iseq: IseqPtr) { /// Assign method arguments to basic block arguments at JIT entry fn gen_entry_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block, c_stack_bytes: usize) { - let self_param = gen_param(asm, SELF_PARAM_IDX); - asm.mov(self_param, Opnd::mem(VALUE_BITS, CFP, RUBY_OFFSET_CFP_SELF)); - let num_params = entry_block.params().len() - 1; // -1 to exclude self if num_params > 0 { asm_comment!(asm, "set method params: {num_params}"); - // Allocate registers for basic block arguments - for idx in 0..num_params { - let param = gen_param(asm, idx + 1); // +1 for self + // Fill basic block parameters. + // Doing it in reverse is load-bearing. High index params have memory slots that might + // require using a register to fill. Filling them first avoids clobbering. + for idx in (0..num_params).rev() { + let param = param_opnd(idx + 1); // +1 for self + let local = gen_entry_param(asm, iseq, idx); // Funky offset adjustment to write into the native stack frame of the // HIR function we'll be calling into. This only makes sense in context @@ -611,17 +615,22 @@ fn gen_entry_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block, c_s // would be while │ │ // the HIR function ────────────► └────────────┘ // is running - let param = if let Opnd::Mem(lir::Mem { base, disp, num_bits }) = param { - Opnd::Mem(lir::Mem { num_bits, base, disp: disp - c_stack_bytes as i32 - Assembler::frame_size() }) - } else { - param - }; + match param { + Opnd::Mem(lir::Mem { base, disp, num_bits }) => { + let param_slot = Opnd::Mem(lir::Mem { num_bits, base, disp: disp - c_stack_bytes as i32 - Assembler::frame_size() }); + asm.mov(param_slot, local); + } + // Prepare for parallel move for locals in registers + reg @ Opnd::Reg(_) => { + asm.load_into(reg, local); + } + _ => unreachable!("on entry, params are either in memory or in reg. Got {param:?}") + } // Assign local variables to the basic block arguments - let local = gen_entry_param(asm, iseq, idx); - asm.mov(param, local); } } + asm.load_into(param_opnd(SELF_PARAM_IDX), Opnd::mem(VALUE_BITS, CFP, RUBY_OFFSET_CFP_SELF)); } /// Set branch params to basic block arguments