* Port anytostring, intern, and toregexp

* Port getspecial to the new backend (#349)

PR: https://github.com/Shopify/ruby/pull/349
This commit is contained in:
Takashi Kokubun 2022-08-01 20:39:31 -07:00
Родитель 16307adf8f
Коммит 330c9e9850
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 6FFC433B12EE23DD
2 изменённых файлов: 77 добавлений и 61 удалений

Просмотреть файл

@ -3087,3 +3087,19 @@ assert_equal 'foo', %q{
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
}

Просмотреть файл

@ -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,
@ -5399,25 +5396,23 @@ 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
}
@ -5425,7 +5420,7 @@ fn gen_intern(
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();
@ -5433,34 +5428,43 @@ fn gen_toregexp(
// 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
}
@ -5468,7 +5472,7 @@ fn gen_toregexp(
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
@ -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,
@ -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),