Skip to content

Commit 5974ec7

Browse files
incr.comp.: Serialize and deserialize new DepGraph
1 parent a7428da commit 5974ec7

File tree

11 files changed

+264
-64
lines changed

11 files changed

+264
-64
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 75 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use super::query::DepGraphQuery;
2525
use super::raii;
2626
use super::safe::DepGraphSafe;
2727
use super::edges::{self, DepGraphEdges};
28+
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
29+
use super::prev::PreviousDepGraph;
2830

2931
#[derive(Clone)]
3032
pub struct DepGraph {
@@ -68,6 +70,10 @@ struct DepGraphData {
6870
/// current one anymore.
6971
current: RefCell<CurrentDepGraph>,
7072

73+
/// The dep-graph from the previous compilation session. It contains all
74+
/// nodes and edges as well as all fingerprints of nodes that have them.
75+
previous: PreviousDepGraph,
76+
7177
/// When we load, there may be `.o` files, cached mir, or other such
7278
/// things available to us. If we find that they are not dirty, we
7379
/// load the path to the file storing those work-products here into
@@ -81,19 +87,24 @@ struct DepGraphData {
8187
}
8288

8389
impl DepGraph {
84-
pub fn new(enabled: bool) -> DepGraph {
90+
91+
pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
8592
DepGraph {
86-
data: if enabled {
87-
Some(Rc::new(DepGraphData {
88-
previous_work_products: RefCell::new(FxHashMap()),
89-
work_products: RefCell::new(FxHashMap()),
90-
edges: RefCell::new(DepGraphEdges::new()),
91-
dep_node_debug: RefCell::new(FxHashMap()),
92-
current: RefCell::new(CurrentDepGraph::new()),
93-
}))
94-
} else {
95-
None
96-
},
93+
data: Some(Rc::new(DepGraphData {
94+
previous_work_products: RefCell::new(FxHashMap()),
95+
work_products: RefCell::new(FxHashMap()),
96+
edges: RefCell::new(DepGraphEdges::new()),
97+
dep_node_debug: RefCell::new(FxHashMap()),
98+
current: RefCell::new(CurrentDepGraph::new()),
99+
previous: prev_graph,
100+
})),
101+
fingerprints: Rc::new(RefCell::new(FxHashMap())),
102+
}
103+
}
104+
105+
pub fn new_disabled() -> DepGraph {
106+
DepGraph {
107+
data: None,
97108
fingerprints: Rc::new(RefCell::new(FxHashMap())),
98109
}
99110
}
@@ -231,7 +242,16 @@ impl DepGraph {
231242
pub fn read(&self, v: DepNode) {
232243
if let Some(ref data) = self.data {
233244
data.edges.borrow_mut().read(v);
234-
data.current.borrow_mut().read(v);
245+
246+
let mut current = data.current.borrow_mut();
247+
debug_assert!(current.node_to_node_index.contains_key(&v),
248+
"DepKind {:?} should be pre-allocated but isn't.",
249+
v.kind);
250+
if let Some(&dep_node_index_new) = current.node_to_node_index.get(&v) {
251+
current.read_index(dep_node_index_new);
252+
} else {
253+
bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
254+
}
235255
}
236256
}
237257

@@ -254,22 +274,12 @@ impl DepGraph {
254274
self.data.as_ref().unwrap().edges.borrow_mut().add_node(node);
255275
}
256276

257-
pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
258-
if let Some(ref data) = self.data {
259-
let dep_node_index_legacy = data.edges.borrow_mut().add_node(node);
260-
let dep_node_index_new = data.current.borrow_mut()
261-
.alloc_node(node, Vec::new());
262-
DepNodeIndex {
263-
legacy: dep_node_index_legacy,
264-
new: dep_node_index_new,
265-
}
266-
} else {
267-
DepNodeIndex::INVALID
268-
}
277+
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
278+
self.fingerprints.borrow()[dep_node]
269279
}
270280

271-
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
272-
self.fingerprints.borrow().get(dep_node).cloned()
281+
pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
282+
self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
273283
}
274284

275285
/// Indicates that a previous work product exists for `v`. This is
@@ -338,6 +348,44 @@ impl DepGraph {
338348
pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
339349
self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned())
340350
}
351+
352+
pub fn serialize(&self) -> SerializedDepGraph {
353+
let fingerprints = self.fingerprints.borrow();
354+
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
355+
356+
let nodes: IndexVec<_, _> = current_dep_graph.nodes.iter().map(|dep_node| {
357+
let fingerprint = fingerprints.get(dep_node)
358+
.cloned()
359+
.unwrap_or(Fingerprint::zero());
360+
(*dep_node, fingerprint)
361+
}).collect();
362+
363+
let total_edge_count: usize = current_dep_graph.edges.iter()
364+
.map(|v| v.len())
365+
.sum();
366+
367+
let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
368+
let mut edge_list_data = Vec::with_capacity(total_edge_count);
369+
370+
for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() {
371+
let start = edge_list_data.len() as u32;
372+
// This should really just be a memcpy :/
373+
edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index)));
374+
let end = edge_list_data.len() as u32;
375+
376+
debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
377+
edge_list_indices.push((start, end));
378+
}
379+
380+
debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
381+
debug_assert_eq!(edge_list_data.len(), total_edge_count);
382+
383+
SerializedDepGraph {
384+
nodes,
385+
edge_list_indices,
386+
edge_list_data,
387+
}
388+
}
341389
}
342390

343391
/// A "work product" is an intermediate result that we save into the
@@ -478,11 +526,6 @@ impl CurrentDepGraph {
478526
}
479527
}
480528

481-
fn read(&mut self, source: DepNode) {
482-
let dep_node_index = self.maybe_alloc_node(source);
483-
self.read_index(dep_node_index);
484-
}
485-
486529
fn read_index(&mut self, source: DepNodeIndexNew) {
487530
match self.task_stack.last_mut() {
488531
Some(&mut OpenTask::Regular {
@@ -521,27 +564,6 @@ impl CurrentDepGraph {
521564
self.edges.push(edges);
522565
dep_node_index
523566
}
524-
525-
fn maybe_alloc_node(&mut self,
526-
dep_node: DepNode)
527-
-> DepNodeIndexNew {
528-
debug_assert_eq!(self.edges.len(), self.nodes.len());
529-
debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
530-
531-
let CurrentDepGraph {
532-
ref mut node_to_node_index,
533-
ref mut nodes,
534-
ref mut edges,
535-
..
536-
} = *self;
537-
538-
*node_to_node_index.entry(dep_node).or_insert_with(|| {
539-
let next_id = nodes.len();
540-
nodes.push(dep_node);
541-
edges.push(Vec::new());
542-
DepNodeIndexNew::new(next_id)
543-
})
544-
}
545567
}
546568

547569
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]

src/librustc/dep_graph/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,17 @@ mod dep_node;
1313
mod dep_tracking_map;
1414
mod edges;
1515
mod graph;
16+
mod prev;
1617
mod query;
1718
mod raii;
1819
mod safe;
20+
mod serialized;
1921

2022
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
21-
pub use self::dep_node::DepNode;
22-
pub use self::dep_node::WorkProductId;
23-
pub use self::graph::DepGraph;
24-
pub use self::graph::WorkProduct;
25-
pub use self::graph::DepNodeIndex;
23+
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId};
24+
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex};
25+
pub use self::prev::PreviousDepGraph;
2626
pub use self::query::DepGraphQuery;
2727
pub use self::safe::AssertDepGraphSafe;
2828
pub use self::safe::DepGraphSafe;
29-
30-
pub use self::dep_node::{DepKind, DepConstructor};
29+
pub use self::serialized::SerializedDepGraph;

src/librustc/dep_graph/prev.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2017 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+
use ich::Fingerprint;
12+
use rustc_data_structures::fx::FxHashMap;
13+
use super::dep_node::DepNode;
14+
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
15+
16+
#[derive(Debug, RustcEncodable, RustcDecodable)]
17+
pub struct PreviousDepGraph {
18+
data: SerializedDepGraph,
19+
index: FxHashMap<DepNode, SerializedDepNodeIndex>,
20+
}
21+
22+
impl PreviousDepGraph {
23+
pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
24+
let index: FxHashMap<_, _> = data.nodes
25+
.iter_enumerated()
26+
.map(|(idx, &(dep_node, _))| (dep_node, idx))
27+
.collect();
28+
PreviousDepGraph { data, index }
29+
}
30+
31+
pub fn with_edges_from<F>(&self, dep_node: &DepNode, mut f: F)
32+
where
33+
F: FnMut(&(DepNode, Fingerprint)),
34+
{
35+
let node_index = self.index[dep_node];
36+
self.data
37+
.edge_targets_from(node_index)
38+
.into_iter()
39+
.for_each(|&index| f(&self.data.nodes[index]));
40+
}
41+
42+
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
43+
let node_index = self.index[dep_node];
44+
self.data.nodes[node_index].1
45+
}
46+
}

