Skip to content

Commit

Permalink
YJIT: Support arity=-2 cfuncs
Browse files Browse the repository at this point in the history
This type of cfuncs shows up as consume a lot of cycles in profiles of
the lobsters benchmark, even though in the stats they don't happen that
frequently. Might be a bug in the profiling, but these calls are not
too bad to support, so might as well do it.
  • Loading branch information
XrXr committed Mar 15, 2024
1 parent 185112f commit 7ef0e6c
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
16 changes: 16 additions & 0 deletions bootstraptest/test_yjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4678,3 +4678,19 @@ def test(klass, args)
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)
}
20 changes: 16 additions & 4 deletions yjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
};

Expand Down
2 changes: 1 addition & 1 deletion yjit/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 7ef0e6c

Please sign in to comment.