Skip to content

Commit 285731b

Browse files
committed
Avoid locking the dep graph in read_index
1 parent 0e45c3e commit 285731b

File tree

1 file changed

+48
-35
lines changed

1 file changed

+48
-35
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1313
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1414
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
1515
use smallvec::SmallVec;
16-
use rustc_data_structures::sync::{Lrc, Lock};
16+
use rustc_data_structures::sync::{Lrc, Lock, AtomicU64, Ordering::Relaxed};
17+
use rustc_data_structures::vec::SmallVecExt;
1718
use std::env;
1819
use std::hash::Hash;
1920
use ty::{self, TyCtxt};
@@ -69,6 +70,8 @@ struct DepGraphData {
6970
/// current one anymore.
7071
current: Lock<CurrentDepGraph>,
7172

73+
current_atomic: CurrentDepGraphAtomic,
74+
7275
/// The dep-graph from the previous compilation session. It contains all
7376
/// nodes and edges as well as all fingerprints of nodes that have them.
7477
previous: PreviousDepGraph,
@@ -98,11 +101,13 @@ impl DepGraph {
98101

99102
let fingerprints = IndexVec::from_elem_n(Fingerprint::ZERO,
100103
(prev_graph_node_count * 115) / 100);
104+
let (current, current_atomic) = CurrentDepGraph::new();
101105
DepGraph {
102106
data: Some(Lrc::new(DepGraphData {
103107
previous_work_products: prev_work_products,
104108
dep_node_debug: Default::default(),
105-
current: Lock::new(CurrentDepGraph::new()),
109+
current: Lock::new(current),
110+
current_atomic,
106111
previous: prev_graph,
107112
colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)),
108113
loaded_from_cache: Default::default(),
@@ -446,9 +451,10 @@ impl DepGraph {
446451
#[inline]
447452
pub fn read(&self, v: DepNode) {
448453
if let Some(ref data) = self.data {
449-
let mut current = data.current.borrow_mut();
454+
let current = data.current.borrow_mut();
450455
if let Some(&dep_node_index) = current.node_to_node_index.get(&v) {
451-
current.read_index(dep_node_index);
456+
std::mem::drop(current);
457+
data.current_atomic.read_index(&data.current, dep_node_index);
452458
} else {
453459
bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
454460
}
@@ -458,7 +464,7 @@ impl DepGraph {
458464
#[inline]
459465
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
460466
if let Some(ref data) = self.data {
461-
data.current.borrow_mut().read_index(dep_node_index);
467+
data.current_atomic.read_index(&data.current, dep_node_index);
462468
}
463469
}
464470

@@ -549,9 +555,10 @@ impl DepGraph {
549555
}
550556

551557
pub fn edge_deduplication_data(&self) -> (u64, u64) {
552-
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
558+
let current_dep_graph = &self.data.as_ref().unwrap().current_atomic;
553559

554-
(current_dep_graph.total_read_count, current_dep_graph.total_duplicate_read_count)
560+
(current_dep_graph.total_read_count.load(Relaxed),
561+
current_dep_graph.total_duplicate_read_count.load(Relaxed))
555562
}
556563

557564
pub fn serialize(&self) -> SerializedDepGraph {
@@ -936,6 +943,11 @@ pub enum WorkProductFileKind {
936943
BytecodeCompressed,
937944
}
938945

946+
pub(super) struct CurrentDepGraphAtomic {
947+
total_read_count: AtomicU64,
948+
total_duplicate_read_count: AtomicU64,
949+
}
950+
939951
pub(super) struct CurrentDepGraph {
940952
nodes: IndexVec<DepNodeIndex, DepNode>,
941953
edges: IndexVec<DepNodeIndex, SmallVec<[DepNodeIndex; 8]>>,
@@ -954,13 +966,10 @@ pub(super) struct CurrentDepGraph {
954966
// each anon node. The session-key is just a random number generated when
955967
// the DepGraph is created.
956968
anon_id_seed: Fingerprint,
957-
958-
total_read_count: u64,
959-
total_duplicate_read_count: u64,
960969
}
961970

962971
impl CurrentDepGraph {
963-
fn new() -> CurrentDepGraph {
972+
fn new() -> (CurrentDepGraph, CurrentDepGraphAtomic) {
964973
use std::time::{SystemTime, UNIX_EPOCH};
965974

966975
let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
@@ -983,15 +992,16 @@ impl CurrentDepGraph {
983992
None
984993
};
985994

986-
CurrentDepGraph {
995+
(CurrentDepGraph {
987996
nodes: IndexVec::new(),
988997
edges: IndexVec::new(),
989998
node_to_node_index: Default::default(),
990999
anon_id_seed: stable_hasher.finish(),
9911000
forbidden_edge,
992-
total_read_count: 0,
993-
total_duplicate_read_count: 0,
994-
}
1001+
}, CurrentDepGraphAtomic {
1002+
total_read_count: AtomicU64::new(0),
1003+
total_duplicate_read_count: AtomicU64::new(0),
1004+
})
9951005
}
9961006

9971007
#[inline(always)]
@@ -1085,22 +1095,39 @@ impl CurrentDepGraph {
10851095
}
10861096
}
10871097

1088-
fn read_index(&mut self, source: DepNodeIndex) {
1098+
fn alloc_node(&mut self,
1099+
dep_node: DepNode,
1100+
edges: SmallVec<[DepNodeIndex; 8]>)
1101+
-> DepNodeIndex {
1102+
debug_assert_eq!(self.edges.len(), self.nodes.len());
1103+
debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
1104+
debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
1105+
let dep_node_index = DepNodeIndex::new(self.nodes.len());
1106+
self.nodes.push(dep_node);
1107+
self.node_to_node_index.insert(dep_node, dep_node_index);
1108+
self.edges.push(edges);
1109+
dep_node_index
1110+
}
1111+
}
1112+
1113+
impl CurrentDepGraphAtomic {
1114+
fn read_index(&self, lock: &Lock<CurrentDepGraph>, source: DepNodeIndex) {
10891115
ty::tls::with_context_opt(|icx| {
10901116
let icx = if let Some(icx) = icx { icx } else { return };
10911117
match *icx.task {
10921118
OpenTask::Regular(ref task) => {
10931119
let mut task = task.lock();
1094-
self.total_read_count += 1;
1120+
self.total_read_count.fetch_add(1, Relaxed);
10951121
// FIXME: Only use the set of the SmallVec moved to the heap
10961122
// Use an array and switch to the set after?
10971123
if task.read_set.insert(source) {
1098-
task.reads.push(source);
1124+
task.reads.push_light(source);
10991125

11001126
if cfg!(debug_assertions) {
1101-
if let Some(ref forbidden_edge) = self.forbidden_edge {
1127+
let graph = lock.lock();
1128+
if let Some(ref forbidden_edge) = graph.forbidden_edge {
11021129
let target = &task.node;
1103-
let source = self.nodes[source];
1130+
let source = graph.nodes[source];
11041131
if forbidden_edge.test(&source, &target) {
11051132
bug!("forbidden edge {:?} -> {:?} created",
11061133
source,
@@ -1109,7 +1136,7 @@ impl CurrentDepGraph {
11091136
}
11101137
}
11111138
} else {
1112-
self.total_duplicate_read_count += 1;
1139+
self.total_duplicate_read_count.fetch_add(1, Relaxed);
11131140
}
11141141
}
11151142
OpenTask::Anon(ref task) => {
@@ -1124,20 +1151,6 @@ impl CurrentDepGraph {
11241151
}
11251152
})
11261153
}
1127-
1128-
fn alloc_node(&mut self,
1129-
dep_node: DepNode,
1130-
edges: SmallVec<[DepNodeIndex; 8]>)
1131-
-> DepNodeIndex {
1132-
debug_assert_eq!(self.edges.len(), self.nodes.len());
1133-
debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
1134-
debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
1135-
let dep_node_index = DepNodeIndex::new(self.nodes.len());
1136-
self.nodes.push(dep_node);
1137-
self.node_to_node_index.insert(dep_node, dep_node_index);
1138-
self.edges.push(edges);
1139-
dep_node_index
1140-
}
11411154
}
11421155

11431156
pub struct RegularOpenTask {

0 commit comments

Comments
 (0)