Skip to content

Commit 9a14045

Browse files
committed
Auto merge of #33476 - nikomatsakis:incr-comp-xcrate, r=mw
track incr. comp. dependencies across crates This PR refactors the compiler's incremental compilation hashing so that it can track dependencies across crates. The main bits are: - computing a hash representing the metadata for an item we are emitting - we do this by making `MetaData(X)` be the current task while computing metadata for an item - this naturally registers reads from any tables and things that we read for that purpose - we can then hash all the inputs to those tables - tracking when we access metadata - we do this by registering a read of `MetaData(X)` for each foreign item `X` whose metadata we read - hashing metadata from foreign items - we do this by loading up metadata from a file in the incr. comp. directory - if there is no file, we use the SVH for the entire crate There is one very simple test only at this point. The next PR will be focused on expanding out the tests. Note that this is based on top of #33228 r? @michaelwoerister
2 parents 9743c66 + f860f8b commit 9a14045

File tree

52 files changed

+1037
-370
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1037
-370
lines changed

src/librustc/cfg/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ impl CFG {
6464
}
6565

6666
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
67-
self.graph.depth_traverse(self.entry)
67+
self.graph.depth_traverse(self.entry, graph::OUTGOING)
6868
.any(|idx| self.graph.node_data(idx).id() == id)
6969
}
7070
}

src/librustc/dep_graph/debug.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! Code for debugging the dep-graph.
12+
13+
use super::dep_node::DepNode;
14+
use std::error::Error;
15+
use std::fmt::Debug;
16+
17+
/// A dep-node filter goes from a user-defined string to a query over
18+
/// nodes. Right now the format is like this:
19+
///
20+
/// x & y & z
21+
///
22+
/// where the format-string of the dep-node must contain `x`, `y`, and
23+
/// `z`.
24+
#[derive(Debug)]
25+
pub struct DepNodeFilter {
26+
text: String
27+
}
28+
29+
impl DepNodeFilter {
30+
pub fn new(text: &str) -> Self {
31+
DepNodeFilter {
32+
text: text.trim().to_string()
33+
}
34+
}
35+
36+
/// True if all nodes always pass the filter.
37+
pub fn accepts_all(&self) -> bool {
38+
self.text.is_empty()
39+
}
40+
41+
/// Tests whether `node` meets the filter, returning true if so.
42+
pub fn test<D: Clone + Debug>(&self, node: &DepNode<D>) -> bool {
43+
let debug_str = format!("{:?}", node);
44+
self.text.split("&")
45+
.map(|s| s.trim())
46+
.all(|f| debug_str.contains(f))
47+
}
48+
}
49+
50+
/// A filter like `F -> G` where `F` and `G` are valid dep-node
51+
/// filters. This can be used to test the source/target independently.
52+
pub struct EdgeFilter {
53+
pub source: DepNodeFilter,
54+
pub target: DepNodeFilter,
55+
}
56+
57+
impl EdgeFilter {
58+
pub fn new(test: &str) -> Result<EdgeFilter, Box<Error>> {
59+
let parts: Vec<_> = test.split("->").collect();
60+
if parts.len() != 2 {
61+
Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into())
62+
} else {
63+
Ok(EdgeFilter {
64+
source: DepNodeFilter::new(parts[0]),
65+
target: DepNodeFilter::new(parts[1]),
66+
})
67+
}
68+
}
69+
}

