Skip to content

Commit 63e9275

Browse files
authored
Merge pull request #203 from jhawthorn/getspecial
Implement getspecial
2 parents 1701214 + 5731380 commit 63e9275

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

test/ruby/test_yjit.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,15 @@ def test_expandarray_nil
205205
RUBY
206206
end
207207

208+
def test_getspecial_backref
209+
assert_compiles("'foo' =~ /(o)./; $&", insns: %i[getspecial], result: "oo")
210+
assert_compiles("'foo' =~ /(o)./; $`", insns: %i[getspecial], result: "f")
211+
assert_compiles("'foo' =~ /(o)./; $'", insns: %i[getspecial], result: "")
212+
assert_compiles("'foo' =~ /(o)./; $+", insns: %i[getspecial], result: "o")
213+
assert_compiles("'foo' =~ /(o)./; $1", insns: %i[getspecial], result: "o")
214+
assert_compiles("'foo' =~ /(o)./; $2", insns: %i[getspecial], result: nil)
215+
end
216+
208217
def test_compile_opt_getinlinecache
209218
assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, min_calls: 2)
210219
def get_foo

yjit_codegen.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3806,6 +3806,77 @@ gen_toregexp(jitstate_t* jit, ctx_t* ctx)
38063806
return YJIT_KEEP_COMPILING;
38073807
}
38083808

3809+
static codegen_status_t
3810+
gen_getspecial(jitstate_t *jit, ctx_t *ctx)
3811+
{
3812+
// This takes two arguments, key and type
3813+
// key is only used when type == 0
3814+
// A non-zero type determines which type of backref to fetch
3815+
rb_num_t key = jit_get_arg(jit, 0);
3816+
rb_num_t type = jit_get_arg(jit, 1);
3817+
3818+
if (type == 0) {
3819+
// not yet implemented
3820+
return YJIT_CANT_COMPILE;
3821+
} else if (type & 0x01) {
3822+
// Fetch a "special" backref based on a char encoded by shifting by 1
3823+
3824+
// Can raise if matchdata uninitialized
3825+
jit_prepare_routine_call(jit, ctx, REG0);
3826+
3827+
// call rb_backref_get()
3828+
ADD_COMMENT(cb, "rb_backref_get");
3829+
call_ptr(cb, REG0, (void *)rb_backref_get);
3830+
mov(cb, C_ARG_REGS[0], RAX);
3831+
3832+
switch (type >> 1) {
3833+
case '&':
3834+
ADD_COMMENT(cb, "rb_reg_last_match");
3835+
call_ptr(cb, REG0, (void *)rb_reg_last_match);
3836+
break;
3837+
case '`':
3838+
ADD_COMMENT(cb, "rb_reg_match_pre");
3839+
call_ptr(cb, REG0, (void *)rb_reg_match_pre);
3840+
break;
3841+
case '\'':
3842+
ADD_COMMENT(cb, "rb_reg_match_post");
3843+
call_ptr(cb, REG0, (void *)rb_reg_match_post);
3844+
break;
3845+
case '+':
3846+
ADD_COMMENT(cb, "rb_reg_match_last");
3847+
call_ptr(cb, REG0, (void *)rb_reg_match_last);
3848+
break;
3849+
default:
3850+
rb_bug("invalid back-ref");
3851+
}
3852+
3853+
x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
3854+
mov(cb, stack_ret, RAX);
3855+
3856+
return YJIT_KEEP_COMPILING;
3857+
} else {
3858+
// Fetch the N-th match from the last backref based on type shifted by 1
3859+
3860+
// Can raise if matchdata uninitialized
3861+
jit_prepare_routine_call(jit, ctx, REG0);
3862+
3863+
// call rb_backref_get()
3864+
ADD_COMMENT(cb, "rb_backref_get");
3865+
call_ptr(cb, REG0, (void *)rb_backref_get);
3866+
3867+
// rb_reg_nth_match((int)(type >> 1), backref);
3868+
ADD_COMMENT(cb, "rb_reg_nth_match");
3869+
mov(cb, C_ARG_REGS[0], imm_opnd(type >> 1));
3870+
mov(cb, C_ARG_REGS[1], RAX);
3871+
call_ptr(cb, REG0, (void *)rb_reg_nth_match);
3872+
3873+
x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
3874+
mov(cb, stack_ret, RAX);
3875+
3876+
return YJIT_KEEP_COMPILING;
3877+
}
3878+
}
3879+
38093880
static codegen_status_t
38103881
gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx)
38113882
{
@@ -4156,6 +4227,7 @@ yjit_init_codegen(void)
41564227
yjit_reg_op(BIN(setglobal), gen_setglobal);
41574228
yjit_reg_op(BIN(tostring), gen_tostring);
41584229
yjit_reg_op(BIN(toregexp), gen_toregexp);
4230+
yjit_reg_op(BIN(getspecial), gen_getspecial);
41594231

41604232
yjit_method_codegen_table = st_init_numtable();
41614233

0 commit comments

Comments
 (0)