diff options
author | Max Bernstein <[email protected]> | 2025-06-05 11:43:56 -0400 |
---|---|---|
committer | Alan Wu <[email protected]> | 2025-06-06 16:17:54 +0900 |
commit | 6a46ca31a7d4999e9788896445fbb53d049882ab (patch) | |
tree | e365720c4d327358674a8fe37f79303aeeaca0ce | |
parent | 2eb0a1a7498db7605a381a6c774b043a74779f16 (diff) |
ZJIT: Add codegen for uncached getinstancevariable
I didn't know `rb_ivar_get` existed until @Xrxr pointed me to it.
Thanks, Alan!
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/13527
-rw-r--r-- | test/ruby/test_zjit.rb | 14 | ||||
-rw-r--r-- | zjit/src/codegen.rs | 10 |
2 files changed, 24 insertions, 0 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index d6fc4ba2f7..d4f53dcb5b 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -545,6 +545,20 @@ class TestZJIT < Test::Unit::TestCase } end + def test_getinstancevariable + assert_compiles 'nil', %q{ + def test() = @foo + + test() + } + assert_compiles '3', %q{ + @foo = 3 + def test() = @foo + + test() + } + end + # tool/ruby_vm/views/*.erb relies on the zjit instructions a) being contiguous and # b) being reliably ordered after all the other instructions. def test_instruction_order diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index dd9d41183d..ec3fdaefcf 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -274,6 +274,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::GuardBitEquals { val, expected, state } => gen_guard_bit_equals(jit, asm, opnd!(val), *expected, &function.frame_state(*state))?, Insn::PatchPoint(_) => return Some(()), // For now, rb_zjit_bop_redefined() panics. TODO: leave a patch point and fix rb_zjit_bop_redefined() Insn::CCall { cfun, args, name: _, return_type: _, elidable: _ } => gen_ccall(jit, asm, *cfun, args)?, + Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id), _ => { debug!("ZJIT: gen_function: unexpected insn {:?}", insn); return None; @@ -297,6 +298,15 @@ fn gen_ccall(jit: &mut JITState, asm: &mut Assembler, cfun: *const u8, args: &[I Some(asm.ccall(cfun, lir_args)) } +/// Emit an uncached instance variable lookup +fn gen_getivar(asm: &mut Assembler, recv: Opnd, id: ID) -> Opnd { + asm_comment!(asm, "call rb_ivar_get"); + asm.ccall( + rb_ivar_get as *const u8, + vec![recv, Opnd::UImm(id.0)], + ) +} + /// Compile an interpreter entry block to be inserted into an ISEQ fn gen_entry_prologue(asm: &mut Assembler, iseq: IseqPtr) { asm_comment!(asm, "ZJIT entry point: {}", iseq_get_location(iseq, 0)); |