src/librustc/dep_graph/dep_node.rs

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ pub enum DepNode<D: Clone + Debug> {
3232
// Represents the HIR node with the given node-id
3333
Hir(D),
3434

35+
// Represents the metadata for a given HIR node, typically found
36+
// in an extern crate.
37+
MetaData(D),
38+
3539
// Represents different phases in the compiler.
3640
CrateReader,
3741
CollectLanguageItems,
@@ -77,6 +81,7 @@ pub enum DepNode<D: Clone + Debug> {
7781
TransCrateItem(D),
7882
TransInlinedItem(D),
7983
TransWriteMetadata,
84+
LinkBinary,
8085

8186
// Nodes representing bits of computed IR in the tcx. Each shared
8287
// table in the tcx (or elsewhere) maps to one of these
@@ -174,7 +179,9 @@ impl<D: Clone + Debug> DepNode<D> {
174179
LateLintCheck => Some(LateLintCheck),
175180
TransCrate => Some(TransCrate),
176181
TransWriteMetadata => Some(TransWriteMetadata),
182+
LinkBinary => Some(LinkBinary),
177183
Hir(ref d) => op(d).map(Hir),
184+
MetaData(ref d) => op(d).map(MetaData),
178185
CollectItem(ref d) => op(d).map(CollectItem),
179186
CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
180187
CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),

src/librustc/dep_graph/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
pub mod debug;
1112
mod dep_node;
1213
mod dep_tracking_map;
1314
mod edges;
@@ -22,3 +23,4 @@ pub use self::dep_node::DepNode;
2223
pub use self::graph::DepGraph;
2324
pub use self::query::DepGraphQuery;
2425
pub use self::visit::visit_all_items_in_krate;
26+
pub use self::raii::DepTask;

src/librustc/dep_graph/query.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use rustc_data_structures::fnv::FnvHashMap;
12-
use rustc_data_structures::graph::{Graph, NodeIndex};
12+
use rustc_data_structures::graph::{Direction, INCOMING, Graph, NodeIndex, OUTGOING};
1313
use std::fmt::Debug;
1414
use std::hash::Hash;
1515

@@ -63,20 +63,29 @@ impl<D: Clone + Debug + Hash + Eq> DepGraphQuery<D> {
6363
.collect()
6464
}
6565

66-
/// All nodes reachable from `node`. In other words, things that
67-
/// will have to be recomputed if `node` changes.
68-
pub fn transitive_dependents(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
66+
fn reachable_nodes(&self, node: DepNode<D>, direction: Direction) -> Vec<DepNode<D>> {
6967
if let Some(&index) = self.indices.get(&node) {
70-
self.graph.depth_traverse(index)
68+
self.graph.depth_traverse(index, direction)
7169
.map(|s| self.graph.node_data(s).clone())
7270
.collect()
7371
} else {
7472
vec![]
7573
}
7674
}
7775

76+
/// All nodes reachable from `node`. In other words, things that
77+
/// will have to be recomputed if `node` changes.
78+
pub fn transitive_successors(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
79+
self.reachable_nodes(node, OUTGOING)
80+
}
81+
82+
/// All nodes that can reach `node`.
83+
pub fn transitive_predecessors(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
84+
self.reachable_nodes(node, INCOMING)
85+
}
86+
7887
/// Just the outgoing edges from `node`.
79-
pub fn immediate_dependents(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
88+
pub fn immediate_successors(&self, node: DepNode<D>) -> Vec<DepNode<D>> {
8089
if let Some(&index) = self.indices.get(&node) {
8190
self.graph.successor_nodes(index)
8291
.map(|s| self.graph.node_data(s).clone())

src/librustc/dep_graph/thread.rs

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use super::DepGraphQuery;
2828
use super::DepNode;
2929
use super::edges::DepGraphEdges;
3030

31+
#[derive(Debug)]
3132
pub enum DepMessage {
3233
Read(DepNode<DefId>),
3334
Write(DepNode<DefId>),
@@ -117,6 +118,8 @@ impl DepGraphThreadData {
117118
/// the buffer is full, this may swap.)
118119
#[inline]
119120
pub fn enqueue(&self, message: DepMessage) {
121+
debug!("enqueue: {:?} tasks_pushed={}", message, self.tasks_pushed.get());
122+
120123
// Regardless of whether dep graph construction is enabled, we
121124
// still want to check that we always have a valid task on the
122125
// stack when a read/write/etc event occurs.

src/librustc/dep_graph/visit.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
4242
let _task = self.tcx.dep_graph.in_task(task_id);
4343
debug!("Started task {:?}", task_id);
4444
self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
45-
self.visitor.visit_item(i)
45+
self.visitor.visit_item(i);
46+
debug!("Ended task {:?}", task_id);
4647
}
4748
}
4849

src/librustc/hir/lowering.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use hir::map::Definitions;
4545
use hir::map::definitions::DefPathData;
4646
use hir::def_id::{DefIndex, DefId};
4747
use hir::def::{Def, PathResolution};
48+
use session::Session;
4849

4950
use std::collections::BTreeMap;
5051
use std::iter;
@@ -97,8 +98,16 @@ impl Resolver for DummyResolver {
9798
}
9899
}
99100

100-
pub fn lower_crate(krate: &Crate, id_assigner: &NodeIdAssigner, resolver: &mut Resolver)
101+
pub fn lower_crate(sess: &Session,
102+
krate: &Crate,
103+
id_assigner: &NodeIdAssigner,
104+
resolver: &mut Resolver)
101105
-> hir::Crate {
106+
// We're constructing the HIR here; we don't care what we will
107+
// read, since we haven't even constructed the *input* to
108+
// incr. comp. yet.
109+
let _ignore = sess.dep_graph.in_ignore();
110+
102111
LoweringContext {
103112
crate_root: if std_inject::no_core(krate) {
104113
None

src/librustc/hir/map/definitions.rs

+6-31
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ impl DefPath {
8282
let mut data = vec![];
8383
let mut index = Some(start_index);
8484
loop {
85+
debug!("DefPath::make: krate={:?} index={:?}", krate, index);
8586
let p = index.unwrap();
8687
let key = get_key(p);
88+
debug!("DefPath::make: key={:?}", key);
8789
match key.disambiguated_data.data {
8890
DefPathData::CrateRoot => {
8991
assert!(key.parent.is_none());
@@ -178,6 +180,10 @@ impl Definitions {
178180
self.data[index.as_usize()].key.clone()
179181
}
180182

183+
pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
184+
self.key_map.get(&key).cloned()
185+
}
186+
181187
/// Returns the path from the crate root to `index`. The root
182188
/// nodes are not included in the path (i.e., this will be an
183189
/// empty vector for the crate root). For an inlined item, this
@@ -208,37 +214,6 @@ impl Definitions {
208214
}
209215
}
210216

211-
pub fn retrace_path(&self, path: &DefPath) -> Option<DefIndex> {
212-
debug!("retrace_path(path={:?})", path);
213-
214-
// we assume that we only want to retrace paths relative to
215-
// the crate root
216-
assert!(path.is_local());
217-
218-
let root_key = DefKey {
219-
parent: None,
220-
disambiguated_data: DisambiguatedDefPathData {
221-
data: DefPathData::CrateRoot,
222-
disambiguator: 0,
223-
},
224-
};
225-
let root_id = self.key_map[&root_key];
226-
227-
debug!("retrace_path: root_id={:?}", root_id);
228-
229-
let mut id = root_id;
230-
for data in &path.data {
231-
let key = DefKey { parent: Some(id), disambiguated_data: data.clone() };
232-
debug!("key = {:?}", key);
233-
id = match self.key_map.get(&key) {
234-
Some(&id) => id,
235-
None => return None
236-
};
237-
}
238-
239-
Some(id)
240-
}
241-
242217
pub fn create_def_with_parent(&mut self,
243218
parent: Option<DefIndex>,
244219
node_id: ast::NodeId,

src/librustc/hir/map/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use dep_graph::{DepGraph, DepNode};
1919

2020
use middle::cstore::InlinedItem;
2121
use middle::cstore::InlinedItem as II;
22-
use hir::def_id::{CRATE_DEF_INDEX, DefId};
22+
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
2323

2424
use syntax::abi::Abi;
2525
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
@@ -160,10 +160,10 @@ pub struct Forest {
160160
}
161161

162162
impl Forest {
163-
pub fn new(krate: Crate, dep_graph: DepGraph) -> Forest {
163+
pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest {
164164
Forest {
165165
krate: krate,
166-
dep_graph: dep_graph,
166+
dep_graph: dep_graph.clone(),
167167
inlined_items: TypedArena::new()
168168
}
169169
}
@@ -285,9 +285,8 @@ impl<'ast> Map<'ast> {
285285
self.definitions.borrow().def_path(def_id.index)
286286
}
287287

288-
pub fn retrace_path(&self, path: &DefPath) -> Option<DefId> {
289-
self.definitions.borrow().retrace_path(path)
290-
.map(DefId::local)
288+
pub fn def_index_for_def_key(&self, def_key: DefKey) -> Option<DefIndex> {
289+
self.definitions.borrow().def_index_for_def_key(def_key)
291290
}
292291

293292
pub fn local_def_id(&self, node: NodeId) -> DefId {

0 commit comments

Comments
 (0)