Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 6bfaf3a

Browse files
committed
Stream the dep-graph to a file.
1 parent 16156fb commit 6bfaf3a

File tree

18 files changed

+711
-919
lines changed

18 files changed

+711
-919
lines changed

compiler/rustc_incremental/src/assert_dep_graph.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ use rustc_graphviz as dot;
4040
use rustc_hir as hir;
4141
use rustc_hir::def_id::DefId;
4242
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
43-
use rustc_middle::dep_graph::debug::{DepNodeFilter, EdgeFilter};
44-
use rustc_middle::dep_graph::{DepGraphQuery, DepKind, DepNode, DepNodeExt};
43+
use rustc_middle::dep_graph::{
44+
DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter,
45+
};
4546
use rustc_middle::hir::map::Map;
4647
use rustc_middle::ty::TyCtxt;
4748
use rustc_span::symbol::{sym, Symbol};
@@ -54,7 +55,7 @@ use std::io::{BufWriter, Write};
5455
pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
5556
tcx.dep_graph.with_ignore(|| {
5657
if tcx.sess.opts.debugging_opts.dump_dep_graph {
57-
dump_graph(tcx);
58+
tcx.dep_graph.with_query(dump_graph);
5859
}
5960

6061
if !tcx.sess.opts.debugging_opts.query_dep_graph {
@@ -200,29 +201,29 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
200201
}
201202
return;
202203
}
203-
let query = tcx.dep_graph.query();
204-
for &(_, source_def_id, ref source_dep_node) in if_this_changed {
205-
let dependents = query.transitive_predecessors(source_dep_node);
206-
for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need {
207-
if !dependents.contains(&target_dep_node) {
208-
tcx.sess.span_err(
209-
target_span,
210-
&format!(
211-
"no path from `{}` to `{}`",
212-
tcx.def_path_str(source_def_id),
213-
target_pass
214-
),
215-
);
216-
} else {
217-
tcx.sess.span_err(target_span, "OK");
204+
tcx.dep_graph.with_query(|query| {
205+
for &(_, source_def_id, ref source_dep_node) in if_this_changed {
206+
let dependents = query.transitive_predecessors(source_dep_node);
207+
for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need {
208+
if !dependents.contains(&target_dep_node) {
209+
tcx.sess.span_err(
210+
target_span,
211+
&format!(
212+
"no path from `{}` to `{}`",
213+
tcx.def_path_str(source_def_id),
214+
target_pass
215+
),
216+
);
217+
} else {
218+
tcx.sess.span_err(target_span, "OK");
219+
}
218220
}
219221
}
220-
}
222+
});
221223
}
222224

223-
fn dump_graph(tcx: TyCtxt<'_>) {
225+
fn dump_graph(query: &DepGraphQuery) {
224226
let path: String = env::var("RUST_DEP_GRAPH").unwrap_or_else(|_| "dep_graph".to_string());
225-
let query = tcx.dep_graph.query();
226227

227228
let nodes = match env::var("RUST_DEP_GRAPH_FILTER") {
228229
Ok(string) => {

compiler/rustc_incremental/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod assert_dep_graph;
1414
pub mod assert_module_sources;
1515
mod persist;
1616

17-
pub use assert_dep_graph::assert_dep_graph;
17+
use assert_dep_graph::assert_dep_graph;
1818
pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir;
1919
pub use persist::delete_workproduct_files;
2020
pub use persist::finalize_session_directory;
@@ -26,4 +26,4 @@ pub use persist::prepare_session_directory;
2626
pub use persist::save_dep_graph;
2727
pub use persist::save_work_product_index;
2828
pub use persist::LoadResult;
29-
pub use persist::{load_dep_graph, DepGraphFuture};
29+
pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture};

compiler/rustc_incremental/src/persist/dirty_clean.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
//! the required condition is not met.
1515
1616
use rustc_ast::{self as ast, Attribute, NestedMetaItem};
17-
use rustc_data_structures::fingerprint::Fingerprint;
1817
use rustc_data_structures::fx::FxHashSet;
1918
use rustc_hir as hir;
2019
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -381,39 +380,20 @@ impl DirtyCleanVisitor<'tcx> {
381380
fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
382381
debug!("assert_dirty({:?})", dep_node);
383382

384-
let current_fingerprint = self.get_fingerprint(&dep_node);
385-
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
386-
387-
if current_fingerprint == prev_fingerprint {
383+
if self.tcx.dep_graph.is_green(&dep_node) {
388384
let dep_node_str = self.dep_node_str(&dep_node);
389385
self.tcx
390386
.sess
391387
.span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str));
392388
}
393389
}
394390

395-
fn get_fingerprint(&self, dep_node: &DepNode) -> Option<Fingerprint> {
396-
if self.tcx.dep_graph.dep_node_exists(dep_node) {
397-
let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node);
398-
Some(self.tcx.dep_graph.fingerprint_of(dep_node_index))
399-
} else {
400-
None
401-
}
402-
}
403-
404391
fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
405392
debug!("assert_clean({:?})", dep_node);
406393

407-
let current_fingerprint = self.get_fingerprint(&dep_node);
408-
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
409-
410394
// if the node wasn't previously evaluated and now is (or vice versa),
411395
// then the node isn't actually clean or dirty.
412-
if (current_fingerprint == None) ^ (prev_fingerprint == None) {
413-
return;
414-
}
415-
416-
if current_fingerprint != prev_fingerprint {
396+
if self.tcx.dep_graph.is_red(&dep_node) {
417397
let dep_node_str = self.dep_node_str(&dep_node);
418398
self.tcx
419399
.sess

compiler/rustc_incremental/src/persist/fs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ mod tests;
122122

123123
const LOCK_FILE_EXT: &str = ".lock";
124124
const DEP_GRAPH_FILENAME: &str = "dep-graph.bin";
125+
const STAGING_DEP_GRAPH_FILENAME: &str = "dep-graph.part.bin";
125126
const WORK_PRODUCTS_FILENAME: &str = "work-products.bin";
126127
const QUERY_CACHE_FILENAME: &str = "query-cache.bin";
127128

@@ -134,6 +135,9 @@ const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE;
134135
pub fn dep_graph_path(sess: &Session) -> PathBuf {
135136
in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
136137
}
138+
pub fn staging_dep_graph_path(sess: &Session) -> PathBuf {
139+
in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME)
140+
}
137141
pub fn dep_graph_path_from(incr_comp_session_dir: &Path) -> PathBuf {
138142
in_incr_comp_dir(incr_comp_session_dir, DEP_GRAPH_FILENAME)
139143
}

compiler/rustc_incremental/src/persist/load.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hir::definitions::Definitions;
55
use rustc_middle::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
66
use rustc_middle::ty::query::OnDiskCache;
77
use rustc_serialize::opaque::Decoder;
8-
use rustc_serialize::Decodable as RustcDecodable;
8+
use rustc_serialize::Decodable;
99
use rustc_session::Session;
1010
use std::path::Path;
1111

@@ -120,7 +120,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
120120
// Decode the list of work_products
121121
let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos);
122122
let work_products: Vec<SerializedWorkProduct> =
123-
RustcDecodable::decode(&mut work_product_decoder).unwrap_or_else(|e| {
123+
Decodable::decode(&mut work_product_decoder).unwrap_or_else(|e| {
124124
let msg = format!(
125125
"Error decoding `work-products` from incremental \
126126
compilation session directory: {}",

compiler/rustc_incremental/src/persist/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub use fs::prepare_session_directory;
1818
pub use load::load_query_result_cache;
1919
pub use load::LoadResult;
2020
pub use load::{load_dep_graph, DepGraphFuture};
21+
pub use save::build_dep_graph;
2122
pub use save::save_dep_graph;
2223
pub use save::save_work_product_index;
2324
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;

compiler/rustc_incremental/src/persist/save.rs

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_data_structures::sync::join;
3-
use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
3+
use rustc_middle::dep_graph::{DepGraph, PreviousDepGraph, WorkProduct, WorkProductId};
44
use rustc_middle::ty::TyCtxt;
55
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
66
use rustc_serialize::Encodable as RustcEncodable;
@@ -15,6 +15,9 @@ use super::file_format;
1515
use super::fs::*;
1616
use super::work_product;
1717

18+
/// Save and dump the DepGraph.
19+
///
20+
/// No query must be invoked after this function.
1821
pub fn save_dep_graph(tcx: TyCtxt<'_>) {
1922
debug!("save_dep_graph()");
2023
tcx.dep_graph.with_ignore(|| {
@@ -29,23 +32,43 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
2932

3033
let query_cache_path = query_cache_path(sess);
3134
let dep_graph_path = dep_graph_path(sess);
35+
let staging_dep_graph_path = staging_dep_graph_path(sess);
36+
37+
join(
38+
|| sess.time("assert_dep_graph", || crate::assert_dep_graph(tcx)),
39+
|| sess.time("check_dirty_clean", || dirty_clean::check_dirty_clean_annotations(tcx)),
40+
);
41+
42+
if sess.opts.debugging_opts.incremental_info {
43+
tcx.dep_graph.print_incremental_info()
44+
}
3245

3346
join(
3447
move || {
3548
sess.time("incr_comp_persist_result_cache", || {
3649
save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e));
3750
});
3851
},
39-
|| {
52+
move || {
4053
sess.time("incr_comp_persist_dep_graph", || {
41-
save_in(sess, dep_graph_path, "dependency graph", |e| {
42-
sess.time("incr_comp_encode_dep_graph", || encode_dep_graph(tcx, e))
43-
});
54+
if let Err(err) = tcx.dep_graph.encode() {
55+
sess.err(&format!(
56+
"failed to write dependency graph to `{}`: {}",
57+
staging_dep_graph_path.display(),
58+
err
59+
));
60+
}
61+
if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) {
62+
sess.err(&format!(
63+
"failed to move dependency graph from `{}` to `{}`: {}",
64+
staging_dep_graph_path.display(),
65+
dep_graph_path.display(),
66+
err
67+
));
68+
}
4469
});
4570
},
4671
);
47-
48-
dirty_clean::check_dirty_clean_annotations(tcx);
4972
})
5073
}
5174

@@ -92,7 +115,7 @@ pub fn save_work_product_index(
92115
});
93116
}
94117

95-
fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
118+
pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
96119
where
97120
F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
98121
{
@@ -144,21 +167,6 @@ where
144167
debug!("save: data written to disk successfully");
145168
}
146169

147-
fn encode_dep_graph(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult {
148-
// First encode the commandline arguments hash
149-
tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
150-
151-
if tcx.sess.opts.debugging_opts.incremental_info {
152-
tcx.dep_graph.print_incremental_info();
153-
}
154-
155-
// There is a tiny window between printing the incremental info above and encoding the dep
156-
// graph below in which the dep graph could change, thus making the printed incremental info
157-
// slightly out of date. If this matters to you, please feel free to submit a patch. :)
158-
159-
tcx.sess.time("incr_comp_encode_serialized_dep_graph", || tcx.dep_graph.encode(encoder))
160-
}
161-
162170
fn encode_work_product_index(
163171
work_products: &FxHashMap<WorkProductId, WorkProduct>,
164172
encoder: &mut FileEncoder,
@@ -177,3 +185,56 @@ fn encode_work_product_index(
177185
fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult {
178186
tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder))
179187
}
188+
189+
pub fn build_dep_graph(
190+
sess: &Session,
191+
prev_graph: PreviousDepGraph,
192+
prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
193+
) -> Option<DepGraph> {
194+
if sess.opts.incremental.is_none() {
195+
// No incremental compilation.
196+
return None;
197+
}
198+
199+
// Stream the dep-graph to an alternate file, to avoid overwriting anything in case of errors.
200+
let path_buf = staging_dep_graph_path(sess);
201+
202+
let mut encoder = match FileEncoder::new(&path_buf) {
203+
Ok(encoder) => encoder,
204+
Err(err) => {
205+
sess.err(&format!(
206+
"failed to create dependency graph at `{}`: {}",
207+
path_buf.display(),
208+
err
209+
));
210+
return None;
211+
}
212+
};
213+
214+
if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) {
215+
sess.err(&format!(
216+
"failed to write dependency graph header to `{}`: {}",
217+
path_buf.display(),
218+
err
219+
));
220+
return None;
221+
}
222+
223+
// First encode the commandline arguments hash
224+
if let Err(err) = sess.opts.dep_tracking_hash().encode(&mut encoder) {
225+
sess.err(&format!(
226+
"failed to write dependency graph hash `{}`: {}",
227+
path_buf.display(),
228+
err
229+
));
230+
return None;
231+
}
232+
233+
Some(DepGraph::new(
234+
prev_graph,
235+
prev_work_products,
236+
encoder,
237+
sess.opts.debugging_opts.query_dep_graph,
238+
sess.opts.debugging_opts.incremental_info,
239+
))
240+
}

compiler/rustc_interface/src/passes.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,9 +1021,6 @@ pub fn start_codegen<'tcx>(
10211021
rustc_symbol_mangling::test::report_symbol_names(tcx);
10221022
}
10231023

1024-
tcx.sess.time("assert_dep_graph", || rustc_incremental::assert_dep_graph(tcx));
1025-
tcx.sess.time("serialize_dep_graph", || rustc_incremental::save_dep_graph(tcx));
1026-
10271024
info!("Post-codegen\n{:?}", tcx.debug_stats());
10281025

10291026
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {

compiler/rustc_interface/src/queries.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,13 @@ impl<'tcx> Queries<'tcx> {
207207
})
208208
.open(self.session())
209209
});
210-
DepGraph::new(prev_graph, prev_work_products)
210+
211+
rustc_incremental::build_dep_graph(
212+
self.session(),
213+
prev_graph,
214+
prev_work_products,
215+
)
216+
.unwrap_or_else(DepGraph::new_disabled)
211217
}
212218
})
213219
})
@@ -435,6 +441,9 @@ impl Compiler {
435441
if self.session().opts.debugging_opts.query_stats {
436442
gcx.enter(rustc_query_impl::print_stats);
437443
}
444+
445+
self.session()
446+
.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph));
438447
}
439448

440449
_timer = Some(self.session().timer("free_global_ctxt"));

compiler/rustc_middle/src/dep_graph/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use rustc_session::Session;
88
mod dep_node;
99

1010
pub use rustc_query_system::dep_graph::{
11-
debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex,
12-
WorkProduct, WorkProductId,
11+
debug::DepNodeFilter, hash_result, DepContext, DepNodeColor, DepNodeIndex,
12+
SerializedDepNodeIndex, WorkProduct, WorkProductId,
1313
};
1414

1515
crate use dep_node::make_compile_codegen_unit;
@@ -20,6 +20,7 @@ pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
2020
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
2121
pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph<DepKind>;
2222
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
23+
pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>;
2324

2425
impl rustc_query_system::dep_graph::DepKind for DepKind {
2526
const NULL: Self = DepKind::Null;

0 commit comments

Comments
 (0)