diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs index 94da426ba3..22998b1ab5 100644 --- a/yjit/src/backend/arm64/mod.rs +++ b/yjit/src/backend/arm64/mod.rs @@ -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 => { diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index 5387629cb8..f4afa567b3 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -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); diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs index 4e0a9dcf02..dfbd9e990b 100644 --- a/yjit/src/backend/x86_64/mod.rs +++ b/yjit/src/backend/x86_64/mod.rs @@ -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 diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index a54137fa97..87815902ee 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -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 { 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), /*