Skip to content

Commit 62ca540

Browse files
committed
wip
1 parent 1a4abcc commit 62ca540

File tree

5 files changed

+294
-152
lines changed

5 files changed

+294
-152
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,13 @@ impl DepNodeColor {
5353

5454
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
5555
pub enum DepNodeState {
56-
/// The node is invalid since its result is older than the previous session.
56+
/// The dep node index is invalid and does not refer to any dep node.
5757
Invalid,
5858

59+
/// The node is from the previous session and it is a eval_always node,
60+
// but its state is unknown.
61+
UnknownEvalAlways,
62+
5963
/// The node is from the previous session, but its state is unknown
6064
Unknown,
6165

@@ -73,7 +77,8 @@ pub enum DepNodeState {
7377
impl DepNodeState {
7478
pub fn color(self) -> Option<DepNodeColor> {
7579
match self {
76-
DepNodeState::Invalid |
80+
DepNodeState::Invalid => bug!(),
81+
DepNodeState::UnknownEvalAlways |
7782
DepNodeState::Unknown |
7883
DepNodeState::WasUnknownWillBeGreen => None,
7984
DepNodeState::Red => Some(DepNodeColor::Red),
@@ -128,6 +133,7 @@ pub struct DepGraphArgs {
128133
pub prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
129134
pub file: File,
130135
pub state: IndexVec<DepNodeIndex, AtomicCell<DepNodeState>>,
136+
pub invalidated: Vec<DepNodeIndex>,
131137
}
132138

133139
impl DepGraph {
@@ -141,7 +147,7 @@ impl DepGraph {
141147
data: Some(Lrc::new(DepGraphData {
142148
previous_work_products: args.prev_work_products,
143149
dep_node_debug: Default::default(),
144-
current: CurrentDepGraph::new(prev_graph.clone(), args.file),
150+
current: CurrentDepGraph::new(prev_graph.clone(), args.file, args.invalidated),
145151
emitted_diagnostics: Default::default(),
146152
emitted_diagnostics_cond_var: Condvar::new(),
147153
colors,
@@ -551,11 +557,28 @@ impl DepGraph {
551557
pub fn serialize(&self) -> IndexVec<DepNodeIndex, Fingerprint> {
552558
let data = self.data.as_ref().unwrap();
553559
// Invalidate dep nodes with unknown state as these cannot safely
554-
// be marked green in the next session.
560+
// be marked green in the next session. One of the dependencies of the
561+
// unknown node may have changed in this session (and is currently marked red),
562+
// but might be green again in the next session, which may cause the unknown node
563+
// to incorrectly be marked green in the next session, even though one of its dependencies
564+
// did actually change.
565+
555566
let invalidate = data.colors.values.indices().filter_map(|prev_index| {
556567
match data.colors.get(prev_index) {
557-
DepNodeState::Unknown => Some(prev_index),
558-
_ => None,
568+
// In order to this invalidation to be safe, none of the valid nodes can
569+
// point to unknown nodes.
570+
DepNodeState::Unknown |
571+
DepNodeState::UnknownEvalAlways => Some(prev_index),
572+
573+
DepNodeState::WasUnknownWillBeGreen => bug!(),
574+
575+
// For green nodes, we either executed the query (which always uses valid nodes)
576+
// or we marked it as green because all its dependencies are green and valid.
577+
DepNodeState::Green |
578+
// Red nodes were always exexuted.
579+
DepNodeState::Red |
580+
// We don't need to invalidate already invalid nodes
581+
DepNodeState::Invalid => None,
559582
}
560583
}).collect();
561584
// FIXME: Can this deadlock?
@@ -606,8 +629,11 @@ impl DepGraph {
606629
let prev_index = data.previous.node_to_index_opt(dep_node)?;
607630

608631
match data.colors.get(prev_index) {
632+
DepNodeState::Invalid => bug!(),
609633
DepNodeState::Green => Some(prev_index),
610-
DepNodeState::Invalid |
634+
// We don't need to mark eval_always nodes as green here, since we'll just be executing
635+
// the query after anyway.
636+
DepNodeState::UnknownEvalAlways |
611637
DepNodeState::Red => None,
612638
DepNodeState::Unknown |
613639
DepNodeState::WasUnknownWillBeGreen => {
@@ -677,6 +703,7 @@ impl DepGraph {
677703
false
678704
}
679705
DepNodeState::Invalid |
706+
DepNodeState::UnknownEvalAlways |
680707
DepNodeState::Unknown |
681708
DepNodeState::WasUnknownWillBeGreen => {
682709
bug!("try_force_previous_green() - Forcing the DepNode \
@@ -720,6 +747,7 @@ impl DepGraph {
720747
let dep_dep_node_color = data.colors.get(dep_dep_node_index);
721748

722749
match dep_dep_node_color {
750+
DepNodeState::Invalid => bug!(),
723751
DepNodeState::Green => {
724752
// This dependency has been marked as green before, we are
725753
// still fine and can continue with checking the other
@@ -740,9 +768,8 @@ impl DepGraph {
740768
data.previous.index_to_node(dep_dep_node_index));
741769
return false
742770
}
743-
// Either the previous result is too old or
744-
// this is a eval_always node. Try to force the node
745-
DepNodeState::Invalid => {
771+
// This is a eval_always node. Try to force the node
772+
DepNodeState::UnknownEvalAlways => {
746773
if !self.try_force_previous_green(tcx, data, dep_dep_node_index) {
747774
return false;
748775
}
@@ -885,8 +912,15 @@ impl DepGraph {
885912
}
886913
}
887914
DepNodeState::WasUnknownWillBeGreen => bug!("no tasks should be in progress"),
915+
916+
// There cannot be results stored for invalid indices.
888917
DepNodeState::Invalid |
918+
919+
// Unknown nodes are unused, so we don't want to promote these and we would
920+
// not to mark their colors in order to do so anyway.
921+
DepNodeState::UnknownEvalAlways |
889922
DepNodeState::Unknown |
923+
890924
DepNodeState::Red => {
891925
// We can skip red nodes because a node can only be marked
892926
// as red if the query result was recomputed and thus is
@@ -1003,7 +1037,11 @@ pub(super) struct CurrentDepGraph {
10031037
}
10041038

10051039
impl CurrentDepGraph {
1006-
fn new(prev_graph: Lrc<PreviousDepGraph>, file: File) -> CurrentDepGraph {
1040+
fn new(
1041+
prev_graph: Lrc<PreviousDepGraph>,
1042+
file: File,
1043+
invalidated: Vec<DepNodeIndex>,
1044+
) -> CurrentDepGraph {
10071045
use std::time::{SystemTime, UNIX_EPOCH};
10081046

10091047
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
@@ -1040,7 +1078,7 @@ impl CurrentDepGraph {
10401078
forbidden_edge,
10411079
total_read_count: AtomicU64::new(0),
10421080
total_duplicate_read_count: AtomicU64::new(0),
1043-
serializer: Lock::new(Serializer::new(file, prev_graph)),
1081+
serializer: Lock::new(Serializer::new(file, prev_graph, invalidated)),
10441082
}
10451083
}
10461084

src/librustc/dep_graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ 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::SerializedDepGraph;
19+
pub use self::serialized::decode_dep_graph;

src/librustc/dep_graph/prev.rs

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,70 +3,28 @@ use rustc_data_structures::fx::FxHashMap;
33
use rustc_data_structures::indexed_vec::IndexVec;
44
use super::dep_node::DepNode;
55
use super::graph::DepNodeIndex;
6-
use super::serialized::SerializedDepGraph;
76

87
#[derive(Debug, Default)]
98
pub struct PreviousDepGraph {
109
/// Maps from dep nodes to their previous index, if any.
11-
index: FxHashMap<DepNode, DepNodeIndex>,
10+
pub(super) index: FxHashMap<DepNode, DepNodeIndex>,
1211
/// The set of all DepNodes in the graph
13-
nodes: IndexVec<DepNodeIndex, DepNode>,
12+
pub(super) nodes: IndexVec<DepNodeIndex, DepNode>,
1413
/// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
1514
/// the DepNode at the same index in the nodes vector.
1615
pub(super) fingerprints: IndexVec<DepNodeIndex, Fingerprint>,
1716
/// For each DepNode, stores the list of edges originating from that
18-
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
19-
/// which holds the actual DepNodeIndices of the target nodes.
20-
edge_list_indices: IndexVec<DepNodeIndex, (u32, u32)>,
21-
/// A flattened list of all edge targets in the graph. Edge sources are
22-
/// implicit in edge_list_indices.
23-
edge_list_data: Vec<DepNodeIndex>,
17+
/// DepNode.
18+
pub(super) edges: IndexVec<DepNodeIndex, Option<Box<[DepNodeIndex]>>>,
2419
}
2520

2621
impl PreviousDepGraph {
27-
pub fn new(graph: SerializedDepGraph) -> PreviousDepGraph {
28-
let index: FxHashMap<_, _> = graph.nodes
29-
.iter_enumerated()
30-
.map(|(idx, dep_node)| (dep_node.node, idx))
31-
.collect();
32-
33-
let nodes: IndexVec<DepNodeIndex, _> =
34-
graph.nodes.iter().map(|d| d.node).collect();
35-
36-
let total_edge_count: usize = graph.nodes.iter().map(|d| d.edges.len()).sum();
37-
38-
let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
39-
let mut edge_list_data = Vec::with_capacity(total_edge_count);
40-
41-
for (current_dep_node_index, edges) in graph.nodes.iter_enumerated()
42-
.map(|(i, d)| (i, &d.edges)) {
43-
let start = edge_list_data.len() as u32;
44-
edge_list_data.extend(edges.iter().cloned());
45-
let end = edge_list_data.len() as u32;
46-
47-
debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
48-
edge_list_indices.push((start, end));
49-
}
50-
51-
debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
52-
debug_assert_eq!(edge_list_data.len(), total_edge_count);
53-
54-
PreviousDepGraph {
55-
fingerprints: graph.fingerprints,
56-
nodes,
57-
edge_list_indices,
58-
edge_list_data,
59-
index,
60-
}
61-
}
62-
6322
#[inline]
6423
pub fn edge_targets_from(
6524
&self,
6625
dep_node_index: DepNodeIndex
6726
) -> &[DepNodeIndex] {
68-
let targets = self.edge_list_indices[dep_node_index];
69-
&self.edge_list_data[targets.0 as usize..targets.1 as usize]
27+
self.edges[dep_node_index].as_ref().unwrap()
7028
}
7129

7230
#[inline]

0 commit comments

Comments
 (0)