Skip to content

Commit 527b8d4

Browse files
committed
Auto merge of #57065 - Zoxc:graph-tweaks, r=michaelwoerister
Optimize try_mark_green and eliminate the lock on dep node colors Blocked on #56614 r? @michaelwoerister
2 parents 38650b6 + 1313678 commit 527b8d4

File tree

4 files changed

+117
-113
lines changed

4 files changed

+117
-113
lines changed

src/librustc/dep_graph/graph.rs

+99-63
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
33
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
55
use smallvec::SmallVec;
6-
use rustc_data_structures::sync::{Lrc, Lock};
6+
use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering};
77
use std::env;
88
use std::hash::Hash;
99
use std::collections::hash_map::Entry;
@@ -58,7 +58,7 @@ struct DepGraphData {
5858
/// nodes and edges as well as all fingerprints of nodes that have them.
5959
previous: PreviousDepGraph,
6060

61-
colors: Lock<DepNodeColorMap>,
61+
colors: DepNodeColorMap,
6262

6363
/// When we load, there may be `.o` files, cached mir, or other such
6464
/// things available to us. If we find that they are not dirty, we
@@ -84,7 +84,7 @@ impl DepGraph {
8484
dep_node_debug: Default::default(),
8585
current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
8686
previous: prev_graph,
87-
colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)),
87+
colors: DepNodeColorMap::new(prev_graph_node_count),
8888
loaded_from_cache: Default::default(),
8989
})),
9090
}
@@ -282,12 +282,11 @@ impl DepGraph {
282282
DepNodeColor::Red
283283
};
284284

285-
let mut colors = data.colors.borrow_mut();
286-
debug_assert!(colors.get(prev_index).is_none(),
285+
debug_assert!(data.colors.get(prev_index).is_none(),
287286
"DepGraph::with_task() - Duplicate DepNodeColor \
288287
insertion for {:?}", key);
289288

290-
colors.insert(prev_index, color);
289+
data.colors.insert(prev_index, color);
291290
}
292291

293292
(result, dep_node_index)
@@ -502,7 +501,7 @@ impl DepGraph {
502501
pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
503502
if let Some(ref data) = self.data {
504503
if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) {
505-
return data.colors.borrow().get(prev_index)
504+
return data.colors.get(prev_index)
506505
} else {
507506
// This is a node that did not exist in the previous compilation
508507
// session, so we consider it to be red.
@@ -513,56 +512,89 @@ impl DepGraph {
513512
None
514513
}
515514

516-
pub fn try_mark_green<'tcx>(&self,
517-
tcx: TyCtxt<'_, 'tcx, 'tcx>,
518-
dep_node: &DepNode)
519-
-> Option<DepNodeIndex> {
520-
debug!("try_mark_green({:?}) - BEGIN", dep_node);
521-
let data = self.data.as_ref().unwrap();
515+
/// Try to read a node index for the node dep_node.
516+
/// A node will have an index, when it's already been marked green, or when we can mark it
517+
/// green. This function will mark the current task as a reader of the specified node, when
518+
/// a node index can be found for that node.
519+
pub fn try_mark_green_and_read(
520+
&self,
521+
tcx: TyCtxt<'_, '_, '_>,
522+
dep_node: &DepNode
523+
) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
524+
self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| {
525+
debug_assert!(self.is_green(&dep_node));
526+
self.read_index(dep_node_index);
527+
(prev_index, dep_node_index)
528+
})
529+
}
522530

523-
#[cfg(not(parallel_queries))]
524-
debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
525-
526-
if dep_node.kind.is_input() {
527-
// We should only hit try_mark_green() for inputs that do not exist
528-
// anymore in the current compilation session. Existing inputs are
529-
// eagerly marked as either red/green before any queries are
530-
// executed.
531-
debug_assert!(dep_node.extract_def_id(tcx).is_none());
532-
debug!("try_mark_green({:?}) - END - DepNode is deleted input", dep_node);
533-
return None;
534-
}
531+
pub fn try_mark_green(
532+
&self,
533+
tcx: TyCtxt<'_, '_, '_>,
534+
dep_node: &DepNode
535+
) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
536+
debug_assert!(!dep_node.kind.is_input());
537+
538+
// Return None if the dep graph is disabled
539+
let data = self.data.as_ref()?;
540+
541+
// Return None if the dep node didn't exist in the previous session
542+
let prev_index = data.previous.node_to_index_opt(dep_node)?;
535543

536-
let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) {
537-
Some(prev) => {
544+
match data.colors.get(prev_index) {
545+
Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)),
546+
Some(DepNodeColor::Red) => None,
547+
None => {
538548
// This DepNode and the corresponding query invocation existed
539549
// in the previous compilation session too, so we can try to
540550
// mark it as green by recursively marking all of its
541551
// dependencies green.
542-
prev
543-
}
544-
None => {
545-
// This DepNode did not exist in the previous compilation session,
546-
// so we cannot mark it as green.
547-
debug!("try_mark_green({:?}) - END - DepNode does not exist in \
548-
current compilation session anymore", dep_node);
549-
return None
552+
self.try_mark_previous_green(
553+
tcx.global_tcx(),
554+
data,
555+
prev_index,
556+
&dep_node
557+
).map(|dep_node_index| {
558+
(prev_index, dep_node_index)
559+
})
550560
}
551-
};
561+
}
562+
}
563+
564+
/// Try to mark a dep-node which existed in the previous compilation session as green
565+
fn try_mark_previous_green<'tcx>(
566+
&self,
567+
tcx: TyCtxt<'_, 'tcx, 'tcx>,
568+
data: &DepGraphData,
569+
prev_dep_node_index: SerializedDepNodeIndex,
570+
dep_node: &DepNode
571+
) -> Option<DepNodeIndex> {
572+
debug!("try_mark_previous_green({:?}) - BEGIN", dep_node);
552573

553-
debug_assert!(data.colors.borrow().get(prev_dep_node_index).is_none());
574+
#[cfg(not(parallel_queries))]
575+
{
576+
debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
577+
debug_assert!(data.colors.get(prev_dep_node_index).is_none());
578+
}
579+
580+
// We never try to mark inputs as green
581+
debug_assert!(!dep_node.kind.is_input());
582+
583+
debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node);
584+
585+
let prev_deps = data.previous.edge_targets_from(prev_dep_node_index);
554586

