summaryrefslogtreecommitdiff
path: root/lib/ruby_vm
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-03-12 21:30:41 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2023-03-12 22:01:38 -0700
commit3938efa70f5e1f69d588c2b7552335176180cbbb (patch)
tree4905a13a519f9b9fd3655091117ba6d2a3d1afd6 /lib/ruby_vm
parenta23f64221e9b006fef74544ffbbca5d09115f807 (diff)
RJIT: Fix block param proxy on send
peek_at_stack was doubly accounting for C::VM_CALL_ARGS_BLOCKARG, which made that case always side-exit and hide this bug. When a block handler is block param proxy, you have to set LEP's specval as next specval instead of block param proxy itself.
Diffstat (limited to 'lib/ruby_vm')
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb20
1 files changed, 8 insertions, 12 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
index a9226f9e41..c23c55e5f0 100644
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ b/lib/ruby_vm/rjit/insn_compiler.rb
@@ -2994,7 +2994,7 @@ module RubyVM::RJIT
# Get a compile-time receiver and its class
recv_idx = argc + (flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0) # blockarg is not popped yet
recv_idx += send_shift
- comptime_recv = jit.peek_at_stack(recv_idx + (flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0)) # this offset is in ctx but not in SP
+ comptime_recv = jit.peek_at_stack(recv_idx)
comptime_recv_klass = C.rb_class_of(comptime_recv)
# Guard the receiver class (part of vm_search_method_fastpath)
@@ -3137,7 +3137,7 @@ module RubyVM::RJIT
# Get a compile-time receiver
recv_idx = argc + (flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0) # blockarg is not popped yet
recv_idx += send_shift
- comptime_recv = jit.peek_at_stack(recv_idx + (flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0)) # this offset is in ctx but not in SP
+ comptime_recv = jit.peek_at_stack(recv_idx)
recv_opnd = ctx.stack_opnd(recv_idx)
jit_call_method_each_type(jit, ctx, asm, argc, flags, cme, comptime_recv, recv_opnd, block_handler, known_recv_class, send_shift:)
@@ -3690,22 +3690,18 @@ module RubyVM::RJIT
# ep[-2]: cref_or_me
asm.mov(:rax, cme.to_i)
asm.mov([SP, C.VALUE.size * (ep_offset - 2)], :rax)
- # ep[-1]: block handler or prev env ptr
+ # ep[-1]: block handler or prev env ptr (specval)
if prev_ep
asm.mov(:rax, prev_ep.to_i | 1) # tagged prev ep
asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax)
elsif block_handler == C::VM_BLOCK_HANDLER_NONE
asm.mov([SP, C.VALUE.size * (ep_offset - 1)], C::VM_BLOCK_HANDLER_NONE)
elsif block_handler == C.rb_block_param_proxy
- # vm_caller_setup_arg_block:
- # VALUE handler = VM_CF_BLOCK_HANDLER(reg_cfp);
- # reg_cfp->block_code = (const void *) handler;
- jit_get_lep(jit, asm, reg: :rax)
- asm.mov(:rax, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # handler
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:block_code)], :rax)
-
- asm.mov(:rax, C.rb_block_param_proxy)
- asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax)
+ # vm_caller_setup_arg_block: block_code == rb_block_param_proxy
+ jit_get_lep(jit, asm, reg: :rax) # VM_CF_BLOCK_HANDLER: VM_CF_LEP
+ asm.mov(:rax, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # VM_CF_BLOCK_HANDLER: VM_ENV_BLOCK_HANDLER
+ asm.mov([CFP, C.rb_control_frame_t.offsetof(:block_code)], :rax) # reg_cfp->block_code = handler
+ asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax) # return handler;
else # assume blockiseq
asm.mov(:rax, block_handler)
asm.mov([CFP, C.rb_control_frame_t.offsetof(:block_code)], :rax)