summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Colson <[email protected]>2021-12-16 19:52:44 -0500
committerAlan Wu <[email protected]>2021-12-18 15:59:30 -0500
commit45f2182438a632b1217ca26f3e89860e2ee58357 (patch)
treeb291107efcb80b71fac9e2bb8acdaaf9edf13aa9
parentdd29ba076439375c6e235218ce5a0a3f01d41b29 (diff)
YJIT: Implement intern
`intern` showed up in the top 20 most frequent exit ops (granted with a fairly small percentage) in a benchmark run by @jhawthorn on github/github. This implementation is similar to gen_anytostring, but with 1 stack pop instead of 2. Co-authored-by: John Hawthorn <[email protected]>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5291
-rw-r--r--test/ruby/test_yjit.rb5
-rw-r--r--yjit_codegen.c20
2 files changed, 25 insertions, 0 deletions
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index c0230f7419..6390ab4c01 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -256,6 +256,11 @@ class TestYJIT < Test::Unit::TestCase
assert_no_exits('/#{true}/')
end
+ def test_compile_dynamic_symbol
+ assert_compiles(':"#{"foo"}"', insns: %i[intern])
+ assert_compiles('s = "bar"; :"foo#{s}"', insns: %i[intern])
+ end
+
def test_getlocal_with_level
assert_compiles(<<~RUBY, insns: %i[getlocal opt_plus], result: [[7]])
def foo(foo, bar)
diff --git a/yjit_codegen.c b/yjit_codegen.c
index eebb129df8..528d9a45d7 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -4500,6 +4500,25 @@ gen_toregexp(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
}
static codegen_status_t
+gen_intern(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
+{
+ // Save the PC and SP because we might allocate
+ jit_prepare_routine_call(jit, ctx, REG0);
+
+ x86opnd_t str = ctx_stack_pop(ctx, 1);
+
+ mov(cb, C_ARG_REGS[0], str);
+
+ call_ptr(cb, REG0, (void *)&rb_str_intern);
+
+ // Push the return value
+ x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
+ mov(cb, stack_ret, RAX);
+
+ return YJIT_KEEP_COMPILING;
+}
+
+static codegen_status_t
gen_getspecial(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
{
// This takes two arguments, key and type
@@ -5010,6 +5029,7 @@ yjit_init_codegen(void)
yjit_reg_op(BIN(anytostring), gen_anytostring);
yjit_reg_op(BIN(objtostring), gen_objtostring);
yjit_reg_op(BIN(toregexp), gen_toregexp);
+ yjit_reg_op(BIN(intern), gen_intern);
yjit_reg_op(BIN(getspecial), gen_getspecial);
yjit_reg_op(BIN(getclassvariable), gen_getclassvariable);
yjit_reg_op(BIN(setclassvariable), gen_setclassvariable);