diff options
author | Takashi Kokubun <[email protected]> | 2025-07-14 12:22:13 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2025-07-14 12:22:13 -0700 |
commit | e288a86692694351278d0c3973881017b5b2e9c6 (patch) | |
tree | 2e23f90f5119d0c2740494a517faf15a7175afc0 | |
parent | b2a7b7699261d2a4ef8a9d5d38d3fb9dc99c8253 (diff) |
Co-authored-by: Alan Wu <[email protected]>
Co-authored-by: Stan Lo <[email protected]>
-rw-r--r-- | test/ruby/test_zjit.rb | 14 | ||||
-rw-r--r-- | zjit/src/codegen.rs | 8 |
2 files changed, 21 insertions, 1 deletions
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb index a54d965872..f71509bc7c 100644 --- a/test/ruby/test_zjit.rb +++ b/test/ruby/test_zjit.rb @@ -905,6 +905,20 @@ class TestZJIT < Test::Unit::TestCase }, call_threshold: 2, insns: [:defined] end + def test_invokeblock_without_block_after_jit_call + assert_compiles '"no block given (yield)"', %q{ + def test(*arr, &b) + arr.class + yield + end + begin + test + rescue => e + e.message + end + } + end + def test_putspecialobject_vm_core_and_cbase assert_compiles '10', %q{ def test diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index cea2da54ef..79460ccdfb 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -757,7 +757,8 @@ fn gen_send_without_block_direct( asm_comment!(asm, "switch to new SP register"); let local_size = unsafe { get_iseq_body_local_table_size(iseq) } as usize; - let new_sp = asm.add(SP, ((state.stack().len() + local_size - args.len() + VM_ENV_DATA_SIZE as usize) * SIZEOF_VALUE).into()); + let sp_offset = (state.stack().len() + local_size - args.len() + VM_ENV_DATA_SIZE as usize) * SIZEOF_VALUE; + let new_sp = asm.add(SP, sp_offset.into()); asm.mov(SP, new_sp); asm_comment!(asm, "switch to new CFP"); @@ -780,9 +781,14 @@ fn gen_send_without_block_direct( // If a callee side-exits, i.e. returns Qundef, propagate the return value to the caller. // The caller will side-exit the callee into the interpreter. // TODO: Let side exit code pop all JIT frames to optimize away this cmp + je. + asm_comment!(asm, "side-exit if callee side-exits"); asm.cmp(ret, Qundef.into()); asm.je(ZJITState::get_exit_trampoline().into()); + asm_comment!(asm, "restore SP register for the caller"); + let new_sp = asm.sub(SP, sp_offset.into()); + asm.mov(SP, new_sp); + Some(ret) } |