Skip to content

Commit 2238f8b

Browse files
incr.comp.: Add minimal version of try_mark_green procedure.
1 parent d17f85a commit 2238f8b

File tree

6 files changed

+268
-56
lines changed

6 files changed

+268
-56
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 131 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use session::config::OutputType;
1616
use std::cell::{Ref, RefCell};
1717
use std::hash::Hash;
1818
use std::rc::Rc;
19+
use ty::TyCtxt;
1920
use util::common::{ProfileQueriesMsg, profq_msg};
2021

2122
use ich::Fingerprint;
@@ -28,6 +29,7 @@ use super::edges::{self, DepGraphEdges};
2829
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
2930
use super::prev::PreviousDepGraph;
3031

32+
3133
#[derive(Clone)]
3234
pub struct DepGraph {
3335
data: Option<Rc<DepGraphData>>,
@@ -62,8 +64,7 @@ impl DepNodeIndex {
6264
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
6365
pub enum DepNodeColor {
6466
Red,
65-
Green,
66-
Gray
67+
Green(DepNodeIndex)
6768
}
6869

6970
struct DepGraphData {
@@ -178,6 +179,8 @@ impl DepGraph {
178179
R: HashStable<HCX>,
179180
{
180181
if let Some(ref data) = self.data {
182+
debug_assert!(!data.colors.borrow().contains_key(&key));
183+
181184
data.edges.borrow_mut().push_task(key);
182185
data.current.borrow_mut().push_task(key);
183186
if cfg!(debug_assertions) {
@@ -212,7 +215,10 @@ impl DepGraph {
212215
let prev_fingerprint = data.previous.fingerprint_of(&key);
213216

214217
let color = if Some(current_fingerprint) == prev_fingerprint {
215-
DepNodeColor::Green
218+
DepNodeColor::Green(DepNodeIndex {
219+
legacy: dep_node_index_legacy,
220+
new: dep_node_index_new,
221+
})
216222
} else {
217223
DepNodeColor::Red
218224
};
@@ -310,18 +316,6 @@ impl DepGraph {
310316
self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
311317
}
312318

313-
pub fn node_color(&self, dep_node: &DepNode) -> DepNodeColor {
314-
match self.data.as_ref().unwrap().colors.borrow().get(dep_node) {
315-
Some(&color) => {
316-
debug_assert!(color != DepNodeColor::Gray);
317-
color
318-
}
319-
None => {
320-
DepNodeColor::Gray
321-
}
322-
}
323-
}
324-
325319
/// Indicates that a previous work product exists for `v`. This is
326320
/// invoked during initial start-up based on what nodes are clean
327321
/// (and what files exist in the incr. directory).
@@ -426,6 +420,128 @@ impl DepGraph {
426420
edge_list_data,
427421
}
428422
}
423+
424+
pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
425+
self.data.as_ref().and_then(|data| data.colors.borrow().get(dep_node).cloned())
426+
}
427+
428+
pub fn try_mark_green(&self,
429+
tcx: TyCtxt,
430+
dep_node: &DepNode)
431+
-> Option<DepNodeIndex> {
432+
let data = self.data.as_ref().unwrap();
433+
434+
debug_assert!(!data.colors.borrow().contains_key(dep_node));
435+
debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
436+
437+
if dep_node.kind.is_input() {
438+
// We should only hit try_mark_green() for inputs that do not exist
439+
// anymore in the current compilation session. Existing inputs are
440+
// eagerly marked as either red/green before any queries are
441+
// executed.
442+
debug_assert!(dep_node.extract_def_id(tcx).is_none());
443+
return None;
444+
}
445+
446+
let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) {
447+
Some(prev) => {
448+
// This DepNode and the corresponding query invocation existed
449+
// in the previous compilation session too, so we can try to
450+
// mark it as green by recursively marking all of its
451+
// dependencies green.
452+
prev
453+
}
454+
None => {
455+
// This DepNode did not exist in the previous compilation session,
456+
// so we cannot mark it as green.
457+
return None
458+
}
459+
};
460+
461+
let mut current_deps = Vec::new();
462+
463+
for &dep_dep_node in prev_deps {
464+
let dep_dep_node = &data.previous.index_to_node(dep_dep_node);
465+
let dep_dep_node_color = data.colors.borrow().get(dep_dep_node).cloned();
466+
match dep_dep_node_color {
467+
Some(DepNodeColor::Green(node_index)) => {
468+
// This dependency has been marked as green before, we are
469+
// still fine and can continue with checking the other
470+
// dependencies.
471+
current_deps.push(node_index);
472+
}
473+
Some(DepNodeColor::Red) => {
474+
// We found a dependency the value of which has changed
475+
// compared to the previous compilation session. We cannot
476+
// mark the DepNode as green and also don't need to bother
477+
// with checking any of the other dependencies.
478+
return None
479+
}
480+
None => {
481+
// We don't know the state of this dependency. Let's try to
482+
// mark it green.
483+
if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
484+
current_deps.push(node_index);
485+
} else {
486+
// We failed to mark it green. This can have various
487+
// reasons.
488+
return None
489+
}
490+
}
491+
}
492+
}
493+
494+
// If we got here without hitting a `return` that means that all
495+
// dependencies of this DepNode could be marked as green. Therefore we
496+
// can also mark this DepNode as green. We do so by...
497+
498+
// ... allocating an entry for it in the current dependency graph and
499+
// adding all the appropriate edges imported from the previous graph ...
500+
let node_index_new = data.current
501+
.borrow_mut()
502+
.alloc_node(*dep_node,
503+
current_deps.iter().map(|n| n.new).collect());
504+
let dep_node_index_legacy = {
505+
let mut legacy_graph = data.edges.borrow_mut();
506+
legacy_graph.push_task(*dep_node);
507+
for node_index in current_deps.into_iter().map(|n| n.legacy) {
508+
legacy_graph.read_index(node_index);
509+
}
510+
legacy_graph.pop_task(*dep_node)
511+
};
512+
513+
// ... copying the fingerprint from the previous graph too, so we don't
514+
// have to recompute it ...
515+
let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
516+
assert!(self.fingerprints
517+
.borrow_mut()
518+
.insert(*dep_node, fingerprint)
519+
.is_none());
520+
521+
let node_index = DepNodeIndex {
522+
legacy: dep_node_index_legacy,
523+
new: node_index_new,
524+
};
525+
526+
// ... and finally storing a "Green" entry in the color map.
527+
assert!(data.colors
528+
.borrow_mut()
529+
.insert(*dep_node, DepNodeColor::Green(node_index))
530+
.is_none());
531+
532+
Some(node_index)
533+
}
534+
535+
// Used in various assertions
536+
pub fn is_green(&self, dep_node_index: DepNodeIndex) -> bool {
537+
let dep_node = self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index.new];
538+
self.data.as_ref().unwrap().colors.borrow().get(&dep_node).map(|&color| {
539+
match color {
540+
DepNodeColor::Red => false,
541+
DepNodeColor::Green(_) => true,
542+
}
543+
}).unwrap_or(false)
544+
}
429545
}
430546

431547
/// A "work product" is an intermediate result that we save into the

src/librustc/dep_graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod serialized;
2121

2222
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
2323
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId};
24-
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex};
24+
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor};
2525
pub use self::prev::PreviousDepGraph;
2626
pub use self::query::DepGraphQuery;
2727
pub use self::safe::AssertDepGraphSafe;

