Skip to content

Commit e6badfd

Browse files
incr.comp.: Use red/green tracking for CGU re-use.
1 parent c9a17ef commit e6badfd

File tree

30 files changed

+206
-246
lines changed

30 files changed

+206
-246
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ pub enum DepNodeColor {
6767
Green(DepNodeIndex)
6868
}
6969

70+
impl DepNodeColor {
71+
pub fn is_green(self) -> bool {
72+
match self {
73+
DepNodeColor::Red => false,
74+
DepNodeColor::Green(_) => true,
75+
}
76+
}
77+
}
78+
7079
struct DepGraphData {
7180
/// The old, initial encoding of the dependency graph. This will soon go
7281
/// away.
@@ -94,6 +103,9 @@ struct DepGraphData {
94103
work_products: RefCell<FxHashMap<WorkProductId, WorkProduct>>,
95104

96105
dep_node_debug: RefCell<FxHashMap<DepNode, String>>,
106+
107+
// Used for testing, only populated when -Zquery-dep-graph is specified.
108+
loaded_from_cache: RefCell<FxHashMap<DepNodeIndexNew, bool>>,
97109
}
98110

99111
impl DepGraph {
@@ -108,6 +120,7 @@ impl DepGraph {
108120
current: RefCell::new(CurrentDepGraph::new()),
109121
previous: prev_graph,
110122
colors: RefCell::new(FxHashMap()),
123+
loaded_from_cache: RefCell::new(FxHashMap()),
111124
})),
112125
fingerprints: Rc::new(RefCell::new(FxHashMap())),
113126
}
@@ -256,16 +269,9 @@ impl DepGraph {
256269
data.current.borrow_mut().push_anon_task();
257270
let result = op();
258271
let dep_node_index_legacy = data.edges.borrow_mut().pop_anon_task(dep_kind);
259-
let (new_dep_node, dep_node_index_new) = data.current
260-
.borrow_mut()
261-
.pop_anon_task(dep_kind);
262-
if let Some(new_dep_node) = new_dep_node {
263-
assert!(data.colors
264-
.borrow_mut()
265-
.insert(new_dep_node, DepNodeColor::Red)
266-
.is_none());
267-
}
268-
272+
let dep_node_index_new = data.current
273+
.borrow_mut()
274+
.pop_anon_task(dep_kind);
269275
(result, DepNodeIndex {
270276
legacy: dep_node_index_legacy,
271277
new: dep_node_index_new,
@@ -594,6 +600,25 @@ impl DepGraph {
594600
}
595601
}).unwrap_or(false)
596602
}
603+
604+
pub fn mark_loaded_from_cache(&self, dep_node: DepNodeIndex, state: bool) {
605+
debug!("mark_loaded_from_cache({:?}, {})",
606+
self.data.as_ref().unwrap().current.borrow().nodes[dep_node.new],
607+
state);
608+
609+
self.data
610+
.as_ref()
611+
.unwrap()
612+
.loaded_from_cache
613+
.borrow_mut()
614+
.insert(dep_node.new, state);
615+
}
616+
617+
pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option<bool> {
618+
let data = self.data.as_ref().unwrap();
619+
let dep_node_index = data.current.borrow().node_to_node_index[dep_node];
620+
data.loaded_from_cache.borrow().get(&dep_node_index).cloned()
621+
}
597622
}
598623

599624
/// A "work product" is an intermediate result that we save into the
@@ -630,11 +655,6 @@ impl DepGraph {
630655
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
631656
pub struct WorkProduct {
632657
pub cgu_name: String,
633-
/// Extra hash used to decide if work-product is still suitable;
634-
/// note that this is *not* a hash of the work-product itself.
635-
/// See documentation on `WorkProduct` type for an example.
636-
pub input_hash: u64,
637-
638658
/// Saved files associated with this CGU
639659
pub saved_files: Vec<(OutputType, String)>,
640660
}
@@ -644,15 +664,26 @@ pub(super) struct CurrentDepGraph {
644664
edges: IndexVec<DepNodeIndexNew, Vec<DepNodeIndexNew>>,
645665
node_to_node_index: FxHashMap<DepNode, DepNodeIndexNew>,
646666

667+
anon_id_seed: Fingerprint,
668+
647669
task_stack: Vec<OpenTask>,
648670
}
649671

650672
impl CurrentDepGraph {
651673
fn new() -> CurrentDepGraph {
674+
use std::time::{SystemTime, UNIX_EPOCH};
675+
676+
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
677+
let nanos = duration.as_secs() * 1_000_000_000 +
678+
duration.subsec_nanos() as u64;
679+
let mut stable_hasher = StableHasher::new();
680+
nanos.hash(&mut stable_hasher);
681+
652682
CurrentDepGraph {
653683
nodes: IndexVec::new(),
654684
edges: IndexVec::new(),
655685
node_to_node_index: FxHashMap(),
686+
anon_id_seed: stable_hasher.finish(),
656687
task_stack: Vec::new(),
657688
}
658689
}
@@ -696,14 +727,14 @@ impl CurrentDepGraph {
696727
});
697728
}
698729

699-
fn pop_anon_task(&mut self, kind: DepKind) -> (Option<DepNode>, DepNodeIndexNew) {
730+
fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew {
700731
let popped_node = self.task_stack.pop().unwrap();
701732

702733
if let OpenTask::Anon {
703734
read_set: _,
704735
reads
705736
} = popped_node {
706-
let mut fingerprint = Fingerprint::zero();
737+
let mut fingerprint = self.anon_id_seed;
707738
let mut hasher = StableHasher::new();
708739

709740
for &read in reads.iter() {
@@ -725,9 +756,9 @@ impl CurrentDepGraph {
725756
};
726757

727758
if let Some(&index) = self.node_to_node_index.get(&target_dep_node) {
728-
(None, index)
759+
index
729760
} else {
730-
(Some(target_dep_node), self.alloc_node(target_dep_node, reads))
761+
self.alloc_node(target_dep_node, reads)
731762
}
732763
} else {
733764
bug!("pop_anon_task() - Expected anonymous task to be popped")

src/librustc/ty/maps/plumbing.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ macro_rules! define_maps {
320320
dep_node_index)
321321
}
322322

323+
debug!("ty::queries::{}::try_get_with(key={:?}) - running try_mark_green",
324+
stringify!($name),
325+
key);
326+
323327
if let Some(dep_node_index) = tcx.dep_graph.try_mark_green(tcx, &dep_node) {
324328
debug_assert!(tcx.dep_graph.is_green(dep_node_index));
325329
profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
@@ -363,6 +367,10 @@ macro_rules! define_maps {
363367
})
364368
})?;
365369

370+
if tcx.sess.opts.debugging_opts.query_dep_graph {
371+
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
372+
}
373+
366374
let value = QueryValue::new(result, dep_node_index, diagnostics);
367375

368376
Ok((&tcx.maps
@@ -394,6 +402,10 @@ macro_rules! define_maps {
394402

395403
let ((result, dep_node_index), diagnostics) = res;
396404

405+
if tcx.sess.opts.debugging_opts.query_dep_graph {
406+
tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false);
407+
}
408+
397409
let value = QueryValue::new(result, dep_node_index, diagnostics);
398410

399411
Ok(((&tcx.maps
@@ -406,8 +418,6 @@ macro_rules! define_maps {
406418
dep_node_index))
407419
}
408420

409-
410-
411421
pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
412422
-> Result<$V, DiagnosticBuilder<'a>> {
413423
match Self::try_get_with(tcx, span, key) {

src/librustc_incremental/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ pub use persist::save_work_products;
3939
pub use persist::in_incr_comp_dir;
4040
pub use persist::prepare_session_directory;
4141
pub use persist::finalize_session_directory;
42+
pub use persist::delete_workproduct_files;

src/librustc_incremental/persist/load.rs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
9999
/// variants that represent inputs (HIR and imported Metadata).
100100
fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool {
101101
match dep_node.kind {
102+
DepKind::Krate |
102103
DepKind::Hir |
103104
DepKind::HirBody |
104105
DepKind::InScopeTraits |
@@ -258,33 +259,28 @@ fn transitive_dirty_nodes(serialized_dep_graph: &SerializedDepGraph,
258259
/// otherwise no longer applicable.
259260
fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
260261
work_products: Vec<SerializedWorkProduct>,
261-
clean_work_products: &FxHashSet<WorkProductId>) {
262+
_clean_work_products: &FxHashSet<WorkProductId>) {
262263
debug!("reconcile_work_products({:?})", work_products);
263264
for swp in work_products {
264-
if !clean_work_products.contains(&swp.id) {
265-
debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
266-
delete_dirty_work_product(tcx, swp);
267-
} else {
268-
let mut all_files_exist = true;
269-
for &(_, ref file_name) in swp.work_product.saved_files.iter() {
270-
let path = in_incr_comp_dir_sess(tcx.sess, file_name);
271-
if !path.exists() {
272-
all_files_exist = false;
273-
274-
if tcx.sess.opts.debugging_opts.incremental_info {
275-
eprintln!("incremental: could not find file for \
276-
up-to-date work product: {}", path.display());
277-
}
265+
let mut all_files_exist = true;
266+
for &(_, ref file_name) in swp.work_product.saved_files.iter() {
267+
let path = in_incr_comp_dir_sess(tcx.sess, file_name);
268+
if !path.exists() {
269+
all_files_exist = false;
270+
271+
if tcx.sess.opts.debugging_opts.incremental_info {
272+
eprintln!("incremental: could not find file for \
273+
up-to-date work product: {}", path.display());
278274
}
279275
}
276+
}
280277

281-
if all_files_exist {
282-
debug!("reconcile_work_products: all files for {:?} exist", swp);
283-
tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product);
284-
} else {
285-
debug!("reconcile_work_products: some file for {:?} does not exist", swp);
286-
delete_dirty_work_product(tcx, swp);
287-
}
278+
if all_files_exist {
279+
debug!("reconcile_work_products: all files for {:?} exist", swp);
280+
tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product);
281+
} else {
282+
debug!("reconcile_work_products: some file for {:?} does not exist", swp);
283+
delete_dirty_work_product(tcx, swp);
288284
}
289285
}
290286
}

src/librustc_incremental/persist/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ pub use self::load::load_dep_graph_new;
2929
pub use self::save::save_dep_graph;
3030
pub use self::save::save_work_products;
3131
pub use self::work_product::save_trans_partition;
32+
pub use self::work_product::delete_workproduct_files;

src/librustc_incremental/persist/work_product.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@ use std::fs as std_fs;
2121
pub fn save_trans_partition(sess: &Session,
2222
dep_graph: &DepGraph,
2323
cgu_name: &str,
24-
partition_hash: u64,
2524
files: &[(OutputType, PathBuf)]) {
26-
debug!("save_trans_partition({:?},{},{:?})",
25+
debug!("save_trans_partition({:?},{:?})",
2726
cgu_name,
28-
partition_hash,
2927
files);
3028
if sess.opts.incremental.is_none() {
3129
return;
@@ -57,7 +55,6 @@ pub fn save_trans_partition(sess: &Session,
5755

5856
let work_product = WorkProduct {
5957
cgu_name: cgu_name.to_string(),
60-
input_hash: partition_hash,
6158
saved_files,
6259
};
6360

src/librustc_trans/assert_module_sources.rs

Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -27,47 +27,32 @@
2727
//! the HIR doesn't change as a result of the annotations, which might
2828
//! perturb the reuse results.
2929
30+
use rustc::dep_graph::{DepNode, DepConstructor};
3031
use rustc::ty::TyCtxt;
3132
use syntax::ast;
32-
33-
use {ModuleSource, ModuleTranslation};
34-
3533
use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
3634

3735
const MODULE: &'static str = "module";
3836
const CFG: &'static str = "cfg";
3937

4038
#[derive(Debug, PartialEq, Clone, Copy)]
41-
pub enum Disposition { Reused, Translated }
42-
43-
impl ModuleTranslation {
44-
pub fn disposition(&self) -> (String, Disposition) {
45-
let disposition = match self.source {
46-
ModuleSource::Preexisting(_) => Disposition::Reused,
47-
ModuleSource::Translated(_) => Disposition::Translated,
48-
};
39+
enum Disposition { Reused, Translated }
4940

50-
(self.name.clone(), disposition)
51-
}
52-
}
53-
54-
pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
55-
modules: &[(String, Disposition)]) {
41+
pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
5642
let _ignore = tcx.dep_graph.in_ignore();
5743

5844
if tcx.sess.opts.incremental.is_none() {
5945
return;
6046
}
6147

62-
let ams = AssertModuleSource { tcx: tcx, modules: modules };
48+
let ams = AssertModuleSource { tcx };
6349
for attr in &tcx.hir.krate().attrs {
6450
ams.check_attr(attr);
6551
}
6652
}
6753

6854
struct AssertModuleSource<'a, 'tcx: 'a> {
69-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
70-
modules: &'a [(String, Disposition)],
55+
tcx: TyCtxt<'a, 'tcx, 'tcx>
7156
}
7257

7358
impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
@@ -86,32 +71,31 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
8671
}
8772

8873
let mname = self.field(attr, MODULE);
89-
let mtrans = self.modules.iter().find(|&&(ref name, _)| name == mname.as_str());
90-
let mtrans = match mtrans {
91-
Some(m) => m,
92-
None => {
93-
debug!("module name `{}` not found amongst:", mname);
94-
for &(ref name, ref disposition) in self.modules {
95-
debug!("module named `{}` with disposition {:?}",
96-
name,
97-
disposition);
98-
}
9974

100-
self.tcx.sess.span_err(
101-
attr.span,
102-
&format!("no module named `{}`", mname));
103-
return;
104-
}
105-
};
75+
let dep_node = DepNode::new(self.tcx,
76+
DepConstructor::CompileCodegenUnit(mname.as_str()));
10677

107-
let mtrans_disposition = mtrans.1;
108-
if disposition != mtrans_disposition {
109-
self.tcx.sess.span_err(
110-
attr.span,
111-
&format!("expected module named `{}` to be {:?} but is {:?}",
112-
mname,
113-
disposition,
114-
mtrans_disposition));
78+
if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
79+
match (disposition, loaded_from_cache) {
80+
(Disposition::Reused, false) => {
81+
self.tcx.sess.span_err(
82+
attr.span,
83+
&format!("expected module named `{}` to be Reused but is Translated",
84+
mname));
85+
}
86+
(Disposition::Translated, true) => {
87+
self.tcx.sess.span_err(
88+
attr.span,
89+
&format!("expected module named `{}` to be Translated but is Reused",
90+
mname));
91+
}
92+
(Disposition::Reused, true) |
93+
(Disposition::Translated, false) => {
94+
// These are what we would expect.
95+
}
96+
}
97+
} else {
98+
self.tcx.sess.span_err(attr.span, &format!("no module named `{}`", mname));
11599
}
116100
}
117101

src/librustc_trans/back/symbol_export.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ pub fn provide_local(providers: &mut Providers) {
7979
providers.is_exported_symbol = |tcx, id| {
8080
// FIXME(#42293) needs red/green to not break a bunch of incremental
8181
// tests
82-
tcx.dep_graph.with_ignore(|| {
83-
tcx.exported_symbol_ids(id.krate).contains(&id)
84-
})
82+
tcx.exported_symbol_ids(id.krate).contains(&id)
8583
};
8684

8785
providers.exported_symbols = |tcx, cnum| {

0 commit comments

Comments
 (0)