summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2023-07-04 10:45:29 -0400
committerGitHub <noreply@github.com>2023-07-04 10:45:29 -0400
commit296782ab60e63fe825461a199369c5dd8505c2b7 (patch)
tree9f3375ce02af963bf860ab8718f42c8113ec5e08 /lib
parent218f913aa6cd3bcbf715f229f400effee0f79ea6 (diff)
YJIT: Fix autosplat miscomp for blocks with optionals (#8006)
* YJIT: Fix autosplat miscomp for blocks with optionals When passing an array as the sole argument to `yield`, and the yieldee takes more than 1 optional parameter, the array is expanded similar to `*array` splat calls. This is called "autosplat" in `setup_parameters_complex()`. Previously, YJIT did not detect this autosplat condition. It passed the array without expanding it, deviating from interpreter behavior. Detect this conditon and refuse to compile it. Fixes: Shopify/yjit#313 * RJIT: Fix autosplat miscomp for blocks with optionals This is mirrors the same issue as YJIT. See previous commit.
Notes
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb10
1 files changed, 9 insertions, 1 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
index d9a2ab52ae..1f0376dd04 100644
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ b/lib/ruby_vm/rjit/insn_compiler.rb
@@ -4553,7 +4553,8 @@ module RubyVM::RJIT
# Check if we need the arg0 splat handling of vm_callee_setup_block_arg
arg_setup_block = (calling.block_handler == :captured) # arg_setup_type: arg_setup_block (invokeblock)
block_arg0_splat = arg_setup_block && argc == 1 &&
- iseq.body.param.flags.has_lead && !iseq.body.param.flags.ambiguous_param0
+ (iseq.body.param.flags.has_lead || opt_num > 1) &&
+ !iseq.body.param.flags.ambiguous_param0
if block_arg0_splat
# If block_arg0_splat, we still need side exits after splat, but
# doing push_splat_args here disallows it. So bail out.
@@ -4567,6 +4568,13 @@ module RubyVM::RJIT
asm.incr_counter(:invokeblock_iseq_arg0_has_kw)
return CantCompile
end
+ # The block_arg0_splat implementation cannot deal with optional parameters.
+ # This is a setup_parameters_complex() situation and interacts with the
+ # starting position of the callee.
+ if opt_num > 1
+ asm.incr_counter(:invokeblock_iseq_arg0_optional)
+ return CantCompile
+ end
end
if flags & C::VM_CALL_ARGS_SPLAT != 0 && !iseq_has_rest
array = jit.peek_at_stack(block_arg ? 1 : 0)