[前][次][番号順一覧][スレッド一覧]

ruby-changes:69237

From: John <ko1@a...>
Date: Thu, 21 Oct 2021 08:24:18 +0900 (JST)
Subject: [ruby-changes:69237] 44214e8ad9 (master): Implement getspecial

https://git.ruby-lang.org/ruby.git/commit/?id=44214e8ad9

From 44214e8ad9e8ba1adf704c8231b4ecced77d3b7a Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Wed, 8 Sep 2021 18:47:09 -0700
Subject: Implement getspecial

---
 test/ruby/test_yjit.rb |  9 +++++++
 yjit_codegen.c         | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index 4307a7dfb6..10eb4aa476 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -205,6 +205,15 @@ class TestYJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_yjit.rb#L205
     RUBY
   end
 
+  def test_getspecial_backref
+    assert_compiles("'foo' =~ /(o)./; $&", insns: %i[getspecial], result: "oo")
+    assert_compiles("'foo' =~ /(o)./; $`", insns: %i[getspecial], result: "f")
+    assert_compiles("'foo' =~ /(o)./; $'", insns: %i[getspecial], result: "")
+    assert_compiles("'foo' =~ /(o)./; $+", insns: %i[getspecial], result: "o")
+    assert_compiles("'foo' =~ /(o)./; $1", insns: %i[getspecial], result: "o")
+    assert_compiles("'foo' =~ /(o)./; $2", insns: %i[getspecial], result: nil)
+  end
+
   def test_compile_opt_getinlinecache
     assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, min_calls: 2)
       def get_foo
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 9fd70917d2..2e6613510f 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -3911,6 +3911,70 @@ gen_toregexp(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3911
     return YJIT_KEEP_COMPILING;
 }
 
+static codegen_status_t
+gen_getspecial(jitstate_t *jit, ctx_t *ctx)
+{
+    rb_num_t key = jit_get_arg(jit, 0);
+    rb_num_t type = jit_get_arg(jit, 1);
+
+    if (type == 0) {
+        // not yet implemented
+        return YJIT_CANT_COMPILE;
+    } else if (type & 0x01) {
+        // Can raise if matchdata uninitialized
+        jit_prepare_routine_call(jit, ctx, REG0);
+
+        // call rb_backref_get()
+        ADD_COMMENT(cb, "rb_backref_get");
+        call_ptr(cb, REG0, (void *)rb_backref_get);
+        mov(cb, C_ARG_REGS[0], RAX);
+
+        switch (type >> 1) {
+            case '&':
+                ADD_COMMENT(cb, "rb_reg_last_match");
+                call_ptr(cb, REG0, (void *)rb_reg_last_match);
+                break;
+            case '`':
+                ADD_COMMENT(cb, "rb_reg_match_pre");
+                call_ptr(cb, REG0, (void *)rb_reg_match_pre);
+                break;
+            case '\'':
+                ADD_COMMENT(cb, "rb_reg_match_post");
+                call_ptr(cb, REG0, (void *)rb_reg_match_post);
+                break;
+            case '+':
+                ADD_COMMENT(cb, "rb_reg_match_last");
+                call_ptr(cb, REG0, (void *)rb_reg_match_last);
+                break;
+            default:
+                rb_bug("invalid back-ref");
+        }
+
+        x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
+        mov(cb, stack_ret, RAX);
+
+        return YJIT_KEEP_COMPILING;
+    } else {
+        // Can raise if matchdata uninitialized
+        jit_prepare_routine_call(jit, ctx, REG0);
+
+        // call rb_backref_get()
+        ADD_COMMENT(cb, "rb_backref_get");
+        call_ptr(cb, REG0, (void *)rb_backref_get);
+
+        // rb_reg_nth_match((int)(type >> 1), backref);
+        ADD_COMMENT(cb, "rb_reg_nth_match");
+        mov(cb, C_ARG_REGS[0], imm_opnd(type >> 1));
+        mov(cb, C_ARG_REGS[1], RAX);
+        call_ptr(cb, REG0, (void *)rb_reg_nth_match);
+
+        x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
+        mov(cb, stack_ret, RAX);
+
+        return YJIT_KEEP_COMPILING;
+    }
+}
+
 static codegen_status_t
 gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx)
 {
@@ -4261,6 +4325,7 @@ yjit_init_codegen(void) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L4325
     yjit_reg_op(BIN(setglobal), gen_setglobal);
     yjit_reg_op(BIN(tostring), gen_tostring);
     yjit_reg_op(BIN(toregexp), gen_toregexp);
+    yjit_reg_op(BIN(getspecial), gen_getspecial);
 
     yjit_method_codegen_table = st_init_numtable();
 
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]