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
|
||||||
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_missing_method,
|
||||||
send_bmethod,
|
send_bmethod,
|
||||||
send_refined_method,
|
send_refined_method,
|
||||||
send_cfunc_ruby_array_varg,
|
|
||||||
send_cfunc_argc_mismatch,
|
send_cfunc_argc_mismatch,
|
||||||
send_cfunc_toomany_args,
|
send_cfunc_toomany_args,
|
||||||
send_cfunc_tracing,
|
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);
|
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 the argument count doesn't match
|
||||||
if (cfunc->argc >= 0 && cfunc->argc != argc) {
|
if (cfunc->argc >= 0 && cfunc->argc != argc) {
|
||||||
GEN_COUNTER_INC(cb, send_cfunc_argc_mismatch);
|
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));
|
lea(cb, C_ARG_REGS[1], ctx_stack_opnd(ctx, argc - 1));
|
||||||
mov(cb, C_ARG_REGS[2], ctx_stack_opnd(ctx, argc));
|
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)
|
// Pop the C function arguments from the stack (in the caller)
|
||||||
ctx_stack_pop(ctx, argc + 1);
|
ctx_stack_pop(ctx, argc + 1);
|
||||||
|
|
Loading…
Add table
Reference in a new issue