Skip to content

Commit

Permalink
Port anytostring, intern, and toregexp (Shopify#348)
Browse files Browse the repository at this point in the history
* Port anytostring, intern, and toregexp

* Port getspecial to the new backend (#349)

PR: Shopify#349
  • Loading branch information
k0kubun committed Aug 29, 2022
1 parent 16307ad commit 330c9e9
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 61 deletions.
16 changes: 16 additions & 0 deletions bootstraptest/test_yjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3087,3 +3087,19 @@ def foo()
foo = Foo.new
foo.foo
}

# anytostring, intern
assert_equal 'true', %q{
def foo()
:"#{true}"
end
foo()
}

# toregexp
assert_equal '/true/', %q{
def foo()
/#{true}/
end
foo().inspect
}
122 changes: 61 additions & 61 deletions yjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5338,31 +5338,28 @@ fn gen_setglobal(
KeepCompiling
}

/*
fn gen_anytostring(
jit: &mut JITState,
ctx: &mut Context,
cb: &mut CodeBlock,
asm: &mut Assembler,
_ocb: &mut OutlinedCb,
) -> CodegenStatus {
// Save the PC and SP since we might call #to_s
jit_prepare_routine_call(jit, ctx, cb, REG0);
jit_prepare_routine_call(jit, ctx, asm);

let str = ctx.stack_pop(1);
let val = ctx.stack_pop(1);

mov(cb, C_ARG_REGS[0], str);
mov(cb, C_ARG_REGS[1], val);
call_ptr(cb, REG0, rb_obj_as_string_result as *const u8);
let val = asm.ccall(rb_obj_as_string_result as *const u8, vec![str, val]);

// Push the return value
let stack_ret = ctx.stack_push(Type::TString);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, val);

KeepCompiling
}

/*
fn gen_objtostring(
jit: &mut JITState,
ctx: &mut Context,
Expand Down Expand Up @@ -5399,76 +5396,83 @@ fn gen_objtostring(
gen_send_general(jit, ctx, cb, ocb, cd, None)
}
}
*/

fn gen_intern(
jit: &mut JITState,
ctx: &mut Context,
cb: &mut CodeBlock,
asm: &mut Assembler,
_ocb: &mut OutlinedCb,
) -> CodegenStatus {
// Save the PC and SP because we might allocate
jit_prepare_routine_call(jit, ctx, cb, REG0);
jit_prepare_routine_call(jit, ctx, asm);

let str = ctx.stack_pop(1);
mov(cb, C_ARG_REGS[0], str);
call_ptr(cb, REG0, rb_str_intern as *const u8);
let sym = asm.ccall(rb_str_intern as *const u8, vec![str]);

// Push the return value
let stack_ret = ctx.stack_push(Type::Unknown);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, sym);

KeepCompiling
}

fn gen_toregexp(
jit: &mut JITState,
ctx: &mut Context,
cb: &mut CodeBlock,
asm: &mut Assembler,
_ocb: &mut OutlinedCb,
) -> CodegenStatus {
let opt = jit_get_arg(jit, 0).as_i64();
let cnt = jit_get_arg(jit, 1).as_usize();

// Save the PC and SP because this allocates an object and could
// raise an exception.
jit_prepare_routine_call(jit, ctx, cb, REG0);
jit_prepare_routine_call(jit, ctx, asm);

let values_ptr = ctx.sp_opnd(-((SIZEOF_VALUE as isize) * (cnt as isize)));
ctx.stack_pop(cnt);

mov(cb, C_ARG_REGS[0], imm_opnd(0));
mov(cb, C_ARG_REGS[1], imm_opnd(cnt.try_into().unwrap()));
lea(cb, C_ARG_REGS[2], values_ptr);
call_ptr(cb, REG0, rb_ary_tmp_new_from_values as *const u8);
let ary = asm.ccall(
rb_ary_tmp_new_from_values as *const u8,
vec![
Opnd::Imm(0),
Opnd::UImm(jit_get_arg(jit, 1).as_u64()),
values_ptr,
]
);

// Save the array so we can clear it later
push(cb, RAX);
push(cb, RAX); // Alignment
mov(cb, C_ARG_REGS[0], RAX);
mov(cb, C_ARG_REGS[1], imm_opnd(opt));
call_ptr(cb, REG0, rb_reg_new_ary as *const u8);
asm.cpush(ary);
asm.cpush(ary); // Alignment

let val = asm.ccall(
rb_reg_new_ary as *const u8,
vec![
ary,
Opnd::Imm(opt),
]
);

// The actual regex is in RAX now. Pop the temp array from
// rb_ary_tmp_new_from_values into C arg regs so we can clear it
pop(cb, REG1); // Alignment
pop(cb, C_ARG_REGS[0]);
let ary = asm.cpop(); // Alignment
asm.cpop_into(ary);

// The value we want to push on the stack is in RAX right now
let stack_ret = ctx.stack_push(Type::Unknown);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, val);

