summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEileen M. Uchitelle <eileencodes@users.noreply.github.com>2021-11-23 14:09:24 -0500
committerGitHub <noreply@github.com>2021-11-23 14:09:24 -0500
commit459f9e3df8e8080d8c44aed3636a337e6ee64132 (patch)
tree497fdb2d8a6751b2dbbaf7be979bce6444b01b9f
parentfb9d67742b77e5b38cfe46b448b64e6965aa3e70 (diff)
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
Notes
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
-rw-r--r--test/ruby/test_yjit.rb5
-rw-r--r--vm_insnhelper.c6
-rw-r--r--yjit_codegen.c21
3 files changed, 32 insertions, 0 deletions
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index a571432ccd..d951f79cfc 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -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)
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index d1930d146c..348bfea5aa 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -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)
{
diff --git a/yjit_codegen.c b/yjit_codegen.c
index c34c56a972..add1e2012a 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -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();