summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_yjit.rb16
-rw-r--r--yjit/src/codegen.rs20
-rw-r--r--yjit/src/stats.rs2
3 files changed, 33 insertions, 5 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 6fc0d48c87..ddd1e321a0 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -4678,3 +4678,19 @@ assert_equal '[0, {1=>1}]', %q{
test(KwInit, [Hash.ruby2_keywords_hash({1 => 1})])
}
+
+# arity=-2 cfuncs
+assert_equal '["", "1/2", [0, [:ok, 1]]]', %q{
+ def test_cases(file, chain)
+ new_chain = chain.allocate # to call initialize directly
+ new_chain.send(:initialize, [0], ok: 1)
+
+ [
+ file.join,
+ file.join("1", "2"),
+ new_chain.to_a,
+ ]
+ end
+
+ test_cases(File, Enumerator::Chain)
+}
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 292de96f70..745433ab00 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -6174,9 +6174,9 @@ fn gen_send_cfunc(
let variable_splat = flags & VM_CALL_ARGS_SPLAT != 0 && cfunc_argc == -1;
let block_arg = flags & VM_CALL_ARGS_BLOCKARG != 0;
- // If the function expects a Ruby array of arguments
- if cfunc_argc < 0 && cfunc_argc != -1 {
- gen_counter_incr(asm, Counter::send_cfunc_ruby_array_varg);
+ // If it's a splat and the method expects a Ruby array of arguments
+ if cfunc_argc == -2 && flags & VM_CALL_ARGS_SPLAT != 0 {
+ gen_counter_incr(asm, Counter::send_cfunc_splat_neg2);
return None;
}
@@ -6461,7 +6461,19 @@ fn gen_send_cfunc(
asm.stack_opnd(argc),
]
}
- else {
+ // Variadic method taking a Ruby array
+ else if cfunc_argc == -2 {
+ // Slurp up all the arguments into an array
+ let stack_args = asm.lea(asm.ctx.sp_opnd(-argc * SIZEOF_VALUE_I32));
+ let args_array = asm.ccall(
+ rb_ec_ary_new_from_values as _,
+ vec![EC, passed_argc.into(), stack_args]
+ );
+
+ // Example signature:
+ // VALUE neg2_method(VALUE self, VALUE argv)
+ vec![asm.stack_opnd(argc), args_array]
+ } else {
panic!("unexpected cfunc_args: {}", cfunc_argc)
};
diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs
index 5fa2bfedfb..c1315aad90 100644
--- a/yjit/src/stats.rs
+++ b/yjit/src/stats.rs
@@ -354,7 +354,7 @@ make_counters! {
send_refined_method,
send_private_not_fcall,
send_cfunc_kw_splat_non_nil,
- send_cfunc_ruby_array_varg,
+ send_cfunc_splat_neg2,
send_cfunc_argc_mismatch,
send_cfunc_block_arg,
send_cfunc_toomany_args,