Skip to content

Commit 2dc8bd4

Browse files
committed
wip
1 parent 4f7895f commit 2dc8bd4

File tree

12 files changed

+324
-188
lines changed

12 files changed

+324
-188
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 134 additions & 111 deletions
Large diffs are not rendered by default.

src/librustc/dep_graph/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ pub mod cgu_reuse_tracker;
1111
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
1212
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, RecoverKey, label_strs};
1313
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result};
14-
pub use self::graph::{DepGraphArgs, WorkProductFileKind};
14+
pub use self::graph::{DepGraphArgs, WorkProductFileKind, ReconstructedDepGraph};
1515
pub use self::prev::PreviousDepGraph;
1616
pub use self::query::DepGraphQuery;
1717
pub use self::safe::AssertDepGraphSafe;
1818
pub use self::safe::DepGraphSafe;
19-
pub use self::serialized::{DecodedDepGraph, decode_dep_graph, gc_dep_graph};
19+
pub use self::serialized::{CompletedDepGraph, DecodedDepGraph, decode_dep_graph, gc_dep_graph};

src/librustc/dep_graph/query.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@ pub struct DepGraphQuery {
1111
}
1212

1313
impl DepGraphQuery {
14-
pub fn new(nodes: &[DepNode],
15-
edges: &[(DepNode, DepNode)])
16-
-> DepGraphQuery {
17-
let mut graph = Graph::with_capacity(nodes.len(), edges.len());
14+
pub fn new(
15+
nodes: impl Iterator<Item = DepNode>,
16+
edges: impl Iterator<Item = (DepNode, DepNode)>,
17+
) -> DepGraphQuery {
18+
let mut graph = Graph::with_capacity(nodes.size_hint().0, edges.size_hint().0);
1819
let mut indices = FxHashMap::default();
1920
for node in nodes {
2021
indices.insert(node.clone(), graph.add_node(node.clone()));
2122
}
2223

23-
for &(ref source, ref target) in edges {
24-
let source = indices[source];
25-
let target = indices[target];
24+
for (source, target) in edges {
25+
let source = indices[&source];
26+
let target = indices[&target];
2627
graph.add_edge(source, target, ());
2728
}
2829

src/librustc/dep_graph/serialized.rs

Lines changed: 106 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub fn gc_dep_graph(
8888
result: &DecodedDepGraph,
8989
file: &mut File,
9090
) {
91-
let (nodes, edges) = time_ext(time_passes, None, "read dep-graph positions", || {
91+
let (nodes, edges) = time_ext(time_passes, None, "read dep-graph positions", || {
9292
read_dep_graph_positions(d, result).unwrap()
9393
});
9494

@@ -150,32 +150,100 @@ pub fn gc_dep_graph(
150150
}
151151
}
152152

153+
/// A simpler dep graph used for debugging and testing purposes.
154+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Default)]
155+
pub struct DepGraphModel {
156+
pub data: FxHashMap<DepNodeIndex, DepNodeData>,
157+
}
158+
159+
impl DepGraphModel {
160+
fn apply(&mut self, action: &Action) {
161+
match action {
162+
Action::UpdateNodes(nodes) => {
163+
for n in nodes {
164+
self.data
165+
.entry(n.0)
166+
.or_insert_with(|| panic!()).edges = n.1.edges.clone();
167+
}
168+
}
169+
Action::NewNodes(nodes) => {
170+
for n in nodes {
171+
assert!(self.data.insert(n.0, n.1.clone()).is_none());
172+
}
173+
}
174+
Action::InvalidateNodes(nodes) => {
175+
for n in nodes {
176+
assert!(self.data.remove(&n).is_some());
177+
}
178+
},
179+
}
180+
}
181+
}
182+
183+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Default)]
184+
pub struct CompletedDepGraph {
185+
/// Hashes of the results of dep nodes
186+
pub(super) results: IndexVec<DepNodeIndex, Fingerprint>,
187+
/// A simpler dep graph stored alongside the result for debugging purposes.
188+
/// This is also constructed when we want to query the dep graph.
189+
pub model: Option<DepGraphModel>,
190+
}
191+
153192
pub struct DecodedDepGraph {
154193
pub prev_graph: PreviousDepGraph,
155194
pub state: IndexVec<DepNodeIndex, AtomicCell<DepNodeState>>,
156195
pub invalidated: Vec<DepNodeIndex>,
157196
pub needs_gc: bool,
197+
pub model: Option<DepGraphModel>,
198+
}
199+
200+
impl DecodedDepGraph {
201+
/// Asserts that the model matches the real dep graph we decoded
202+
fn validate_model(&mut self) {
203+
let model = if let Some(ref model) = self.model {
204+
model
205+
} else {
206+
return
207+
};
208+
209+
for i in self.state.indices() {
210+
if *self.state[i].get_mut() == DepNodeState::Invalid {
211+
assert!(!model.data.contains_key(&i));
212+
assert_eq!(self.prev_graph.edges[i], None);
213+
} else {
214+
let data = model.data.get(&i).unwrap();
215+
assert_eq!(self.prev_graph.nodes[i], data.node);
216+
assert_eq!(&self.prev_graph.edges[i].as_ref().unwrap()[..], &data.edges[..]);
217+
}
218+
}
219+
220+
for k in model.data.keys() {
221+
assert!((k.as_u32() as usize) < self.state.len());
222+
}
223+
224+
}
158225
}
159226

160227
pub fn decode_dep_graph(
161228
time_passes: bool,
162229
d: &mut opaque::Decoder<'_>,
163230
results_d: &mut opaque::Decoder<'_>,
164231
) -> Result<DecodedDepGraph, String> {
165-
// Metrics used to decided when to GC
232+
// Metrics used to decide when to GC
166233
let mut valid_data = 0;
167234
let mut total_data = 0;
168235

169-
let fingerprints: IndexVec<DepNodeIndex, Fingerprint> =
170-
time_ext(time_passes, None, "decode prev result fingerprints", || {
171-
IndexVec::decode(results_d)
172-
})?;
236+
let result_format = time_ext(time_passes, None, "decode prev result fingerprints", || {
237+
CompletedDepGraph::decode(results_d)
238+
})?;
239+
240+
let node_count = result_format.results.len();
173241
let mut nodes: IndexVec<_, _> = repeat(DepNode {
174242
kind: DepKind::Null,
175243
hash: Fingerprint::ZERO,
176-
}).take(fingerprints.len()).collect();
177-
let mut edges: IndexVec<_, _> = repeat(None).take(fingerprints.len()).collect();
178-
let mut state: IndexVec<_, _> = (0..fingerprints.len()).map(|_| {
244+
}).take(node_count).collect();
245+
let mut edges: IndexVec<_, _> = repeat(None).take(node_count).collect();
246+
let mut state: IndexVec<_, _> = (0..node_count).map(|_| {
179247
AtomicCell::new(DepNodeState::Invalid)
180248
}).collect();
181249
loop {
@@ -221,6 +289,7 @@ pub fn decode_dep_graph(
221289
let i = DepNodeIndex::decode(d)?;
222290
valid_data -= edges[i].as_ref().map_or(0, |edges| edges.len());
223291
state[i] = AtomicCell::new(DepNodeState::Invalid);
292+
edges[i] = None;
224293
}
225294
valid_data -= len as usize * 8;
226295
}
@@ -241,19 +310,24 @@ pub fn decode_dep_graph(
241310
valid_data as f32 / total_data as f32
242311
);
243312

244-
Ok(DecodedDepGraph {
313+
let mut graph = DecodedDepGraph {
245314
prev_graph: PreviousDepGraph {
246315
index,
247316
nodes,
248-
fingerprints,
317+
fingerprints: result_format.results,
249318
edges,
250319
},
251320
invalidated: state.indices()
252321
.filter(|&i| *state[i].get_mut() == DepNodeState::Invalid)
253322
.collect(),
254323
state,
255324
needs_gc: valid_data + valid_data / 3 < total_data,
256-
})
325+
model: result_format.model,
326+
};
327+
328+
graph.validate_model();
329+
330+
Ok(graph)
257331
}
258332

259333
#[derive(Debug, RustcDecodable, RustcEncodable)]
@@ -279,6 +353,7 @@ struct SerializerWorker {
279353
fingerprints: IndexVec<DepNodeIndex, Fingerprint>,
280354
previous: Lrc<PreviousDepGraph>,
281355
file: File,
356+
model: Option<DepGraphModel>,
282357
}
283358

284359
impl SerializerWorker {
@@ -397,9 +472,12 @@ impl SerializerWorker {
397472

398473
impl Worker for SerializerWorker {
399474
type Message = (usize, Action);
400-
type Result = IndexVec<DepNodeIndex, Fingerprint>;
475+
type Result = CompletedDepGraph;
401476

402477
fn message(&mut self, (buffer_size_est, action): (usize, Action)) {
478+
// Apply the action to the model if present
479+
self.model.as_mut().map(|model| model.apply(&action));
480+
403481
let mut encoder = opaque::Encoder::new(Vec::with_capacity(buffer_size_est * 5));
404482
let action = match action {
405483
Action::UpdateNodes(nodes) => {
@@ -420,8 +498,11 @@ impl Worker for SerializerWorker {
420498
self.file.write_all(&encoder.into_inner()).expect("unable to write to temp dep graph");
421499
}
422500

423-
fn complete(self) -> IndexVec<DepNodeIndex, Fingerprint> {
424-
self.fingerprints
501+
fn complete(self) -> CompletedDepGraph {
502+
CompletedDepGraph {
503+
results: self.fingerprints,
504+
model: self.model
505+
}
425506
}
426507
}
427508

@@ -430,7 +511,7 @@ const BUFFER_SIZE: usize = 800000;
430511
pub struct Serializer {
431512
worker: Lrc<WorkerExecutor<SerializerWorker>>,
432513
node_count: u32,
433-
invalids: Vec<DepNodeIndex>,
514+
invalidated: Vec<DepNodeIndex>,
434515
new_buffer: Vec<(DepNodeIndex, DepNodeData)>,
435516
new_buffer_size: usize,
436517
updated_buffer: Vec<(DepNodeIndex, DepNodeData)>,
@@ -441,15 +522,17 @@ impl Serializer {
441522
pub fn new(
442523
file: File,
443524
previous: Lrc<PreviousDepGraph>,
444-
invalids: Vec<DepNodeIndex>,
525+
invalidated: Vec<DepNodeIndex>,
526+
model: Option<DepGraphModel>,
445527
) -> Self {
446528
Serializer {
447-
invalids,
448-
node_count: previous.node_count() as u32,
529+
invalidated,
530+
node_count: previous.nodes.len() as u32,
449531
worker: Lrc::new(WorkerExecutor::new(SerializerWorker {
450532
fingerprints: previous.fingerprints.clone(),
451533
previous,
452534
file,
535+
model,
453536
})),
454537
new_buffer: Vec::with_capacity(BUFFER_SIZE),
455538
new_buffer_size: 0,
@@ -467,9 +550,9 @@ impl Serializer {
467550

468551
#[inline]
469552
fn alloc_index(&mut self) -> DepNodeIndex {
470-
if let Some(invalid) = self.invalids.pop() {
553+
if let Some(invalidated) = self.invalidated.pop() {
471554
// Reuse an invalided index
472-
invalid
555+
invalidated
473556
} else {
474557
// Create a new index
475558
let index = self.node_count;
@@ -511,10 +594,10 @@ impl Serializer {
511594
}
512595
}
513596

514-
pub fn complete(
597+
pub(super) fn complete(
515598
&mut self,
516599
invalidate: Vec<DepNodeIndex>,
517-
) -> IndexVec<DepNodeIndex, Fingerprint> {
600+
) -> CompletedDepGraph {
518601
if self.new_buffer.len() > 0 {
519602
self.flush_new();
520603
}

src/librustc/session/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,11 @@ impl Session {
730730
)
731731
}
732732

733+
pub fn reconstruct_dep_graph(&self) -> bool {
734+
self.opts.debugging_opts.dump_dep_graph ||
735+
self.opts.debugging_opts.query_dep_graph
736+
}
737+
733738
pub fn set_incr_session_load_dep_graph(&self, load: bool) {
734739
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
735740

src/librustc/ty/query/plumbing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,14 +544,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
544544
// in DepGraph::try_mark_green()
545545
// 2. Two distinct query keys get mapped to the same DepNode
546546
// (see for example #48923)
547-
/*debug_assert!(
547+
debug_assert!(
548548
!self.dep_graph.dep_node_exists(&dep_node),
549549
"Forcing query with already existing DepNode.\n\
550550
- query-key: {:?}\n\
551551
- dep-node: {:?}",
552552
key,
553553
dep_node,
554-
);*/
554+
);
555555

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

src/librustc_codegen_ssa/base.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,6 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
777777
}
778778

779779
fn assert_and_save_dep_graph<'ll, 'tcx>(tcx: TyCtxt<'ll, 'tcx, 'tcx>) {
780-
time(tcx.sess,
781-
"assert dep graph",
782-
|| ::rustc_incremental::assert_dep_graph(tcx));
783-
784780
time(tcx.sess,
785781
"serialize dep graph",
786782
|| ::rustc_incremental::save_dep_graph(tcx));
@@ -944,9 +940,9 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
944940
// know that later). If we are not doing LTO, there is only one optimized
945941
// version of each module, so we re-use that.
946942
let dep_node = cgu.codegen_dep_node(tcx);
947-
/*debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
943+
debug_assert!(!tcx.dep_graph.dep_node_exists(&dep_node),
948944
"CompileCodegenUnit dep-node for CGU `{}` already exists before marking.",
949-
cgu.name());*/
945+
cgu.name());
950946

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

0 commit comments

Comments
 (0)