Skip to content

Commit 648a8e3

Browse files
authored
Rollup merge of rust-lang#94306 - Mark-Simulacrum:dom-fixups, r=jackh726
Avoid exhausting stack space in dominator compression Doesn't add a test case -- I ended up running into this while playing with the generated example from rust-lang#43578, which we could do with a run-make test (to avoid checking a large code snippet into tree), but I suspect we don't want to wait for it to compile (locally it takes ~14s -- not terrible, but doesn't seem worth it to me). In practice stack space exhaustion is difficult to test for, too, since if we set the bound too low a different call structure above us (e.g., a nearer ensure_sufficient_stack call) would let the test pass even with the old impl, most likely. Locally it seems like this manages to perform approximately equivalently to the recursion, but will run perf to confirm.
2 parents d6ca388 + 4d89292 commit 648a8e3

File tree

1 file changed

+13
-3
lines changed
  • compiler/rustc_data_structures/src/graph/dominators

1 file changed

+13
-3
lines changed

compiler/rustc_data_structures/src/graph/dominators/mod.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,19 @@ fn compress(
241241
v: PreorderIndex,
242242
) {
243243
assert!(is_processed(v, lastlinked));
244-
let u = ancestor[v];
245-
if is_processed(u, lastlinked) {
246-
compress(ancestor, lastlinked, semi, label, u);
244+
// Compute the processed list of ancestors
245+
//
246+
// We use a heap stack here to avoid recursing too deeply, exhausting the
247+
// stack space.
248+
let mut stack: smallvec::SmallVec<[_; 8]> = smallvec::smallvec![v];
249+
let mut u = ancestor[v];
250+
while is_processed(u, lastlinked) {
251+
stack.push(u);
252+
u = ancestor[u];
253+
}
254+
255+
// Then in reverse order, popping the stack
256+
for &[v, u] in stack.array_windows().rev() {
247257
if semi[label[u]] < semi[label[v]] {
248258
label[v] = label[u];
249259
}

0 commit comments

Comments
 (0)