src/librustc/dep_graph/serialized.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2017 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+
//! The data that we will serialize and deserialize.
12+
13+
use dep_graph::DepNode;
14+
use ich::Fingerprint;
15+
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
16+
17+
/// The index of a DepNode in the SerializedDepGraph::nodes array.
18+
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug,
19+
RustcEncodable, RustcDecodable)]
20+
pub struct SerializedDepNodeIndex(pub u32);
21+
22+
impl SerializedDepNodeIndex {
23+
#[inline]
24+
pub fn new(idx: usize) -> SerializedDepNodeIndex {
25+
assert!(idx <= ::std::u32::MAX as usize);
26+
SerializedDepNodeIndex(idx as u32)
27+
}
28+
}
29+
30+
impl Idx for SerializedDepNodeIndex {
31+
#[inline]
32+
fn new(idx: usize) -> Self {
33+
assert!(idx <= ::std::u32::MAX as usize);
34+
SerializedDepNodeIndex(idx as u32)
35+
}
36+
37+
#[inline]
38+
fn index(self) -> usize {
39+
self.0 as usize
40+
}
41+
}
42+
43+
/// Data for use when recompiling the **current crate**.
44+
#[derive(Debug, RustcEncodable, RustcDecodable)]
45+
pub struct SerializedDepGraph {
46+
/// The set of all DepNodes in the graph
47+
pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>,
48+
/// For each DepNode, stores the list of edges originating from that
49+
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
50+
/// which holds the actual DepNodeIndices of the target nodes.
51+
pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
52+
/// A flattened list of all edge targets in the graph. Edge sources are
53+
/// implicit in edge_list_indices.
54+
pub edge_list_data: Vec<SerializedDepNodeIndex>,
55+
}
56+
57+
impl SerializedDepGraph {
58+
59+
pub fn new() -> SerializedDepGraph {
60+
SerializedDepGraph {
61+
nodes: IndexVec::new(),
62+
edge_list_indices: IndexVec::new(),
63+
edge_list_data: Vec::new(),
64+
}
65+
}
66+
67+
pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] {
68+
let targets = self.edge_list_indices[source];
69+
&self.edge_list_data[targets.0 as usize..targets.1 as usize]
70+
}
71+
}

src/librustc_driver/driver.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,16 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
643643
&crate_name,
644644
&disambiguator.as_str(),
645645
);
646-
let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
646+
647+
let dep_graph = if sess.opts.build_dep_graph() {
648+
let prev_dep_graph = time(time_passes, "load prev dep-graph (new)", || {
649+
rustc_incremental::load_dep_graph_new(sess)
650+
});
651+
652+
DepGraph::new(prev_dep_graph)
653+
} else {
654+
DepGraph::new_disabled()
655+
};
647656

648657
time(time_passes, "recursion limit", || {
649658
middle::recursion_limit::update_limits(sess, &krate);
@@ -713,7 +722,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
713722
// item, much like we do for macro expansion. In other words, the hash reflects not just
714723
// its contents but the results of name resolution on those contents. Hopefully we'll push
715724
// this back at some point.
716-
let _ignore = dep_graph.in_ignore();
717725
let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
718726
let resolver_arenas = Resolver::arenas();
719727
let mut resolver = Resolver::new(sess,

src/librustc_incremental/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod persist;
3232

3333
pub use assert_dep_graph::assert_dep_graph;
3434
pub use persist::load_dep_graph;
35+
pub use persist::load_dep_graph_new;
3536
pub use persist::save_dep_graph;
3637
pub use persist::save_trans_partition;
3738
pub use persist::save_work_products;

src/librustc_incremental/persist/fs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ use std::__rand::{thread_rng, Rng};
132132

133133
const LOCK_FILE_EXT: &'static str = ".lock";
134134
const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
135+
const DEP_GRAPH_NEW_FILENAME: &'static str = "dep-graph-new.bin";
135136
const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin";
136137
const METADATA_HASHES_FILENAME: &'static str = "metadata.bin";
137138

@@ -145,6 +146,10 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf {
145146
in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
146147
}
147148

149+
pub fn dep_graph_path_new(sess: &Session) -> PathBuf {
150+
in_incr_comp_dir_sess(sess, DEP_GRAPH_NEW_FILENAME)
151+
}
152+
148153
pub fn work_products_path(sess: &Session) -> PathBuf {
149154
in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)
150155
}

0 commit comments

Comments
 (0)