Skip to content

Commit cb33f22

Browse files
jhawthorntekknolagist0012
committed
ZJIT: Precise GC writebarriers
This issues writebarriers for objects added via gc_offsets or by profiling. This may be slower than writebarrier_remember, but we would like it to be more debuggable. Co-authored-by: Max Bernstein <ruby@bernsteinbear.com> Co-authored-by: Stan Lo <stan001212@gmail.com>
1 parent 39b844e commit cb33f22

File tree

3 files changed

+24
-8
lines changed

3 files changed

+24
-8
lines changed

zjit/src/codegen.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::rc::Rc;
44
use crate::asm::Label;
55
use crate::backend::current::{Reg, ALLOC_REGS};
66
use crate::invariants::track_bop_assumption;
7-
use crate::gc::get_or_create_iseq_payload;
7+
use crate::gc::{get_or_create_iseq_payload, append_gc_offsets};
88
use crate::state::ZJITState;
99
use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
1010
use crate::backend::lir::{self, asm_comment, asm_ccall, Assembler, Opnd, SideExitContext, Target, CFP, C_ARG_OPNDS, C_RET_OPND, EC, NATIVE_STACK_PTR, SP};
@@ -124,7 +124,7 @@ fn gen_iseq_entry_point_body(cb: &mut CodeBlock, iseq: IseqPtr) -> *const u8 {
124124
// Remember the block address to reuse it later
125125
let payload = get_or_create_iseq_payload(iseq);
126126
payload.start_ptr = Some(start_ptr);
127-
payload.gc_offsets.extend(gc_offsets);
127+
append_gc_offsets(iseq, &gc_offsets);
128128

129129
// Compile an entry point to the JIT code
130130
(gen_entry(cb, iseq, &function, start_ptr, jit.c_stack_bytes), jit.branch_iseqs)
@@ -193,7 +193,7 @@ fn gen_iseq(cb: &mut CodeBlock, iseq: IseqPtr) -> Option<(CodePtr, Vec<(Rc<Branc
193193
let result = gen_function(cb, iseq, &function);
194194
if let Some((start_ptr, gc_offsets, jit)) = result {
195195
payload.start_ptr = Some(start_ptr);
196-
payload.gc_offsets.extend(gc_offsets);
196+
append_gc_offsets(iseq, &gc_offsets);
197197
Some((start_ptr, jit.branch_iseqs))
198198
} else {
199199
None
@@ -999,7 +999,7 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard
999999

10001000
/// Compile an identity check with a side exit
10011001
fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: VALUE, state: &FrameState) -> Option<lir::Opnd> {
1002-
asm.cmp(val, Opnd::UImm(expected.into()));
1002+
asm.cmp(val, Opnd::Value(expected));
10031003
asm.jnz(side_exit(jit, state, GuardBitEquals(expected))?);
10041004
Some(val)
10051005
}

zjit/src/gc.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,23 @@ pub extern "C" fn rb_zjit_iseq_mark(payload: *mut c_void) {
9090
}
9191
}
9292

93+
/// Append a set of gc_offsets to the iseq's payload
94+
pub fn append_gc_offsets(iseq: IseqPtr, offsets: &Vec<CodePtr>) {
95+
let payload = get_or_create_iseq_payload(iseq);
96+
payload.gc_offsets.extend(offsets);
97+
98+
// Call writebarrier on each newly added value
99+
let cb = ZJITState::get_code_block();
100+
for &offset in offsets.iter() {
101+
let value_ptr: *const u8 = offset.raw_ptr(cb);
102+
let value_ptr = value_ptr as *const VALUE;
103+
unsafe {
104+
let object = value_ptr.read_unaligned();
105+
rb_gc_writebarrier(iseq.into(), object);
106+
}
107+
}
108+
}
109+
93110
/// GC callback for updating GC objects in the per-iseq payload.
94111
/// This is a mirror of [rb_zjit_iseq_mark].
95112
#[unsafe(no_mangle)]

zjit/src/profile.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,10 @@ fn profile_operands(profiler: &mut Profiler, profile: &mut IseqProfile, n: usize
8888
for i in 0..n {
8989
let opnd_type = Type::from_value(profiler.peek_at_stack((n - i - 1) as isize));
9090
types[i] = types[i].union(opnd_type);
91+
if let Some(object) = types[i].gc_object() {
92+
unsafe { rb_gc_writebarrier(profiler.iseq.into(), object) };
93+
}
9194
}
92-
// In the loop above, we probably added a new reference to the profile through
93-
// the VALUE in Type. It's messy and relatively slow to conditionally run a
94-
// write barrier for each Type, so just remember to re-mark the iseq.
95-
unsafe { rb_gc_writebarrier_remember(profiler.iseq.into()) };
9695
}
9796

9897
#[derive(Debug)]

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