mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
YJIT: Add support for ruby array cfuncs (argc=-2)
This adds support for cfuncs which take variable arguments using a Ruby array. This is specified with the method entry's argc == -2.
This commit is contained in:
parent
b5c039125f
commit
18b97eee5a
Notes:
git
2022-01-09 04:41:20 +09:00
3 changed files with 42 additions and 7 deletions
|
@ -2766,3 +2766,23 @@ assert_equal 'ok', %q{
|
|||
foo(s) rescue :ok
|
||||
foo(s) rescue :ok
|
||||
}
|
||||
|
||||
# File.join is a cfunc accepting variable arguments as a Ruby array (argc = -2)
|
||||
assert_equal 'foo/bar', %q{
|
||||
def foo
|
||||
File.join("foo", "bar")
|
||||
end
|
||||
|
||||
foo
|
||||
foo
|
||||
}
|
||||
|
||||
# File.join is a cfunc accepting variable arguments as a Ruby array (argc = -2)
|
||||
assert_equal '', %q{
|
||||
def foo
|
||||
File.join()
|
||||
end
|
||||
|
||||
foo
|
||||
foo
|
||||
}
|
||||
|
|
1
yjit.c
1
yjit.c
|
@ -69,7 +69,6 @@ YJIT_DECLARE_COUNTERS(
|
|||
send_missing_method,
|
||||
send_bmethod,
|
||||
send_refined_method,
|
||||
send_cfunc_ruby_array_varg,
|
||||
send_cfunc_argc_mismatch,
|
||||
send_cfunc_toomany_args,
|
||||
send_cfunc_tracing,
|
||||
|
|
|
@ -3244,12 +3244,6 @@ gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const
|
|||
{
|
||||
const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(cme->def, body.cfunc);
|
||||
|
||||
// If the function expects a Ruby array of arguments
|
||||
if (cfunc->argc < 0 && cfunc->argc != -1) {
|
||||
GEN_COUNTER_INC(cb, send_cfunc_ruby_array_varg);
|
||||
return YJIT_CANT_COMPILE;
|
||||
}
|
||||
|
||||
// If the argument count doesn't match
|
||||
if (cfunc->argc >= 0 && cfunc->argc != argc) {
|
||||
GEN_COUNTER_INC(cb, send_cfunc_argc_mismatch);
|
||||
|
@ -3402,6 +3396,28 @@ gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const
|
|||
lea(cb, C_ARG_REGS[1], ctx_stack_opnd(ctx, argc - 1));
|
||||
mov(cb, C_ARG_REGS[2], ctx_stack_opnd(ctx, argc));
|
||||
}
|
||||
// Variadic method with Ruby array
|
||||
if (cfunc->argc == -2) {
|
||||
// Create a Ruby array from the arguments.
|
||||
//
|
||||
// This follows similar behaviour to vm_call_cfunc_with_frame() and
|
||||
// call_cfunc_m2(). We use rb_ec_ary_new_from_values() instead of
|
||||
// rb_ary_new4() since we have REG_EC available.
|
||||
//
|
||||
// Before getting here we will have set the new CFP in the EC, and the
|
||||
// stack at CFP's SP will contain the values we are inserting into the
|
||||
// Array, so they will be properly marked if we hit a GC.
|
||||
|
||||
// rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VLAUE *elts)
|
||||
mov(cb, C_ARG_REGS[0], REG_EC);
|
||||
mov(cb, C_ARG_REGS[1], imm_opnd(argc));
|
||||
lea(cb, C_ARG_REGS[2], ctx_stack_opnd(ctx, argc - 1));
|
||||
call_ptr(cb, REG0, (void *)rb_ec_ary_new_from_values);
|
||||
|
||||
// rb_file_s_join(VALUE recv, VALUE args)
|
||||
mov(cb, C_ARG_REGS[0], ctx_stack_opnd(ctx, argc));
|
||||
mov(cb, C_ARG_REGS[1], RAX);
|
||||
}
|
||||
|
||||
// Pop the C function arguments from the stack (in the caller)
|
||||
ctx_stack_pop(ctx, argc + 1);
|
||||
|
|
Loading…
Add table
Reference in a new issue