diff options
| -rw-r--r-- | bootstraptest/test_yjit.rb | 16 | ||||
| -rw-r--r-- | yjit/src/codegen.rs | 20 | ||||
| -rw-r--r-- | yjit/src/stats.rs | 2 |
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, |
