Skip to content

Commit bb4761d

Browse files
committed
ZJIT: x86: split: Query new assembler for live ranges
Previously we crashed panicked due to index bounds check running test_fixnum.rb. On ARM and in other places in the x86 backend, this isn't a problem because they inspect the output of instructions which is never replaced.
1 parent e60e195 commit bb4761d

1 file changed

Lines changed: 15 additions & 4 deletions

File tree

zjit/src/backend/x86_64/mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ impl Assembler
128128
let mut iterator = self.insns.into_iter().enumerate().peekable();
129129
let mut asm = Assembler::new_with_label_names(take(&mut self.label_names), live_ranges.len());
130130

131+
// When we add news instructions to `asm`, we also create new VRegs not in the old
132+
// assembler. All VRegs with index larger than the old `live_ranges` live in the
133+
// new assembler since all old VRegs are inherited and keep their index.
134+
fn vreg_outlives_insn(vreg_idx: usize, older_live_ranges: &Vec<LiveRange>, new_asm: &Assembler, insn_idx: usize) -> bool {
135+
older_live_ranges
136+
.get(vreg_idx)
137+
.map_or_else(|| new_asm.live_ranges.get(vreg_idx), Some)
138+
.map(|live_range| live_range.end() > insn_idx)
139+
.expect("VReg in old or new assembler")
140+
}
141+
131142
while let Some((index, mut insn)) = iterator.next() {
132143
let is_load = matches!(insn, Insn::Load { .. } | Insn::LoadInto { .. });
133144
let mut opnd_iter = insn.opnd_iter_mut();
@@ -183,7 +194,7 @@ impl Assembler
183194
},
184195
// Instruction output whose live range spans beyond this instruction
185196
(Opnd::VReg { idx, .. }, _) => {
186-
if live_ranges[idx].end() > index {
197+
if vreg_outlives_insn(idx, &live_ranges, &asm, index) {
187198
*left = asm.load(*left);
188199
}
189200
},
@@ -248,7 +259,7 @@ impl Assembler
248259
match opnd {
249260
// Instruction output whose live range spans beyond this instruction
250261
Opnd::VReg { idx, .. } => {
251-
if live_ranges[*idx].end() > index {
262+
if vreg_outlives_insn(*idx, &live_ranges, &asm, index) {
252263
*opnd = asm.load(*opnd);
253264
}
254265
},
@@ -272,7 +283,7 @@ impl Assembler
272283
// If we have an instruction output whose live range
273284
// spans beyond this instruction, we have to load it.
274285
Opnd::VReg { idx, .. } => {
275-
if live_ranges[idx].end() > index {
286+
if vreg_outlives_insn(idx, &live_ranges, &asm, index) {
276287
*truthy = asm.load(*truthy);
277288
}
278289
},
@@ -307,7 +318,7 @@ impl Assembler
307318
// If we have an instruction output whose live range
308319
// spans beyond this instruction, we have to load it.
309320
Opnd::VReg { idx, .. } => {
310-
if live_ranges[idx].end() > index {
321+
if vreg_outlives_insn(idx, &live_ranges, &asm, index) {
311322
*opnd = asm.load(*opnd);
312323
}
313324
},

0 commit comments

Comments
 (0)