зеркало из https://github.com/github/ruby.git
Port newhash, add tests for newhash, duphash
This commit is contained in:
Родитель
a1ea018fd6
Коммит
6c50089599
|
@ -466,6 +466,9 @@ impl Assembler
|
||||||
emit_push(cb, sys_scratch);
|
emit_push(cb, sys_scratch);
|
||||||
},
|
},
|
||||||
Op::CPop => {
|
Op::CPop => {
|
||||||
|
emit_pop(cb, insn.out.into());
|
||||||
|
},
|
||||||
|
Op::CPopInto => {
|
||||||
emit_pop(cb, insn.opnds[0].into());
|
emit_pop(cb, insn.opnds[0].into());
|
||||||
},
|
},
|
||||||
Op::CPopAll => {
|
Op::CPopAll => {
|
||||||
|
|
|
@ -96,6 +96,7 @@ pub enum Op
|
||||||
// Push and pop registers to/from the C stack
|
// Push and pop registers to/from the C stack
|
||||||
CPush,
|
CPush,
|
||||||
CPop,
|
CPop,
|
||||||
|
CPopInto,
|
||||||
|
|
||||||
// Push and pop all of the caller-save registers and the flags to/from the C
|
// Push and pop all of the caller-save registers and the flags to/from the C
|
||||||
// stack
|
// 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 {
|
macro_rules! def_push_0_opnd_no_out {
|
||||||
($op_name:ident, $opcode:expr) => {
|
($op_name:ident, $opcode:expr) => {
|
||||||
impl Assembler
|
impl Assembler
|
||||||
|
@ -817,7 +831,8 @@ def_push_2_opnd!(sub, Op::Sub);
|
||||||
def_push_2_opnd!(and, Op::And);
|
def_push_2_opnd!(and, Op::And);
|
||||||
def_push_1_opnd!(not, Op::Not);
|
def_push_1_opnd!(not, Op::Not);
|
||||||
def_push_1_opnd_no_out!(cpush, Op::CPush);
|
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!(cpush_all, Op::CPushAll);
|
||||||
def_push_0_opnd_no_out!(cpop_all, Op::CPopAll);
|
def_push_0_opnd_no_out!(cpop_all, Op::CPopAll);
|
||||||
def_push_1_opnd_no_out!(cret, Op::CRet);
|
def_push_1_opnd_no_out!(cret, Op::CRet);
|
||||||
|
|
|
@ -243,9 +243,10 @@ impl Assembler
|
||||||
// Load effective address
|
// Load effective address
|
||||||
Op::Lea => lea(cb, insn.out.into(), insn.opnds[0].into()),
|
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::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
|
// Push and pop to the C stack all caller-save registers and the
|
||||||
// flags
|
// flags
|
||||||
|
|
|
@ -394,9 +394,9 @@ fn gen_code_for_exit_from_stub(ocb: &mut OutlinedCb) -> CodePtr {
|
||||||
|
|
||||||
gen_counter_incr!(asm, exit_from_branch_stub);
|
gen_counter_incr!(asm, exit_from_branch_stub);
|
||||||
|
|
||||||
asm.cpop(SP);
|
asm.cpop_into(SP);
|
||||||
asm.cpop(EC);
|
asm.cpop_into(EC);
|
||||||
asm.cpop(CFP);
|
asm.cpop_into(CFP);
|
||||||
|
|
||||||
asm.cret(Qundef.into());
|
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_into(SP);
|
||||||
asm.cpop(EC);
|
asm.cpop_into(EC);
|
||||||
asm.cpop(CFP);
|
asm.cpop_into(CFP);
|
||||||
|
|
||||||
asm.cret(Qundef.into());
|
asm.cret(Qundef.into());
|
||||||
}
|
}
|
||||||
|
@ -527,9 +527,9 @@ fn gen_full_cfunc_return(ocb: &mut OutlinedCb) -> CodePtr {
|
||||||
gen_counter_incr!(asm, traced_cfunc_return);
|
gen_counter_incr!(asm, traced_cfunc_return);
|
||||||
|
|
||||||
// Return to the interpreter
|
// Return to the interpreter
|
||||||
asm.cpop(SP);
|
asm.cpop_into(SP);
|
||||||
asm.cpop(EC);
|
asm.cpop_into(EC);
|
||||||
asm.cpop(CFP);
|
asm.cpop_into(CFP);
|
||||||
|
|
||||||
asm.cret(Qundef.into());
|
asm.cret(Qundef.into());
|
||||||
|
|
||||||
|
@ -551,9 +551,9 @@ fn gen_leave_exit(ocb: &mut OutlinedCb) -> CodePtr {
|
||||||
// Every exit to the interpreter should be counted
|
// Every exit to the interpreter should be counted
|
||||||
gen_counter_incr!(asm, leave_interp_return);
|
gen_counter_incr!(asm, leave_interp_return);
|
||||||
|
|
||||||
asm.cpop(SP);
|
asm.cpop_into(SP);
|
||||||
asm.cpop(EC);
|
asm.cpop_into(EC);
|
||||||
asm.cpop(CFP);
|
asm.cpop_into(CFP);
|
||||||
|
|
||||||
asm.cret(C_RET_OPND);
|
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.
|
// We're not starting at the first PC, so we need to exit.
|
||||||
gen_counter_incr!(asm, leave_start_pc_non_zero);
|
gen_counter_incr!(asm, leave_start_pc_non_zero);
|
||||||
|
|
||||||
asm.cpop(SP);
|
asm.cpop_into(SP);
|
||||||
asm.cpop(EC);
|
asm.cpop_into(EC);
|
||||||
asm.cpop(CFP);
|
asm.cpop_into(CFP);
|
||||||
|
|
||||||
asm.cret(Qundef.into());
|
asm.cret(Qundef.into());
|
||||||
|
|
||||||
|
@ -1706,55 +1706,59 @@ fn gen_setlocal_wc1(
|
||||||
let idx = jit_get_arg(jit, 0).as_i32();
|
let idx = jit_get_arg(jit, 0).as_i32();
|
||||||
gen_setlocal_generic(jit, ctx, cb, ocb, idx, 1)
|
gen_setlocal_generic(jit, ctx, cb, ocb, idx, 1)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// new hash initialized from top N values
|
// new hash initialized from top N values
|
||||||
fn gen_newhash(
|
fn gen_newhash(
|
||||||
jit: &mut JITState,
|
jit: &mut JITState,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
cb: &mut CodeBlock,
|
asm: &mut Assembler,
|
||||||
_ocb: &mut OutlinedCb,
|
_ocb: &mut OutlinedCb,
|
||||||
) -> CodegenStatus {
|
) -> 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
|
// 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 {
|
if num != 0 {
|
||||||
// val = rb_hash_new_with_size(num / 2);
|
// val = rb_hash_new_with_size(num / 2);
|
||||||
mov(cb, C_ARG_REGS[0], imm_opnd(num / 2));
|
let new_hash = asm.ccall(
|
||||||
call_ptr(cb, REG0, rb_hash_new_with_size as *const u8);
|
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
|
// Save the allocated hash as we want to push it after insertion
|
||||||
push(cb, RAX);
|
asm.cpush(new_hash);
|
||||||
push(cb, RAX); // alignment
|
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);
|
// rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
|
||||||
mov(cb, C_ARG_REGS[0], imm_opnd(num));
|
asm.ccall(
|
||||||
lea(
|
rb_hash_bulk_insert as *const u8,
|
||||||
cb,
|
vec![
|
||||||
C_ARG_REGS[1],
|
Opnd::UImm(num),
|
||||||
ctx.stack_opnd((num - 1).try_into().unwrap()),
|
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
|
let new_hash = asm.cpop();
|
||||||
pop(cb, RAX);
|
asm.cpop_into(new_hash); // x86 alignment
|
||||||
|
|
||||||
ctx.stack_pop(num.try_into().unwrap());
|
ctx.stack_pop(num.try_into().unwrap());
|
||||||
let stack_ret = ctx.stack_push(Type::Hash);
|
let stack_ret = ctx.stack_push(Type::Hash);
|
||||||
mov(cb, stack_ret, RAX);
|
asm.mov(stack_ret, new_hash);
|
||||||
} else {
|
} else {
|
||||||
// val = rb_hash_new();
|
// 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);
|
let stack_ret = ctx.stack_push(Type::Hash);
|
||||||
mov(cb, stack_ret, RAX);
|
asm.mov(stack_ret, new_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
fn gen_putstring(
|
fn gen_putstring(
|
||||||
jit: &mut JITState,
|
jit: &mut JITState,
|
||||||
|
@ -6005,8 +6009,8 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {
|
||||||
YARVINSN_opt_minus => Some(gen_opt_minus),
|
YARVINSN_opt_minus => Some(gen_opt_minus),
|
||||||
YARVINSN_opt_and => Some(gen_opt_and),
|
YARVINSN_opt_and => Some(gen_opt_and),
|
||||||
YARVINSN_opt_or => Some(gen_opt_or),
|
YARVINSN_opt_or => Some(gen_opt_or),
|
||||||
YARVINSN_newhash => Some(gen_newhash),
|
|
||||||
*/
|
*/
|
||||||
|
YARVINSN_newhash => Some(gen_newhash),
|
||||||
YARVINSN_duphash => Some(gen_duphash),
|
YARVINSN_duphash => Some(gen_duphash),
|
||||||
YARVINSN_newarray => Some(gen_newarray),
|
YARVINSN_newarray => Some(gen_newarray),
|
||||||
/*
|
/*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче