Skip to content

Commit 21cb1c9

Browse files
committed
ZJIT: x86: split: Fix live ranges index-out-of-range panic
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 71b4693 commit 21cb1c9

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

zjit/src/backend/x86_64/mod.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ impl Assembler
148148
};
149149
}
150150

151+
// When we split an operand, we can create a new VReg not in `live_ranges`.
152+
// So when we see a VReg with out-of-range index, it's created from splitting
153+
// from the loop above and we know it doesn't outlive the current instruction.
154+
let vreg_outlives_insn = |vreg_idx| {
155+
live_ranges
156+
.get(vreg_idx)
157+
.map_or(false, |live_range: &LiveRange| live_range.end() > index)
158+
};
159+
151160
// We are replacing instructions here so we know they are already
152161
// being used. It is okay not to use their output here.
153162
#[allow(unused_must_use)]
@@ -183,7 +192,7 @@ impl Assembler
183192
},
184193
// Instruction output whose live range spans beyond this instruction
185194
(Opnd::VReg { idx, .. }, _) => {
186-
if live_ranges[idx].end() > index {
195+
if vreg_outlives_insn(idx) {
187196
*left = asm.load(*left);
188197
}
189198
},
@@ -248,7 +257,7 @@ impl Assembler
248257
match opnd {
249258
// Instruction output whose live range spans beyond this instruction
250259
Opnd::VReg { idx, .. } => {
251-
if live_ranges[*idx].end() > index {
260+
if vreg_outlives_insn(*idx) {
252261
*opnd = asm.load(*opnd);
253262
}
254263
},
@@ -272,7 +281,7 @@ impl Assembler
272281
// If we have an instruction output whose live range
273282
// spans beyond this instruction, we have to load it.
274283
Opnd::VReg { idx, .. } => {
275-
if live_ranges[idx].end() > index {
284+
if vreg_outlives_insn(idx) {
276285
*truthy = asm.load(*truthy);
277286
}
278287
},
@@ -307,7 +316,7 @@ impl Assembler
307316
// If we have an instruction output whose live range
308317
// spans beyond this instruction, we have to load it.
309318
Opnd::VReg { idx, .. } => {
310-
if live_ranges[idx].end() > index {
319+
if vreg_outlives_insn(idx) {
311320
*opnd = asm.load(*opnd);
312321
}
313322
},

0 commit comments

Comments
 (0)