src/librustc/dep_graph/prev.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,33 @@ impl PreviousDepGraph {
2828
PreviousDepGraph { data, index }
2929
}
3030

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]));
31+
#[inline]
32+
pub fn edges_from(&self,
33+
dep_node: &DepNode)
34+
-> Option<(&[SerializedDepNodeIndex], SerializedDepNodeIndex)> {
35+
self.index
36+
.get(dep_node)
37+
.map(|&node_index| {
38+
(self.data.edge_targets_from(node_index), node_index)
39+
})
40+
}
41+
42+
#[inline]
43+
pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode {
44+
self.data.nodes[dep_node_index].0
4045
}
4146

47+
#[inline]
4248
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
4349
self.index
4450
.get(dep_node)
4551
.map(|&node_index| self.data.nodes[node_index].1)
4652
}
53+
54+
#[inline]
55+
pub fn fingerprint_by_index(&self,
56+
dep_node_index: SerializedDepNodeIndex)
57+
-> Fingerprint {
58+
self.data.nodes[dep_node_index].1
59+
}
4760
}

src/librustc/ty/maps/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ use rustc_back::PanicStrategy;
4343
use rustc_data_structures::indexed_vec::IndexVec;
4444
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4545
use rustc_data_structures::stable_hasher::StableVec;
46-
use std::cell::{RefCell, Cell};
4746

4847
use std::ops::Deref;
4948
use std::rc::Rc;

0 commit comments

Comments
 (0)