Skip to content

Commit 3251792

Browse files
committed
ZJIT: Fix infinite loop from make_equal_to(x,y) where x=y
Sometimes it's convenient to write that `make_equal_to(x, big_decision_tree_to_find_replacement)` where most of the time the decision tree gives something not equal to `x`. Since infinite loops are hard to debug and this condition is easy to check, let's allow it.
1 parent 4eadf03 commit 3251792

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

zjit/src/hir.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,9 @@ impl<T: Copy + Into<usize> + PartialEq> UnionFind<T> {
18451845
if idx.into() >= self.forwarded.len() {
18461846
self.forwarded.resize(idx.into()+1, None);
18471847
}
1848-
self.forwarded[idx.into()] = Some(value);
1848+
if idx != value {
1849+
self.forwarded[idx.into()] = Some(value);
1850+
}
18491851
}
18501852

18511853
/// Find the set representative for `insn`. Perform path compression at the same time to speed
@@ -1874,7 +1876,10 @@ impl<T: Copy + Into<usize> + PartialEq> UnionFind<T> {
18741876
loop {
18751877
match self.at(result) {
18761878
None => return result,
1877-
Some(insn) => result = insn,
1879+
Some(insn) => {
1880+
assert!(result != insn, "cycle detected");
1881+
result = insn;
1882+
}
18781883
}
18791884
}
18801885
}
@@ -8230,6 +8235,13 @@ mod union_find_tests {
82308235
assert_eq!(uf.find(3usize), 4);
82318236
}
82328237

8238+
#[test]
8239+
fn test_find_halts_with_identity_make_equal_to() {
8240+
let mut uf = UnionFind::<usize>::new();
8241+
uf.make_equal_to(0, 0);
8242+
assert_eq!(uf.find(0), 0);
8243+
}
8244+
82338245
#[test]
82348246
fn test_find_returns_transitive_target() {
82358247
let mut uf = UnionFind::new();

0 commit comments

Comments
 (0)