555587
let mut current_deps = SmallVec::new();
556588

557589
for &dep_dep_node_index in prev_deps {
558-
let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
590+
let dep_dep_node_color = data.colors.get(dep_dep_node_index);
559591

560592
match dep_dep_node_color {
561593
Some(DepNodeColor::Green(node_index)) => {
562594
// This dependency has been marked as green before, we are
563595
// still fine and can continue with checking the other
564596
// dependencies.
565-
debug!("try_mark_green({:?}) --- found dependency {:?} to \
597+
debug!("try_mark_previous_green({:?}) --- found dependency {:?} to \
566598
be immediately green",
567599
dep_node,
568600
data.previous.index_to_node(dep_dep_node_index));
@@ -573,7 +605,7 @@ impl DepGraph {
573605
// compared to the previous compilation session. We cannot
574606
// mark the DepNode as green and also don't need to bother
575607
// with checking any of the other dependencies.
576-
debug!("try_mark_green({:?}) - END - dependency {:?} was \
608+
debug!("try_mark_previous_green({:?}) - END - dependency {:?} was \
577609
immediately red",
578610
dep_node,
579611
data.previous.index_to_node(dep_dep_node_index));
@@ -585,12 +617,18 @@ impl DepGraph {
585617
// We don't know the state of this dependency. If it isn't
586618
// an input node, let's try to mark it green recursively.
587619
if !dep_dep_node.kind.is_input() {
588-
debug!("try_mark_green({:?}) --- state of dependency {:?} \
620+
debug!("try_mark_previous_green({:?}) --- state of dependency {:?} \
589621
is unknown, trying to mark it green", dep_node,
590622
dep_dep_node);
591623

592-
if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
593-
debug!("try_mark_green({:?}) --- managed to MARK \
624+
let node_index = self.try_mark_previous_green(
625+
tcx,
626+
data,
627+
dep_dep_node_index,
628+
dep_dep_node
629+
);
630+
if let Some(node_index) = node_index {
631+
debug!("try_mark_previous_green({:?}) --- managed to MARK \
594632
dependency {:?} as green", dep_node, dep_dep_node);
595633
current_deps.push(node_index);
596634
continue;
@@ -620,28 +658,28 @@ impl DepGraph {
620658
}
621659

622660
// We failed to mark it green, so we try to force the query.
623-
debug!("try_mark_green({:?}) --- trying to force \
661+
debug!("try_mark_previous_green({:?}) --- trying to force \
624662
dependency {:?}", dep_node, dep_dep_node);
625663
if ::ty::query::force_from_dep_node(tcx, dep_dep_node) {
626-
let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
664+
let dep_dep_node_color = data.colors.get(dep_dep_node_index);
627665

628666
match dep_dep_node_color {
629667
Some(DepNodeColor::Green(node_index)) => {
630-
debug!("try_mark_green({:?}) --- managed to \
668+
debug!("try_mark_previous_green({:?}) --- managed to \
631669
FORCE dependency {:?} to green",
632670
dep_node, dep_dep_node);
633671
current_deps.push(node_index);
634672
}
635673
Some(DepNodeColor::Red) => {
636-
debug!("try_mark_green({:?}) - END - \
674+
debug!("try_mark_previous_green({:?}) - END - \
637675
dependency {:?} was red after forcing",
638676
dep_node,
639677
dep_dep_node);
640678
return None
641679
}
642680
None => {
643681
if !tcx.sess.has_errors() {
644-
bug!("try_mark_green() - Forcing the DepNode \
682+
bug!("try_mark_previous_green() - Forcing the DepNode \
645683
should have set its color")
646684
} else {
647685
// If the query we just forced has resulted
@@ -653,7 +691,7 @@ impl DepGraph {
653691
}
654692
} else {
655693
// The DepNode could not be forced.
656-
debug!("try_mark_green({:?}) - END - dependency {:?} \
694+
debug!("try_mark_previous_green({:?}) - END - dependency {:?} \
657695
could not be forced", dep_node, dep_dep_node);
658696
return None
659697
}
@@ -705,16 +743,15 @@ impl DepGraph {
705743
}
706744

707745
// ... and finally storing a "Green" entry in the color map.
708-
let mut colors = data.colors.borrow_mut();
709746
// Multiple threads can all write the same color here
710747
#[cfg(not(parallel_queries))]
711-
debug_assert!(colors.get(prev_dep_node_index).is_none(),
712-
"DepGraph::try_mark_green() - Duplicate DepNodeColor \
748+
debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
749+
"DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
713750
insertion for {:?}", dep_node);
714751

715-
colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
752+
data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
716753

717-
debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node);
754+
debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node);
718755
Some(dep_node_index)
719756
}
720757

@@ -735,9 +772,8 @@ impl DepGraph {
735772
pub fn exec_cache_promotions<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
736773
let green_nodes: Vec<DepNode> = {
737774
let data = self.data.as_ref().unwrap();
738-
let colors = data.colors.borrow();
739-
colors.values.indices().filter_map(|prev_index| {
740-
match colors.get(prev_index) {
775+
data.colors.values.indices().filter_map(|prev_index| {
776+
match data.colors.get(prev_index) {
741777
Some(DepNodeColor::Green(_)) => {
742778
let dep_node = data.previous.index_to_node(prev_index);
743779
if dep_node.cache_on_disk(tcx) {
@@ -1035,7 +1071,7 @@ pub struct TaskDeps {
10351071
// A data structure that stores Option<DepNodeColor> values as a contiguous
10361072
// array, using one u32 per entry.
10371073
struct DepNodeColorMap {
1038-
values: IndexVec<SerializedDepNodeIndex, u32>,
1074+
values: IndexVec<SerializedDepNodeIndex, AtomicU32>,
10391075
}
10401076

10411077
const COMPRESSED_NONE: u32 = 0;
@@ -1045,12 +1081,12 @@ const COMPRESSED_FIRST_GREEN: u32 = 2;
10451081
impl DepNodeColorMap {
10461082
fn new(size: usize) -> DepNodeColorMap {
10471083
DepNodeColorMap {
1048-
values: IndexVec::from_elem_n(COMPRESSED_NONE, size)
1084+
values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect(),
10491085
}
10501086
}
10511087

10521088
fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
1053-
match self.values[index] {
1089+
match self.values[index].load(Ordering::Acquire) {
10541090
COMPRESSED_NONE => None,
10551091
COMPRESSED_RED => Some(DepNodeColor::Red),
10561092
value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(
@@ -1059,10 +1095,10 @@ impl DepNodeColorMap {
10591095
}
10601096
}
10611097

1062-
fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
1063-
self.values[index] = match color {
1098+
fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
1099+
self.values[index].store(match color {
10641100
DepNodeColor::Red => COMPRESSED_RED,
10651101
DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN,
1066-
}
1102+
}, Ordering::Release)
10671103
}
10681104
}

src/librustc/dep_graph/prev.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,11 @@ impl PreviousDepGraph {
1919
}
2020

2121
#[inline]
22-
pub fn edges_from(&self,
23-
dep_node: &DepNode)
24-
-> Option<(&[SerializedDepNodeIndex], SerializedDepNodeIndex)> {
25-
self.index
26-
.get(dep_node)
27-
.map(|&node_index| {
28-
(self.data.edge_targets_from(node_index), node_index)
29-
})
22+
pub fn edge_targets_from(
23+
&self,
24+
dep_node_index: SerializedDepNodeIndex
25+
) -> &[SerializedDepNodeIndex] {
26+
self.data.edge_targets_from(dep_node_index)
3027
}
3128

3229
#[inline]

0 commit comments

Comments
 (0)