about summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src/graph/iterate/mod.rs
diff options
context:
space:
mode:
authorAndreas Molzer <andreas.molzer@gmx.de>2020-10-31 17:56:13 +0100
committerAndreas Molzer <andreas.molzer@gmx.de>2020-10-31 18:52:00 +0100
commitaf72a70ee27faa85522f7656e042c85ab1ee275e (patch)
tree51bcfa310359132c94a5ab34f669d0c85a96cee7 /compiler/rustc_data_structures/src/graph/iterate/mod.rs
parentffe52882ed79be67344dd6085559e308241e7f60 (diff)
downloadrust-af72a70ee27faa85522f7656e042c85ab1ee275e.tar.gz
rust-af72a70ee27faa85522f7656e042c85ab1ee275e.zip
Move post order walk to iterative approach
The previous recursive approach might overflow the stack when walking a
particularly deep, list-like, graph. In particular, dominator
calculation for borrow checking does such a traversal and very long
functions might lead to a region dependency graph with in this
problematic structure.
Diffstat (limited to 'compiler/rustc_data_structures/src/graph/iterate/mod.rs')
-rw-r--r--compiler/rustc_data_structures/src/graph/iterate/mod.rs25
1 files changed, 20 insertions, 5 deletions
diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
index 5f42d46e285..1634c586316 100644
--- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
@@ -33,16 +33,31 @@ fn post_order_walk<G: DirectedGraph + WithSuccessors + WithNumNodes>(
     result: &mut Vec<G::Node>,
     visited: &mut IndexVec<G::Node, bool>,
 ) {
+    struct PostOrderFrame<Node, Iter> {
+        node: Node,
+        iter: Iter,
+    }
+
     if visited[node] {
         return;
     }
-    visited[node] = true;
 
-    for successor in graph.successors(node) {
-        post_order_walk(graph, successor, result, visited);
-    }
+    let mut stack = vec![PostOrderFrame { node, iter: graph.successors(node) }];
+
+    'recurse: while let Some(frame) = stack.last_mut() {
+        let node = frame.node;
+        visited[node] = true;
 
-    result.push(node);
+        while let Some(successor) = frame.iter.next() {
+            if !visited[successor] {
+                stack.push(PostOrderFrame { node: successor, iter: graph.successors(successor) });
+                continue 'recurse;
+            }
+        }
+
+        let _ = stack.pop();
+        result.push(node);
+    }
 }
 
 pub fn reverse_post_order<G: DirectedGraph + WithSuccessors + WithNumNodes>(