about summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src/graph
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2022-02-23 10:31:26 -0500
committerMark Rousskov <mark.simulacrum@gmail.com>2022-02-23 16:07:56 -0500
commit4d89292785653e399512d85f95a9870836ec9632 (patch)
tree89dc0f6631b027fd47d71b31332aac521d237a43 /compiler/rustc_data_structures/src/graph
parentc651ba8a542c7d89b271efbf024a31091c824f4b (diff)
downloadrust-4d89292785653e399512d85f95a9870836ec9632.tar.gz
rust-4d89292785653e399512d85f95a9870836ec9632.zip
Avoid exhausting stack space in dominator compression
Diffstat (limited to 'compiler/rustc_data_structures/src/graph')
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs16
1 files changed, 13 insertions, 3 deletions
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 0d2ae115cb0..00913a483db 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -241,9 +241,19 @@ fn compress(
     v: PreorderIndex,
 ) {
     assert!(is_processed(v, lastlinked));
-    let u = ancestor[v];
-    if is_processed(u, lastlinked) {
-        compress(ancestor, lastlinked, semi, label, u);
+    // Compute the processed list of ancestors
+    //
+    // We use a heap stack here to avoid recursing too deeply, exhausting the
+    // stack space.
+    let mut stack: smallvec::SmallVec<[_; 8]> = smallvec::smallvec![v];
+    let mut u = ancestor[v];
+    while is_processed(u, lastlinked) {
+        stack.push(u);
+        u = ancestor[u];
+    }
+
+    // Then in reverse order, popping the stack
+    for &[v, u] in stack.array_windows().rev() {
         if semi[label[u]] < semi[label[v]] {
             label[v] = label[u];
         }