Skip to content

Commit ad84032

Browse files
committed
ZJIT: Use rb_vm_env_write() for hir::Insn::SetLocal
We weren't firing write barriers before when writing to imemo/env objects. Wbcheck caught this with test/ruby/test_refinement.rb: ruby -v: ruby 3.5.0dev (2025-07-22T17:05:58Z wbcheck 2569a80954) +ZJIT dev +PRISM +GC[wbcheck] [x86_64-linux] WBCHECK ERROR: Missed write barrier detected! Parent object: 0x558de9f4e6e0 (wb_protected: true) rb_obj_info_dump: 0x0000558de9f4e6e0 T_IMEMO/<env> Reference counts - snapshot: 3, writebarrier: 0, current: 4, missed: 1 Missing reference to: 0x558decf37c30 rb_obj_info_dump: 0x0000558decf37c30 method/UnboundMethod method WBCHECK SUMMARY: Found 1 objects with missed write barriers (1 total violations)
1 parent 45e65f5 commit ad84032

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

zjit/src/codegen.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cell::Cell;
22
use std::rc::Rc;
3+
use std::ffi::{c_int};
34

45
use crate::asm::Label;
56
use crate::backend::current::{Reg, ALLOC_REGS};
@@ -446,8 +447,18 @@ fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -
446447
/// can't optimize the level=0 case using the SP register.
447448
fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, local_ep_offset: u32, level: u32) -> Option<()> {
448449
let ep = gen_get_ep(asm, level);
449-
let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
450-
asm.mov(Opnd::mem(64, ep, offset), val);
450+
let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1))?;
451+
match val {
452+
// If we're writing a constant, non-heap VALUE, do a raw memory write without
453+
// running write barrier.
454+
lir::Opnd::Value(const_val) if const_val.special_const_p() => {
455+
let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
456+
asm.mov(Opnd::mem(64, ep, offset), val);
457+
}
458+
// We're potentially writing a reference to an IMEMO/env object,
459+
// so take care of the write barrier with a function.
460+
_ => { asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), val); }
461+
}
451462
Some(())
452463
}
453464

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy