Add setclassvariable to yjit (#5127)

Implements setclassvariable in yjit. Note that this version is not
faster than the standard version because we aren't handling the inline
cache in assembly. This is still important to implement because it will
prevent yjit from exiting in methods that call both a cvar setter and
other code that yjit can compile.

Co-authored-by: Aaron Patterson tenderlove@ruby-lang.org
This commit is contained in:
Eileen M. Uchitelle 2021-11-23 14:09:24 -05:00 committed by GitHub
parent fb9d67742b
commit 459f9e3df8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2021-11-24 04:09:46 +09:00
Merged-By: maximecb <maximecb@ruby-lang.org>
3 changed files with 32 additions and 0 deletions

View File

@ -52,6 +52,11 @@ class TestYJIT < Test::Unit::TestCase
assert_in_out_err([yjit_child_env, '-e p RubyVM::YJIT.enabled?'], '', ['true'])
end
def test_compile_setclassvariable
script = 'class Foo; def self.foo; @@foo = 1; end; end; Foo.foo'
assert_compiles(script, insns: %i[setclassvariable], result: 1)
end
def test_compile_getclassvariable
script = 'class Foo; @@foo = 1; def self.foo; @@foo; end; end; Foo.foo'
assert_compiles(script, insns: %i[getclassvariable], result: 1)

View File

@ -1367,6 +1367,12 @@ vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *reg_cfp, ID
update_classvariable_cache(iseq, klass, id, ic);
}
void
rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic)
{
vm_setclassvariable(iseq, cfp, id, val, ic);
}
static inline VALUE
vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic)
{

View File

@ -4488,6 +4488,26 @@ gen_getclassvariable(jitstate_t* jit, ctx_t* ctx, codeblock_t* cb)
return YJIT_KEEP_COMPILING;
}
VALUE
rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic);
static codegen_status_t
gen_setclassvariable(jitstate_t* jit, ctx_t* ctx, codeblock_t* cb)
{
// rb_vm_setclassvariable can raise exceptions.
jit_prepare_routine_call(jit, ctx, REG0);
mov(cb, C_ARG_REGS[0], member_opnd(REG_CFP, rb_control_frame_t, iseq));
mov(cb, C_ARG_REGS[1], REG_CFP);
mov(cb, C_ARG_REGS[2], imm_opnd(jit_get_arg(jit, 0)));
mov(cb, C_ARG_REGS[3], ctx_stack_pop(ctx, 1));
mov(cb, C_ARG_REGS[4], imm_opnd(jit_get_arg(jit, 1)));
call_ptr(cb, REG0, (void *)rb_vm_setclassvariable);
return YJIT_KEEP_COMPILING;
}
static codegen_status_t
gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
{
@ -4886,6 +4906,7 @@ yjit_init_codegen(void)
yjit_reg_op(BIN(toregexp), gen_toregexp);
yjit_reg_op(BIN(getspecial), gen_getspecial);
yjit_reg_op(BIN(getclassvariable), gen_getclassvariable);
yjit_reg_op(BIN(setclassvariable), gen_setclassvariable);
yjit_method_codegen_table = st_init_numtable();