mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Implement invokebuiltin
This commit is contained in:
parent
6055078b24
commit
9951a9a8ec
3 changed files with 60 additions and 1 deletions
|
@ -1210,6 +1210,18 @@ assert_equal 'foo123', %q{
|
||||||
make_str("foo", 123)
|
make_str("foo", 123)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# test invokebuiltin as used in struct assignment
|
||||||
|
assert_equal '123', %q{
|
||||||
|
def foo(obj)
|
||||||
|
obj.foo = 123
|
||||||
|
end
|
||||||
|
|
||||||
|
struct = Struct.new(:foo)
|
||||||
|
obj = struct.new
|
||||||
|
foo(obj)
|
||||||
|
foo(obj)
|
||||||
|
}
|
||||||
|
|
||||||
# test invokebuiltin_delegate as used inside Dir.open
|
# test invokebuiltin_delegate as used inside Dir.open
|
||||||
assert_equal '.', %q{
|
assert_equal '.', %q{
|
||||||
def foo(path)
|
def foo(path)
|
||||||
|
|
|
@ -310,6 +310,19 @@ class TestYJIT < Test::Unit::TestCase
|
||||||
RUBY
|
RUBY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_invokebuiltin
|
||||||
|
assert_compiles(<<~RUBY)
|
||||||
|
def foo(obj)
|
||||||
|
obj.foo = 123
|
||||||
|
obj.bar = 123
|
||||||
|
end
|
||||||
|
|
||||||
|
Foo = Struct.new(:foo, :bar)
|
||||||
|
foo(Foo.new(123))
|
||||||
|
foo(Foo.new(123))
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
def test_super_iseq
|
def test_super_iseq
|
||||||
assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
|
assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
|
||||||
class A
|
class A
|
||||||
|
|
|
@ -4136,6 +4136,39 @@ gen_getblockparamproxy(jitstate_t *jit, ctx_t *ctx)
|
||||||
return YJIT_KEEP_COMPILING;
|
return YJIT_KEEP_COMPILING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static codegen_status_t
|
||||||
|
gen_invokebuiltin(jitstate_t *jit, ctx_t *ctx)
|
||||||
|
{
|
||||||
|
const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0);
|
||||||
|
|
||||||
|
if (bf->argc + 2 > NUM_C_ARG_REGS) {
|
||||||
|
return YJIT_CANT_COMPILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the calls don't allocate, do they need up to date PC, SP?
|
||||||
|
jit_prepare_routine_call(jit, ctx, REG0);
|
||||||
|
|
||||||
|
// Call the builtin func (ec, recv, arg1, arg2, ...)
|
||||||
|
mov(cb, C_ARG_REGS[0], REG_EC);
|
||||||
|
mov(cb, C_ARG_REGS[1], member_opnd(REG_CFP, rb_control_frame_t, self));
|
||||||
|
|
||||||
|
// Copy arguments from locals
|
||||||
|
for (int32_t i = 0; i < bf->argc; i++) {
|
||||||
|
x86opnd_t stack_opnd = ctx_stack_opnd(ctx, bf->argc - i - 1);
|
||||||
|
x86opnd_t c_arg_reg = C_ARG_REGS[2 + i];
|
||||||
|
mov(cb, c_arg_reg, stack_opnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
call_ptr(cb, REG0, (void *)bf->func_ptr);
|
||||||
|
|
||||||
|
// Push the return value
|
||||||
|
ctx_stack_pop(ctx, bf->argc);
|
||||||
|
x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
|
||||||
|
mov(cb, stack_ret, RAX);
|
||||||
|
|
||||||
|
return YJIT_KEEP_COMPILING;
|
||||||
|
}
|
||||||
|
|
||||||
// opt_invokebuiltin_delegate calls a builtin function, like
|
// opt_invokebuiltin_delegate calls a builtin function, like
|
||||||
// invokebuiltin does, but instead of taking arguments from the top of the
|
// invokebuiltin does, but instead of taking arguments from the top of the
|
||||||
// stack uses the argument locals (and self) from the current method.
|
// stack uses the argument locals (and self) from the current method.
|
||||||
|
@ -4145,7 +4178,7 @@ gen_opt_invokebuiltin_delegate(jitstate_t *jit, ctx_t *ctx)
|
||||||
const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0);
|
const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0);
|
||||||
int32_t start_index = (int32_t)jit_get_arg(jit, 1);
|
int32_t start_index = (int32_t)jit_get_arg(jit, 1);
|
||||||
|
|
||||||
if (bf->argc + 2 >= NUM_C_ARG_REGS) {
|
if (bf->argc + 2 > NUM_C_ARG_REGS) {
|
||||||
return YJIT_CANT_COMPILE;
|
return YJIT_CANT_COMPILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4387,6 +4420,7 @@ yjit_init_codegen(void)
|
||||||
yjit_reg_op(BIN(opt_length), gen_opt_length);
|
yjit_reg_op(BIN(opt_length), gen_opt_length);
|
||||||
yjit_reg_op(BIN(opt_regexpmatch2), gen_opt_regexpmatch2);
|
yjit_reg_op(BIN(opt_regexpmatch2), gen_opt_regexpmatch2);
|
||||||
yjit_reg_op(BIN(opt_getinlinecache), gen_opt_getinlinecache);
|
yjit_reg_op(BIN(opt_getinlinecache), gen_opt_getinlinecache);
|
||||||
|
yjit_reg_op(BIN(invokebuiltin), gen_invokebuiltin);
|
||||||
yjit_reg_op(BIN(opt_invokebuiltin_delegate), gen_opt_invokebuiltin_delegate);
|
yjit_reg_op(BIN(opt_invokebuiltin_delegate), gen_opt_invokebuiltin_delegate);
|
||||||
yjit_reg_op(BIN(opt_invokebuiltin_delegate_leave), gen_opt_invokebuiltin_delegate);
|
yjit_reg_op(BIN(opt_invokebuiltin_delegate_leave), gen_opt_invokebuiltin_delegate);
|
||||||
yjit_reg_op(BIN(opt_case_dispatch), gen_opt_case_dispatch);
|
yjit_reg_op(BIN(opt_case_dispatch), gen_opt_case_dispatch);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue