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.
This commit is contained in:
Andreas Molzer 2020-10-31 17:56:13 +01:00
parent ffe52882ed
commit af72a70ee2

View File

@ -33,16 +33,31 @@ fn post_order_walk<G: DirectedGraph + WithSuccessors + WithNumNodes>(
result: &mut Vec<G::Node>, result: &mut Vec<G::Node>,
visited: &mut IndexVec<G::Node, bool>, visited: &mut IndexVec<G::Node, bool>,
) { ) {
struct PostOrderFrame<Node, Iter> {
node: Node,
iter: Iter,
}
if visited[node] { if visited[node] {
return; return;
} }
visited[node] = true;
for successor in graph.successors(node) { let mut stack = vec![PostOrderFrame { node, iter: graph.successors(node) }];
post_order_walk(graph, successor, result, visited);
'recurse: while let Some(frame) = stack.last_mut() {
let node = frame.node;
visited[node] = true;
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);
} }
result.push(node);
} }
pub fn reverse_post_order<G: DirectedGraph + WithSuccessors + WithNumNodes>( pub fn reverse_post_order<G: DirectedGraph + WithSuccessors + WithNumNodes>(