mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
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:
parent
ffe52882ed
commit
af72a70ee2
@ -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>(
|
||||||
|
Loading…
Reference in New Issue
Block a user