Skip to content

Commit 90d1dc7

Browse files
committed
Only store changed dep nodes
1 parent c3e5603 commit 90d1dc7

File tree

8 files changed

+414
-300
lines changed

8 files changed

+414
-300
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 245 additions & 198 deletions
Large diffs are not rendered by default.

src/librustc/dep_graph/prev.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use crate::ich::Fingerprint;
22
use rustc_data_structures::fx::FxHashMap;
33
use rustc_data_structures::indexed_vec::IndexVec;
44
use super::dep_node::DepNode;
5+
use super::graph::DepNodeState;
56
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
67

7-
#[derive(Debug, RustcEncodable, RustcDecodable, Default)]
8+
#[derive(Debug, /*RustcEncodable, RustcDecodable,*/ Default)]
89
pub struct PreviousDepGraph {
910
/// Maps from dep nodes to their previous index, if any.
1011
index: FxHashMap<DepNode, SerializedDepNodeIndex>,
@@ -20,29 +21,35 @@ pub struct PreviousDepGraph {
2021
/// A flattened list of all edge targets in the graph. Edge sources are
2122
/// implicit in edge_list_indices.
2223
edge_list_data: Vec<SerializedDepNodeIndex>,
24+
/// A set of nodes which are no longer valid.
25+
pub(super) state: IndexVec<SerializedDepNodeIndex, DepNodeState>,
2326
}
2427

2528
impl PreviousDepGraph {
2629
pub fn new(graph: SerializedDepGraph) -> PreviousDepGraph {
2730
let index: FxHashMap<_, _> = graph.nodes
2831
.iter_enumerated()
29-
.map(|(idx, dep_node)| (dep_node.node, idx))
32+
.map(|(idx, dep_node)| {
33+
(dep_node.node, SerializedDepNodeIndex::from_u32(idx.as_u32()))
34+
})
3035
.collect();
3136

3237
let fingerprints: IndexVec<SerializedDepNodeIndex, _> =
3338
graph.nodes.iter().map(|d| d.fingerprint).collect();
3439
let nodes: IndexVec<SerializedDepNodeIndex, _> =
3540
graph.nodes.iter().map(|d| d.node).collect();
3641

37-
let total_edge_count: usize = graph.nodes.iter().map(|d| d.deps.len()).sum();
42+
let total_edge_count: usize = graph.nodes.iter().map(|d| d.edges.len()).sum();
3843

3944
let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
4045
let mut edge_list_data = Vec::with_capacity(total_edge_count);
4146

4247
for (current_dep_node_index, edges) in graph.nodes.iter_enumerated()
43-
.map(|(i, d)| (i, &d.deps)) {
48+
.map(|(i, d)| (i, &d.edges)) {
4449
let start = edge_list_data.len() as u32;
45-
edge_list_data.extend(edges.iter().cloned());
50+
edge_list_data.extend(edges.iter().map(|i| {
51+
SerializedDepNodeIndex::from_u32(i.as_u32())
52+
}));
4653
let end = edge_list_data.len() as u32;
4754

4855
debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
@@ -58,6 +65,7 @@ impl PreviousDepGraph {
5865
edge_list_indices,
5966
edge_list_data,
6067
index,
68+
state: graph.state.convert_index_type(),
6169
}
6270
}
6371

src/librustc/dep_graph/serialized.rs

Lines changed: 99 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,82 +3,100 @@ use rustc_data_structures::sync::Lrc;
33
use rustc_data_structures::{unlikely, cold_path};
44
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
55
use rustc_serialize::opaque;
6-
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
6+
use rustc_serialize::{Decodable, Encodable};
77
use std::mem;
88
use std::fs::File;
99
use std::io::Write;
10-
use super::graph::DepNodeData;
11-
use crate::dep_graph::DepNode;
12-
use crate::ich::Fingerprint;
10+
use super::graph::{DepNodeData, DepNodeIndex, DepNodeState};
1311

1412
newtype_index! {
1513
pub struct SerializedDepNodeIndex { .. }
1614
}
1715

18-
/// Data for use when recompiling the **current crate**.
16+
impl SerializedDepNodeIndex {
17+
pub fn current(self) -> DepNodeIndex {
18+
DepNodeIndex::from_u32(self.as_u32())
19+
}
20+
}
21+
1922
#[derive(Debug, Default)]
2023
pub struct SerializedDepGraph {
21-
pub nodes: IndexVec<SerializedDepNodeIndex, SerializedNode>,
24+
pub(super) nodes: IndexVec<DepNodeIndex, DepNodeData>,
25+
pub(super) state: IndexVec<DepNodeIndex, DepNodeState>,
2226
}
2327

24-
impl Decodable for SerializedDepGraph {
25-
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
28+
impl SerializedDepGraph {
29+
pub fn decode(d: &mut opaque::Decoder<'_>) -> Result<Self, String> {
2630
let mut nodes = IndexVec::new();
31+
let mut invalidated_list = Vec::new();
2732
loop {
28-
let count = d.read_usize()?;
29-
if count == 0 {
33+
if d.position() == d.data.len() {
3034
break;
3135
}
32-
for _ in 0..count {
33-
nodes.push(SerializedNode::decode(d)?);
36+
match Action::decode(d)? {
37+
Action::NewNodes(new_nodes) => {
38+
nodes.extend(new_nodes);
39+
}
40+
Action::UpdateNodes(changed) => {
41+
for (i, data) in changed {
42+
nodes[i] = data;
43+
}
44+
}
45+
Action::InvalidateNodes(nodes) => {
46+
invalidated_list.extend(nodes);
47+
}
3448
}
3549
}
50+
let mut state: IndexVec<_, _> = (0..nodes.len()).map(|_| {
51+
DepNodeState::Unknown
52+
}).collect();
53+
for i in invalidated_list {
54+
state[i] = DepNodeState::Invalidated;
55+
}
3656
Ok(SerializedDepGraph {
3757
nodes,
58+
state,
3859
})
3960
}
4061
}
4162

42-
#[derive(Debug, RustcDecodable)]
43-
pub struct SerializedNode {
44-
pub node: DepNode,
45-
pub deps: Vec<SerializedDepNodeIndex>,
46-
pub fingerprint: Fingerprint,
63+
#[derive(Debug, RustcEncodable, RustcDecodable)]
64+
enum Action {
65+
NewNodes(Vec<DepNodeData>),
66+
UpdateNodes(Vec<(DepNodeIndex, DepNodeData)>),
67+
// FIXME: Is this redundant since these nodes will be also be updated?
68+
// Could one of the indirect dependencies of a dep node change its result and
69+
// cause a red node to be incorrectly green again?
70+
// What about nodes which are in an unknown state?
71+
// We must invalidate unknown nodes. Red nodes will have an entry in UpdateNodes
72+
InvalidateNodes(Vec<DepNodeIndex>)
4773
}
4874

4975
struct SerializerWorker {
5076
file: File,
5177
}
5278

5379
impl Worker for SerializerWorker {
54-
type Message = (usize, Vec<DepNodeData>);
80+
type Message = (usize, Action);
5581
type Result = ();
5682

57-
fn message(&mut self, (buffer_size_est, nodes): (usize, Vec<DepNodeData>)) {
58-
let mut encoder = opaque::Encoder::new(Vec::with_capacity(buffer_size_est * 4));
59-
assert!(!nodes.is_empty());
60-
encoder.emit_usize(nodes.len()).ok();
61-
for data in nodes {
62-
data.node.encode(&mut encoder).ok();
63-
data.edges.encode(&mut encoder).ok();
64-
data.fingerprint.encode(&mut encoder).ok();
65-
}
83+
fn message(&mut self, (buffer_size_est, action): (usize, Action)) {
84+
let mut encoder = opaque::Encoder::new(Vec::with_capacity(buffer_size_est * 5));
85+
action.encode(&mut encoder).ok();
6686
self.file.write_all(&encoder.into_inner()).expect("unable to write to temp dep graph");
6787
}
6888

69-
fn complete(mut self) {
70-
let mut encoder = opaque::Encoder::new(Vec::with_capacity(16));
71-
encoder.emit_usize(0).ok();
72-
self.file.write_all(&encoder.into_inner()).expect("unable to write to temp dep graph");
73-
}
89+
fn complete(self) {}
7490
}
7591

7692
const BUFFER_SIZE: usize = 800000;
7793

7894
pub struct Serializer {
7995
worker: Lrc<WorkerExecutor<SerializerWorker>>,
80-
buffer: Vec<DepNodeData>,
81-
buffer_size: usize,
96+
new_buffer: Vec<DepNodeData>,
97+
new_buffer_size: usize,
98+
updated_buffer: Vec<(DepNodeIndex, DepNodeData)>,
99+
updated_buffer_size: usize,
82100
}
83101

84102
impl Serializer {
@@ -87,33 +105,65 @@ impl Serializer {
87105
worker: Lrc::new(WorkerExecutor::new(SerializerWorker {
88106
file,
89107
})),
90-
buffer: Vec::with_capacity(BUFFER_SIZE),
91-
buffer_size: 0,
108+
new_buffer: Vec::with_capacity(BUFFER_SIZE),
109+
new_buffer_size: 0,
110+
updated_buffer: Vec::with_capacity(BUFFER_SIZE),
111+
updated_buffer_size: 0,
112+
}
113+
}
114+
115+
fn flush_new(&mut self) {
116+
let msgs = mem::replace(&mut self.new_buffer, Vec::with_capacity(BUFFER_SIZE));
117+
let buffer_size = self.new_buffer_size;
118+
self.new_buffer_size = 0;
119+
self.worker.message_in_pool((buffer_size, Action::NewNodes(msgs)));
120+
}
121+
122+
#[inline]
123+
pub(super) fn serialize_new(&mut self, data: DepNodeData) {
124+
let edges = data.edges.len();
125+
self.new_buffer.push(data);
126+
self.new_buffer_size += 8 + edges;
127+
if unlikely!(self.new_buffer_size >= BUFFER_SIZE) {
128+
cold_path(|| {
129+
self.flush_new();
130+
})
92131
}
93132
}
94133

95-
fn flush(&mut self) {
96-
let msgs = mem::replace(&mut self.buffer, Vec::with_capacity(BUFFER_SIZE));
97-
let buffer_size = self.buffer_size;
98-
self.buffer_size = 0;
99-
self.worker.message_in_pool((buffer_size, msgs));
134+
fn flush_updated(&mut self) {
135+
let msgs = mem::replace(&mut self.updated_buffer, Vec::with_capacity(BUFFER_SIZE));
136+
let buffer_size = self.updated_buffer_size;
137+
self.updated_buffer_size = 0;
138+
self.worker.message_in_pool((buffer_size, Action::UpdateNodes(msgs)));
100139
}
101140

102141
#[inline]
103-
pub(super) fn serialize(&mut self, data: DepNodeData) {
142+
pub(super) fn serialize_updated(&mut self, index: DepNodeIndex, data: DepNodeData) {
104143
let edges = data.edges.len();
105-
self.buffer.push(data);
106-
self.buffer_size += 8 + edges;
107-
if unlikely!(self.buffer_size >= BUFFER_SIZE) {
144+
self.updated_buffer.push((index, data));
145+
self.updated_buffer_size += 9 + edges;
146+
if unlikely!(self.updated_buffer_size >= BUFFER_SIZE) {
108147
cold_path(|| {
109-
self.flush();
148+
self.flush_updated();
110149
})
111150
}
112151
}
113152

114-
pub fn complete(&mut self) {
115-
if self.buffer.len() > 0 {
116-
self.flush();
153+
pub fn complete(
154+
&mut self,
155+
invalidate: Vec<DepNodeIndex>,
156+
) {
157+
if self.new_buffer.len() > 0 {
158+
self.flush_new();
159+
}
160+
if self.updated_buffer.len() > 0 {
161+
self.flush_updated();
162+
}
163+
if !invalidate.is_empty() {
164+
self.worker.message_in_pool(
165+
(invalidate.len(), Action::InvalidateNodes(invalidate))
166+
);
117167
}
118168
self.worker.complete()
119169
}

src/librustc/ty/query/plumbing.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -546,11 +546,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
546546
// in DepGraph::try_mark_green()
547547
// 2. Two distinct query keys get mapped to the same DepNode
548548
// (see for example #48923)
549-
assert!(!self.dep_graph.dep_node_exists(&dep_node),
550-
"Forcing query with already existing DepNode.\n\
551-
- query-key: {:?}\n\
552-
- dep-node: {:?}",
553-
key, dep_node);
549+
/*debug_assert!(
550+
!self.dep_graph.dep_node_exists(&dep_node),
551+
"Forcing query with already existing DepNode.\n\
552+
- query-key: {:?}\n\
553+
- dep-node: {:?}",
554+
key,
555+
dep_node,
556+
);*/
554557

555558
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
556559
self.sess.profiler(|p| p.start_query(Q::NAME));

src/librustc_codegen_ssa/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,9 +944,9 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
944944
// know that later). If we are not doing LTO, there is only one optimized
945945
// version of each module, so we re-use that.
946946
let dep_node = cgu.codegen_dep_node(tcx);
947-
assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
947+
/*debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
948948
"CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
949-
cgu.name());
949+
cgu.name());*/
950950

951951
if tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() {
952952
// We can re-use either the pre- or the post-thinlto state

src/librustc_incremental/persist/dirty_clean.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
460460
})
461461
}
462462

463-
fn dep_node_str(&self, dep_node: &DepNode) -> String {
463+
fn _dep_node_str(&self, dep_node: &DepNode) -> String {
464464
if let Some(def_id) = dep_node.extract_def_id(self.tcx) {
465465
format!("{:?}({})",
466466
dep_node.kind,
@@ -470,10 +470,10 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
470470
}
471471
}
472472

473-
fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
473+
fn assert_dirty(&self, _item_span: Span, dep_node: DepNode) {
474474
debug!("assert_dirty({:?})", dep_node);
475-
476-
let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
475+
panic!()
476+
/*let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
477477
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
478478
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
479479
@@ -482,13 +482,13 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
482482
self.tcx.sess.span_err(
483483
item_span,
484484
&format!("`{}` should be dirty but is not", dep_node_str));
485-
}
485+
}*/
486486
}
487487

488-
fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
488+
fn assert_clean(&self, _item_span: Span, dep_node: DepNode) {
489489
debug!("assert_clean({:?})", dep_node);
490-
491-
let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
490+
panic!()
491+
/*let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node);
492492
let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index);
493493
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
494494
@@ -497,7 +497,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
497497
self.tcx.sess.span_err(
498498
item_span,
499499
&format!("`{}` should be clean but is not", dep_node_str));
500-
}
500+
}*/
501501
}
502502

503503
fn check_item(&mut self, item_id: hir::HirId, item_span: Span) {

src/librustc_incremental/persist/file_format.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
1212
use std::io::{self, Read};
1313
use std::path::Path;
14-
use std::fs;
14+
use std::fs::{OpenOptions, File};
1515
use std::env;
1616

1717
use rustc::session::config::nightly_options;
@@ -49,13 +49,16 @@ pub fn write_file_header(stream: &mut Encoder) {
4949
/// - Returns `Err(..)` if some kind of IO error occurred while reading the
5050
/// file.
5151
pub fn read_file(report_incremental_info: bool, path: &Path)
52-
-> io::Result<Option<(Vec<u8>, usize)>>
52+
-> io::Result<Option<(Vec<u8>, usize, File)>>
5353
{
5454
if !path.exists() {
5555
return Ok(None);
5656
}
5757

58-
let data = fs::read(path)?;
58+
let mut real_file = OpenOptions::new().read(true).write(true).open(path)?;
59+
let len = real_file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0);
60+
let mut data = Vec::with_capacity(len);
61+
real_file.read_to_end(&mut data)?;
5962

6063
let mut file = io::Cursor::new(data);
6164

@@ -100,7 +103,7 @@ pub fn read_file(report_incremental_info: bool, path: &Path)
100103
}
101104

102105
let post_header_start_pos = file.position() as usize;
103-
Ok(Some((file.into_inner(), post_header_start_pos)))
106+
Ok(Some((file.into_inner(), post_header_start_pos, real_file)))
104107
}
105108

106109
fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &str) {

0 commit comments

Comments
 (0)