// Clear the temp array.
call_ptr(cb, REG0, rb_ary_clear as *const u8);
asm.ccall(rb_ary_clear as *const u8, vec![ary]);

KeepCompiling
}

fn gen_getspecial(
jit: &mut JITState,
ctx: &mut Context,
cb: &mut CodeBlock,
asm: &mut Assembler,
_ocb: &mut OutlinedCb,
) -> CodegenStatus {
// This takes two arguments, key and type
Expand All @@ -5484,65 +5488,63 @@ fn gen_getspecial(
// Fetch a "special" backref based on a char encoded by shifting by 1

// Can raise if matchdata uninitialized
jit_prepare_routine_call(jit, ctx, cb, REG0);
jit_prepare_routine_call(jit, ctx, asm);

// call rb_backref_get()
add_comment(cb, "rb_backref_get");
call_ptr(cb, REG0, rb_backref_get as *const u8);
mov(cb, C_ARG_REGS[0], RAX);
asm.comment("rb_backref_get");
let backref = asm.ccall(rb_backref_get as *const u8, vec![]);

let rt_u8: u8 = (rtype >> 1).try_into().unwrap();
match rt_u8.into() {
let val = match rt_u8.into() {
'&' => {
add_comment(cb, "rb_reg_last_match");
call_ptr(cb, REG0, rb_reg_last_match as *const u8);
asm.comment("rb_reg_last_match");
asm.ccall(rb_reg_last_match as *const u8, vec![backref])
}
'`' => {
add_comment(cb, "rb_reg_match_pre");
call_ptr(cb, REG0, rb_reg_match_pre as *const u8);
asm.comment("rb_reg_match_pre");
asm.ccall(rb_reg_match_pre as *const u8, vec![backref])
}
'\'' => {
add_comment(cb, "rb_reg_match_post");
call_ptr(cb, REG0, rb_reg_match_post as *const u8);
asm.comment("rb_reg_match_post");
asm.ccall(rb_reg_match_post as *const u8, vec![backref])
}
'+' => {
add_comment(cb, "rb_reg_match_last");
call_ptr(cb, REG0, rb_reg_match_last as *const u8);
asm.comment("rb_reg_match_last");
asm.ccall(rb_reg_match_last as *const u8, vec![backref])
}
_ => panic!("invalid back-ref"),
}
};

let stack_ret = ctx.stack_push(Type::Unknown);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, val);

KeepCompiling
} else {
// Fetch the N-th match from the last backref based on type shifted by 1

// Can raise if matchdata uninitialized
jit_prepare_routine_call(jit, ctx, cb, REG0);
jit_prepare_routine_call(jit, ctx, asm);

// call rb_backref_get()
add_comment(cb, "rb_backref_get");
call_ptr(cb, REG0, rb_backref_get as *const u8);
asm.comment("rb_backref_get");
let backref = asm.ccall(rb_backref_get as *const u8, vec![]);

// rb_reg_nth_match((int)(type >> 1), backref);
add_comment(cb, "rb_reg_nth_match");
mov(
cb,
C_ARG_REGS[0],
imm_opnd((rtype >> 1).try_into().unwrap()),
asm.comment("rb_reg_nth_match");
let val = asm.ccall(
rb_reg_nth_match as *const u8,
vec![
Opnd::Imm((rtype >> 1).try_into().unwrap()),
backref,
]
);
mov(cb, C_ARG_REGS[1], RAX);
call_ptr(cb, REG0, rb_reg_nth_match as *const u8);

let stack_ret = ctx.stack_push(Type::Unknown);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, val);

KeepCompiling
}
}
*/

fn gen_getclassvariable(
jit: &mut JITState,
Expand Down Expand Up @@ -6052,13 +6054,11 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {

YARVINSN_getglobal => Some(gen_getglobal),
YARVINSN_setglobal => Some(gen_setglobal),
/*
YARVINSN_anytostring => Some(gen_anytostring),
YARVINSN_objtostring => Some(gen_objtostring),
//YARVINSN_objtostring => Some(gen_objtostring),
YARVINSN_intern => Some(gen_intern),
YARVINSN_toregexp => Some(gen_toregexp),
YARVINSN_getspecial => Some(gen_getspecial),
*/
YARVINSN_getclassvariable => Some(gen_getclassvariable),
YARVINSN_setclassvariable => Some(gen_setclassvariable),

Expand Down

0 comments on commit 330c9e9

Please sign in to comment.