Skip to content

Commit b1cf4d0

Browse files
committed
wip
1 parent 692a477 commit b1cf4d0

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

609632
match data.colors.get(prev_index) {
633+
DepNodeState::Invalid => bug!(),
610634
DepNodeState::Green => Some(prev_index),
611-
DepNodeState::Invalid |
635+
// We don't need to mark eval_always nodes as green here, since we'll just be executing
636+
// the query after anyway.
637+
DepNodeState::UnknownEvalAlways |
612638
DepNodeState::Red => None,
613639
DepNodeState::Unknown |
614640
DepNodeState::WasUnknownWillBeGreen => {
@@ -678,6 +704,7 @@ impl DepGraph {
678704
false
679705
}
680706
DepNodeState::Invalid |
707+
DepNodeState::UnknownEvalAlways |
681708
DepNodeState::Unknown |
682709
DepNodeState::WasUnknownWillBeGreen => {
683710
bug!("try_force_previous_green() - Forcing the DepNode \
@@ -721,6 +748,7 @@ impl DepGraph {
721748
let dep_dep_node_color = data.colors.get(dep_dep_node_index);
722749

723750
match dep_dep_node_color {
751+
DepNodeState::Invalid => bug!(),
724752
DepNodeState::Green => {
725753
// This dependency has been marked as green before, we are
726754
// still fine and can continue with checking the other
@@ -741,9 +769,8 @@ impl DepGraph {
741769
data.previous.index_to_node(dep_dep_node_index));
742770
return false
743771
}
744-
// Either the previous result is too old or
745-
// this is a eval_always node. Try to force the node
746-
DepNodeState::Invalid => {
772+
// This is a eval_always node. Try to force the node
773+
DepNodeState::UnknownEvalAlways => {
747774
if !self.try_force_previous_green(tcx, data, dep_dep_node_index) {
748775
return false;
749776
}
@@ -886,8 +913,15 @@ impl DepGraph {
886913
}
887914
}
888915
DepNodeState::WasUnknownWillBeGreen => bug!("no tasks should be in progress"),
916+
917+
// There cannot be results stored for invalid indices.
889918
DepNodeState::Invalid |
919+
920+
// Unknown nodes are unused, so we don't want to promote these and we would
921+
// not to mark their colors in order to do so anyway.
922+
DepNodeState::UnknownEvalAlways |
890923
DepNodeState::Unknown |
924+
891925
DepNodeState::Red => {
892926
// We can skip red nodes because a node can only be marked
893927
// as red if the query result was recomputed and thus is
@@ -1004,7 +1038,11 @@ pub(super) struct CurrentDepGraph {
10041038
}
10051039

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

10101048
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
@@ -1041,7 +1079,7 @@ impl CurrentDepGraph {
10411079
forbidden_edge,
10421080
total_read_count: AtomicU64::new(0),
10431081
total_duplicate_read_count: AtomicU64::new(0),
1044-
serializer: Lock::new(Serializer::new(file, prev_graph)),
1082+
serializer: Lock::new(Serializer::new(file, prev_graph, invalidated)),
10451083
}
10461084
}
10471085

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)