YJIT: Reject keywords hash in -1 arity cfunc splat support
`test_keyword.rb` caught this issue. Just need to run with `threshold=1`
This commit is contained in:
parent
4b92b60f0b
commit
558b58d330
@ -4658,3 +4658,19 @@ assert_equal '[[1, 2, 3], [0, 2, 3], [1, 2, 3], [2, 2, 3], [], [], [{}]]', %q{
|
|||||||
|
|
||||||
test_cfunc_vargs_splat(Foo.new, Array, Hash.ruby2_keywords_hash({}))
|
test_cfunc_vargs_splat(Foo.new, Array, Hash.ruby2_keywords_hash({}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Class#new (arity=-1), splat, and ruby2_keywords
|
||||||
|
assert_equal '[0, {1=>1}]', %q{
|
||||||
|
class KwInit
|
||||||
|
attr_reader :init_args
|
||||||
|
def initialize(x = 0, **kw)
|
||||||
|
@init_args = [x, kw]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test(klass, args)
|
||||||
|
klass.new(*args).init_args
|
||||||
|
end
|
||||||
|
|
||||||
|
test(KwInit, [Hash.ruby2_keywords_hash({1 => 1})])
|
||||||
|
}
|
||||||
|
22
yjit.c
22
yjit.c
@ -903,13 +903,22 @@ rb_yjit_splat_varg_checks(VALUE *sp, VALUE splat_array, rb_control_frame_t *cfp)
|
|||||||
// Would we overflow if we put the contents of the array onto the stack?
|
// Would we overflow if we put the contents of the array onto the stack?
|
||||||
if (sp + len > (VALUE *)(cfp - 2)) return Qfalse;
|
if (sp + len > (VALUE *)(cfp - 2)) return Qfalse;
|
||||||
|
|
||||||
|
// Reject keywords hash since that requires duping it sometimes
|
||||||
|
if (len > 0) {
|
||||||
|
VALUE last_hash = RARRAY_AREF(splat_array, len - 1);
|
||||||
|
if (RB_TYPE_P(last_hash, T_HASH) &&
|
||||||
|
FL_TEST_RAW(last_hash, RHASH_PASS_AS_KEYWORDS)) {
|
||||||
|
return Qfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push array elements to the stack for a C method that has a variable number
|
// Push array elements to the stack for a C method that has a variable number
|
||||||
// of parameters. Returns the number of arguments the splat array contributes.
|
// of parameters. Returns the number of arguments the splat array contributes.
|
||||||
int
|
int
|
||||||
rb_yjit_splat_varg_cfunc(VALUE *stack_splat_array, bool sole_splat)
|
rb_yjit_splat_varg_cfunc(VALUE *stack_splat_array)
|
||||||
{
|
{
|
||||||
VALUE splat_array = *stack_splat_array;
|
VALUE splat_array = *stack_splat_array;
|
||||||
int len;
|
int len;
|
||||||
@ -918,17 +927,6 @@ rb_yjit_splat_varg_cfunc(VALUE *stack_splat_array, bool sole_splat)
|
|||||||
RUBY_ASSERT(RB_TYPE_P(splat_array, T_ARRAY));
|
RUBY_ASSERT(RB_TYPE_P(splat_array, T_ARRAY));
|
||||||
len = (int)RARRAY_LEN(splat_array);
|
len = (int)RARRAY_LEN(splat_array);
|
||||||
|
|
||||||
// If this is a splat call without any keyword arguments, exclude the
|
|
||||||
// ruby2_keywords hash if it's empty
|
|
||||||
if (sole_splat && len > 0) {
|
|
||||||
VALUE last_hash = RARRAY_AREF(splat_array, len - 1);
|
|
||||||
if (RB_TYPE_P(last_hash, T_HASH) &&
|
|
||||||
FL_TEST_RAW(last_hash, RHASH_PASS_AS_KEYWORDS) &&
|
|
||||||
RHASH_EMPTY_P(last_hash)) {
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the contents of the array onto the stack
|
// Push the contents of the array onto the stack
|
||||||
MEMCPY(stack_splat_array, RARRAY_CONST_PTR(splat_array), VALUE, len);
|
MEMCPY(stack_splat_array, RARRAY_CONST_PTR(splat_array), VALUE, len);
|
||||||
|
|
||||||
|
@ -6324,9 +6324,8 @@ fn gen_send_cfunc(
|
|||||||
// Push a dynamic number of items from the splat array to the stack when calling a vargs method
|
// Push a dynamic number of items from the splat array to the stack when calling a vargs method
|
||||||
let dynamic_splat_size = if variable_splat {
|
let dynamic_splat_size = if variable_splat {
|
||||||
asm_comment!(asm, "variable length splat");
|
asm_comment!(asm, "variable length splat");
|
||||||
let just_splat = usize::from(!kw_splat && kw_arg.is_null()).into();
|
|
||||||
let stack_splat_array = asm.lea(asm.stack_opnd(0));
|
let stack_splat_array = asm.lea(asm.stack_opnd(0));
|
||||||
Some(asm.ccall(rb_yjit_splat_varg_cfunc as _, vec![stack_splat_array, just_splat]))
|
Some(asm.ccall(rb_yjit_splat_varg_cfunc as _, vec![stack_splat_array]))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -1199,10 +1199,7 @@ extern "C" {
|
|||||||
splat_array: VALUE,
|
splat_array: VALUE,
|
||||||
cfp: *mut rb_control_frame_t,
|
cfp: *mut rb_control_frame_t,
|
||||||
) -> VALUE;
|
) -> VALUE;
|
||||||
pub fn rb_yjit_splat_varg_cfunc(
|
pub fn rb_yjit_splat_varg_cfunc(stack_splat_array: *mut VALUE) -> ::std::os::raw::c_int;
|
||||||
stack_splat_array: *mut VALUE,
|
|
||||||
sole_splat: bool,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32);
|
pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32);
|
||||||
pub fn rb_yjit_iseq_inspect(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_char;
|
pub fn rb_yjit_iseq_inspect(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_char;
|
||||||
pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE;
|
pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user