Skip to content

Commit 0e97240

Browse files
committed
isolate predecessor computation
The new `Predecessors` type computes a set of interesting targets and their HIR predecessors, and discards everything in between.
1 parent 82b6dc2 commit 0e97240

File tree

4 files changed

+121
-18
lines changed

4 files changed

+121
-18
lines changed

src/librustc_data_structures/bitvec.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ impl BitVector {
2222
BitVector { data: vec![0; num_words] }
2323
}
2424

25+
pub fn clear(&mut self) {
26+
for p in &mut self.data {
27+
*p = 0;
28+
}
29+
}
30+
2531
pub fn contains(&self, bit: usize) -> bool {
2632
let (word, mask) = word_mask(bit);
2733
(self.data[word] & mask) != 0

src/librustc_data_structures/graph/mod.rs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,7 @@ impl<N: Debug, E: Debug> Graph<N, E> {
296296
start: NodeIndex,
297297
direction: Direction)
298298
-> DepthFirstTraversal<'a, N, E> {
299-
DepthFirstTraversal {
300-
graph: self,
301-
stack: vec![start],
302-
visited: BitVector::new(self.nodes.len()),
303-
direction: direction,
304-
}
299+
DepthFirstTraversal::with_start_node(self, start, direction)
305300
}
306301
}
307302

@@ -378,26 +373,57 @@ pub struct DepthFirstTraversal<'g, N: 'g, E: 'g> {
378373
direction: Direction,
379374
}
380375

376+
impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
377+
pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
378+
let visited = BitVector::new(graph.len_nodes());
379+
DepthFirstTraversal {
380+
graph: graph,
381+
stack: vec![],
382+
visited: visited,
383+
direction: direction
384+
}
385+
}
386+
387+
pub fn with_start_node(graph: &'g Graph<N, E>,
388+
start_node: NodeIndex,
389+
direction: Direction)
390+
-> Self {
391+
let mut visited = BitVector::new(graph.len_nodes());
392+
visited.insert(start_node.node_id());
393+
DepthFirstTraversal {
394+
graph: graph,
395+
stack: vec![start_node],
396+
visited: visited,
397+
direction: direction
398+
}
399+
}
400+
401+
pub fn reset(&mut self, start_node: NodeIndex) {
402+
self.stack.truncate(0);
403+
self.stack.push(start_node);
404+
self.visited.clear();
405+
self.visited.insert(start_node.node_id());
406+
}
407+
408+
fn visit(&mut self, node: NodeIndex) {
409+
if self.visited.insert(node.node_id()) {
410+
self.stack.push(node);
411+
}
412+
}
413+
}
414+
381415
impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
382416
type Item = NodeIndex;
383417

384418
fn next(&mut self) -> Option<NodeIndex> {
385-
while let Some(idx) = self.stack.pop() {
386-
if !self.visited.insert(idx.node_id()) {
387-
continue;
388-
}
389-
419+
let next = self.stack.pop();
420+
if let Some(idx) = next {
390421
for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
391422
let target = edge.source_or_target(self.direction);
392-
if !self.visited.contains(target.node_id()) {
393-
self.stack.push(target);
394-
}
423+
self.visit(target);
395424
}
396-
397-
return Some(idx);
398425
}
399-
400-
return None;
426+
next
401427
}
402428
}
403429

src/librustc_incremental/persist/hash.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
3939
}
4040
}
4141

42+
pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
43+
match *dep_node {
44+
DepNode::Hir(_) => true,
45+
DepNode::MetaData(def_id) => !def_id.is_local(),
46+
_ => false,
47+
}
48+
}
49+
4250
pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<(DefId, u64)> {
4351
match *dep_node {
4452
// HIR nodes (which always come from our crate) are an input:
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use rustc::dep_graph::{DepGraphQuery, DepNode};
2+
use rustc::hir::def_id::DefId;
3+
use rustc_data_structures::fnv::FnvHashMap;
4+
use rustc_data_structures::graph::{DepthFirstTraversal, INCOMING, NodeIndex};
5+
6+
use super::hash::*;
7+
8+
/// A data-structure that makes it easy to enumerate the hashable
9+
/// predecessors of any given dep-node.
10+
pub struct Predecessors<'query> {
11+
// - Keys: dep-nodes that may have work-products, output meta-data
12+
// nodes.
13+
// - Values: transitive predecessors of the key that are hashable
14+
// (e.g., HIR nodes, input meta-data nodes)
15+
pub inputs: FnvHashMap<&'query DepNode<DefId>, Vec<&'query DepNode<DefId>>>,
16+
17+
// - Keys: some hashable node
18+
// - Values: the hash thereof
19+
pub hashes: FnvHashMap<&'query DepNode<DefId>, u64>,
20+
}
21+
22+
impl<'q> Predecessors<'q> {
23+
pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
24+
// Find nodes for which we want to know the full set of preds
25+
let mut dfs = DepthFirstTraversal::new(&query.graph, INCOMING);
26+
let all_nodes = query.graph.all_nodes();
27+
let tcx = hcx.tcx;
28+
29+
let inputs: FnvHashMap<_, _> = all_nodes.iter()
30+
.enumerate()
31+
.filter(|&(_, node)| match node.data {
32+
DepNode::WorkProduct(_) => true,
33+
DepNode::MetaData(ref def_id) => def_id.is_local(),
34+
35+
// if -Z query-dep-graph is passed, save more extended data
36+
// to enable better unit testing
37+
DepNode::TypeckItemBody(_) |
38+
DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph,
39+
40+
_ => false,
41+
})
42+
.map(|(node_index, node)| {
43+
dfs.reset(NodeIndex(node_index));
44+
let inputs: Vec<_> = dfs.by_ref()
45+
.map(|i| &all_nodes[i.node_id()].data)
46+
.filter(|d| HashContext::is_hashable(d))
47+
.collect();
48+
(&node.data, inputs)
49+
})
50+
.collect();
51+
52+
let mut hashes = FnvHashMap();
53+
for input in inputs.values().flat_map(|v| v.iter().cloned()) {
54+
hashes.entry(input)
55+
.or_insert_with(|| hcx.hash(input).unwrap().1);
56+
}
57+
58+
Predecessors {
59+
inputs: inputs,
60+
hashes: hashes,
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)