Port newhash, add tests for newhash, duphash

This commit is contained in:
Maxime Chevalier-Boisvert 2022-07-14 16:51:01 -04:00 коммит произвёл Takashi Kokubun
Родитель a1ea018fd6
Коммит 6c50089599
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 6FFC433B12EE23DD
4 изменённых файлов: 64 добавлений и 41 удалений

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

@ -466,6 +466,9 @@ impl Assembler
emit_push(cb, sys_scratch);
},
Op::CPop => {
emit_pop(cb, insn.out.into());
},
Op::CPopInto => {
emit_pop(cb, insn.opnds[0].into());
},
Op::CPopAll => {

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

@ -96,6 +96,7 @@ pub enum Op
// Push and pop registers to/from the C stack
CPush,
CPop,
CPopInto,
// Push and pop all of the caller-save registers and the flags to/from the C
// stack
@ -743,6 +744,19 @@ macro_rules! def_push_jcc {
};
}
macro_rules! def_push_0_opnd {
($op_name:ident, $opcode:expr) => {
impl Assembler
{
#[must_use]
pub fn $op_name(&mut self) -> Opnd
{
self.push_insn($opcode, vec![], None)
}
}
};
}
macro_rules! def_push_0_opnd_no_out {
($op_name:ident, $opcode:expr) => {
impl Assembler
@ -817,7 +831,8 @@ def_push_2_opnd!(sub, Op::Sub);
def_push_2_opnd!(and, Op::And);
def_push_1_opnd!(not, Op::Not);
def_push_1_opnd_no_out!(cpush, Op::CPush);
def_push_1_opnd_no_out!(cpop, Op::CPop);
def_push_0_opnd!(cpop, Op::CPop);
def_push_1_opnd_no_out!(cpop_into, Op::CPopInto);
def_push_0_opnd_no_out!(cpush_all, Op::CPushAll);
def_push_0_opnd_no_out!(cpop_all, Op::CPopAll);
def_push_1_opnd_no_out!(cret, Op::CRet);

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

@ -243,9 +243,10 @@ impl Assembler
// Load effective address
Op::Lea => lea(cb, insn.out.into(), insn.opnds[0].into()),
// Push and pop to the C stack
// Push and pop to/from the C stack
Op::CPush => push(cb, insn.opnds[0].into()),
Op::CPop => pop(cb, insn.opnds[0].into()),
Op::CPop => pop(cb, insn.out.into()),
Op::CPopInto => pop(cb, insn.opnds[0].into()),
// Push and pop to the C stack all caller-save registers and the
// flags

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

@ -394,9 +394,9 @@ fn gen_code_for_exit_from_stub(ocb: &mut OutlinedCb) -> CodePtr {
gen_counter_incr!(asm, exit_from_branch_stub);
asm.cpop(SP);
asm.cpop(EC);
asm.cpop(CFP);
asm.cpop_into(SP);
asm.cpop_into(EC);
asm.cpop_into(CFP);
asm.cret(Qundef.into());
@ -443,9 +443,9 @@ fn gen_exit(exit_pc: *mut VALUE, ctx: &Context, asm: &mut Assembler) {
}
}
asm.cpop(SP);
asm.cpop(EC);
asm.cpop(CFP);
asm.cpop_into(SP);
asm.cpop_into(EC);
asm.cpop_into(CFP);
asm.cret(Qundef.into());
}
@ -527,9 +527,9 @@ fn gen_full_cfunc_return(ocb: &mut OutlinedCb) -> CodePtr {
gen_counter_incr!(asm, traced_cfunc_return);
// Return to the interpreter
asm.cpop(SP);
asm.cpop(EC);
asm.cpop(CFP);
asm.cpop_into(SP);
asm.cpop_into(EC);
asm.cpop_into(CFP);
asm.cret(Qundef.into());
@ -551,9 +551,9 @@ fn gen_leave_exit(ocb: &mut OutlinedCb) -> CodePtr {
// Every exit to the interpreter should be counted
gen_counter_incr!(asm, leave_interp_return);
asm.cpop(SP);
asm.cpop(EC);
asm.cpop(CFP);
asm.cpop_into(SP);
asm.cpop_into(EC);
asm.cpop_into(CFP);
asm.cret(C_RET_OPND);
@ -580,9 +580,9 @@ fn gen_pc_guard(asm: &mut Assembler, iseq: IseqPtr, insn_idx: u32) {
// We're not starting at the first PC, so we need to exit.
gen_counter_incr!(asm, leave_start_pc_non_zero);
asm.cpop(SP);
asm.cpop(EC);
asm.cpop(CFP);
asm.cpop_into(SP);
asm.cpop_into(EC);
asm.cpop_into(CFP);
asm.cret(Qundef.into());
@ -1706,55 +1706,59 @@ fn gen_setlocal_wc1(
let idx = jit_get_arg(jit, 0).as_i32();
gen_setlocal_generic(jit, ctx, cb, ocb, idx, 1)
}
*/
// new hash initialized from top N values
fn gen_newhash(
jit: &mut JITState,
ctx: &mut Context,
cb: &mut CodeBlock,
asm: &mut Assembler,
_ocb: &mut OutlinedCb,
) -> CodegenStatus {
let num: i64 = jit_get_arg(jit, 0).as_i64();
let num: u64 = jit_get_arg(jit, 0).as_u64();
// Save the PC and SP because we are allocating
jit_prepare_routine_call(jit, ctx, cb, REG0);
jit_prepare_routine_call(jit, ctx, asm);
if num != 0 {
// val = rb_hash_new_with_size(num / 2);
mov(cb, C_ARG_REGS[0], imm_opnd(num / 2));
call_ptr(cb, REG0, rb_hash_new_with_size as *const u8);
let new_hash = asm.ccall(
rb_hash_new_with_size as *const u8,
vec![Opnd::UImm(num / 2)]
);
// save the allocated hash as we want to push it after insertion
push(cb, RAX);
push(cb, RAX); // alignment
// Save the allocated hash as we want to push it after insertion
asm.cpush(new_hash);
asm.cpush(new_hash); // x86 alignment
// Get a pointer to the values to insert into the hash
let stack_addr_from_top = asm.lea(ctx.stack_opnd((num - 1) as i32));
// rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
mov(cb, C_ARG_REGS[0], imm_opnd(num));
lea(
cb,
C_ARG_REGS[1],
ctx.stack_opnd((num - 1).try_into().unwrap()),
asm.ccall(
rb_hash_bulk_insert as *const u8,
vec![
Opnd::UImm(num),
stack_addr_from_top,
new_hash
]
);
mov(cb, C_ARG_REGS[2], RAX);
call_ptr(cb, REG0, rb_hash_bulk_insert as *const u8);
pop(cb, RAX); // alignment
pop(cb, RAX);
let new_hash = asm.cpop();
asm.cpop_into(new_hash); // x86 alignment
ctx.stack_pop(num.try_into().unwrap());
let stack_ret = ctx.stack_push(Type::Hash);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, new_hash);
} else {
// val = rb_hash_new();
call_ptr(cb, REG0, rb_hash_new as *const u8);
let new_hash = asm.ccall(rb_hash_new as *const u8, vec![]);
let stack_ret = ctx.stack_push(Type::Hash);
mov(cb, stack_ret, RAX);
asm.mov(stack_ret, new_hash);
}
KeepCompiling
}
*/
fn gen_putstring(
jit: &mut JITState,
@ -6005,8 +6009,8 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {
YARVINSN_opt_minus => Some(gen_opt_minus),
YARVINSN_opt_and => Some(gen_opt_and),
YARVINSN_opt_or => Some(gen_opt_or),
YARVINSN_newhash => Some(gen_newhash),
*/
YARVINSN_newhash => Some(gen_newhash),
YARVINSN_duphash => Some(gen_duphash),
YARVINSN_newarray => Some(gen_newarray),
/*