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/