Skip to content

Commit b349c91

Browse files
committed
ZJIT: Guide WB skipping for Insn::SetLocal using HIR type info
1 parent 3f89353 commit b349c91

2 files changed

Lines changed: 12 additions & 14 deletions

File tree

zjit/src/codegen.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
371371
Insn::SetGlobal { id, val, state } => return gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state)),
372372
Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
373373
&Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level)?,
374-
Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, opnd!(val), *ep_offset, *level),
374+
&Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, jit, function, val, ep_offset, level),
375375
Insn::GetConstantPath { ic, state } => gen_get_constant_path(jit, asm, *ic, &function.frame_state(*state))?,
376376
Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)),
377377
Insn::SideExit { state, reason } => return gen_side_exit(jit, asm, reason, &function.frame_state(*state)),
@@ -506,21 +506,19 @@ fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -
506506
/// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
507507
/// We generate this instruction with level=0 only when the local variable is on the heap, so we
508508
/// can't optimize the level=0 case using the SP register.
509-
fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, local_ep_offset: u32, level: u32) -> Option<()> {
509+
fn gen_setlocal_with_ep(asm: &mut Assembler, jit: &JITState, function: &Function, val: InsnId, local_ep_offset: u32, level: u32) -> Option<()> {
510510
let ep = gen_get_ep(asm, level);
511-
match val {
512-
// If we're writing a constant, non-heap VALUE, do a raw memory write without
513-
// running write barrier.
514-
lir::Opnd::Value(const_val) if const_val.special_const_p() => {
515-
let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
516-
asm.mov(Opnd::mem(64, ep, offset), val);
517-
}
511+
512+
// When we've proved that we're writing an immediate,
513+
// we can skip the write barrier.
514+
if function.type_of(val).is_immediate() {
515+
let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
516+
asm.mov(Opnd::mem(64, ep, offset), jit.get_opnd(val)?);
517+
} else {
518518
// We're potentially writing a reference to an IMEMO/env object,
519519
// so take care of the write barrier with a function.
520-
_ => {
521-
let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1))?;
522-
asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), val);
523-
}
520+
let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1))?;
521+
asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), jit.get_opnd(val)?);
524522
}
525523
Some(())
526524
}

zjit/src/hir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,7 @@ impl Function {
12341234
self.union_find.borrow_mut().make_equal_to(insn, replacement);
12351235
}
12361236

1237-
fn type_of(&self, insn: InsnId) -> Type {
1237+
pub fn type_of(&self, insn: InsnId) -> Type {
12381238
assert!(self.insns[insn.0].has_output());
12391239
self.insn_types[self.union_find.borrow_mut().find(insn).0]
12401240
}

0 commit comments

Comments
 (0)