Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port anytostring, intern, and toregexp #348

Merged
merged 2 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions bootstraptest/test_yjit_new_backend.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ def self.foo
Foo.foo
}

# getspecial
assert_equal 'nil', %q{
def foo()
$1
end
foo().inspect
}

# setglobal
assert_equal 'foo', %q{
def foo()
Expand All @@ -210,6 +218,21 @@ def foo()
$foo
}

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

# toregexp
assert_equal '/true/', %q{
def foo()
/#{true}/
end
foo().inspect
}



Expand Down
122 changes: 61 additions & 61 deletions yjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5300,31 +5300,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 @@ -5361,76 +5358,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 @@ -5446,65 +5450,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 @@ -5971,13 +5973,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