Skip to content

Commit cd2747e

Browse files
committed
Use more fine grained locks for the dep graph
1 parent 9b7150a commit cd2747e

File tree

2 files changed

+59
-68
lines changed

2 files changed

+59
-68
lines changed

src/librustc/dep_graph/graph.rs

Lines changed: 57 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ 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, AtomicU32, Ordering};
6+
use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering};
7+
use std::sync::atomic::Ordering::{Acquire, SeqCst};
78
use std::env;
89
use std::hash::Hash;
910
use std::collections::hash_map::Entry;
@@ -54,7 +55,7 @@ struct DepGraphData {
5455
/// tracking. The `current` field is the dependency graph of only the
5556
/// current compilation session: We don't merge the previous dep-graph into
5657
/// current one anymore.
57-
current: Lock<CurrentDepGraph>,
58+
current: CurrentDepGraph,
5859

5960
/// The dep-graph from the previous compilation session. It contains all
6061
/// nodes and edges as well as all fingerprints of nodes that have them.
@@ -77,7 +78,7 @@ struct DepGraphData {
7778
dep_node_debug: Lock<FxHashMap<DepNode, String>>,
7879

7980
// Used for testing, only populated when -Zquery-dep-graph is specified.
80-
loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>,
81+
loaded_from_cache: Lock<FxHashMap<DepNode, bool>>,
8182
}
8283

8384
pub fn hash_result<R>(hcx: &mut StableHashingContext<'_>, result: &R) -> Option<Fingerprint>
@@ -99,7 +100,7 @@ impl DepGraph {
99100
data: Some(Lrc::new(DepGraphData {
100101
previous_work_products: prev_work_products,
101102
dep_node_debug: Default::default(),
102-
current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
103+
current: CurrentDepGraph::new(prev_graph_node_count),
103104
emitting_diagnostics: Default::default(),
104105
emitting_diagnostics_cond_var: Condvar::new(),
105106
previous: prev_graph,
@@ -122,13 +123,13 @@ impl DepGraph {
122123
}
123124

124125
pub fn query(&self) -> DepGraphQuery {
125-
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
126-
let nodes: Vec<_> = current_dep_graph.data.iter().map(|n| n.node).collect();
126+
let data = self.data.as_ref().unwrap().current.data.lock();
127+
let nodes: Vec<_> = data.iter().map(|n| n.node).collect();
127128
let mut edges = Vec::new();
128-
for (from, edge_targets) in current_dep_graph.data.iter()
129+
for (from, edge_targets) in data.iter()
129130
.map(|d| (d.node, &d.edges)) {
130131
for &edge_target in edge_targets.iter() {
131-
let to = current_dep_graph.data[edge_target].node;
132+
let to = data[edge_target].node;
132133
edges.push((from, to));
133134
}
134135
}
@@ -207,7 +208,7 @@ impl DepGraph {
207208
read_set: Default::default(),
208209
}),
209210
|data, key, fingerprint, task| {
210-
data.borrow_mut().complete_task(key, task.unwrap(), fingerprint)
211+
data.complete_task(key, task.unwrap(), fingerprint)
211212
},
212213
hash_result)
213214
}
@@ -228,7 +229,7 @@ impl DepGraph {
228229
self.with_task_impl(key, cx, input, true, identity_fn,
229230
|_| None,
230231
|data, key, fingerprint, _| {
231-
data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint)
232+
data.alloc_node(key, SmallVec::new(), fingerprint)
232233
},
233234
hash_result::<R>)
234235
}
@@ -241,7 +242,7 @@ impl DepGraph {
241242
no_tcx: bool,
242243
task: fn(C, A) -> R,
243244
create_task: fn(DepNode) -> Option<TaskDeps>,
244-
finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
245+
finish_task_and_alloc_depnode: fn(&CurrentDepGraph,
245246
DepNode,
246247
Fingerprint,
247248
Option<TaskDeps>) -> DepNodeIndex,
@@ -363,7 +364,6 @@ impl DepGraph {
363364
(r, task_deps.into_inner())
364365
});
365366
let dep_node_index = data.current
366-
.borrow_mut()
367367
.complete_anon_task(dep_kind, task_deps);
368368
(result, dep_node_index)
369369
} else {
@@ -387,18 +387,17 @@ impl DepGraph {
387387
self.with_task_impl(key, cx, arg, false, task,
388388
|_| None,
389389
|data, key, fingerprint, _| {
390-
let mut current = data.borrow_mut();
391-
current.alloc_node(key, smallvec![], fingerprint)
390+
data.alloc_node(key, smallvec![], fingerprint)
392391
},
393392
hash_result)
394393
}
395394

396395
#[inline]
397396
pub fn read(&self, v: DepNode) {
398397
if let Some(ref data) = self.data {
399-
let current = data.current.borrow_mut();
400-
if let Some(&dep_node_index) = current.node_to_node_index.get(&v) {
401-
std::mem::drop(current);
398+
let map = data.current.node_to_node_index.lock();
399+
if let Some(dep_node_index) = map.get(&v).copied() {
400+
std::mem::drop(map);
402401
data.read_index(dep_node_index);
403402
} else {
404403
bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
@@ -419,8 +418,8 @@ impl DepGraph {
419418
.as_ref()
420419
.unwrap()
421420
.current
422-
.borrow_mut()
423421
.node_to_node_index
422+
.lock()
424423
.get(dep_node)
425424
.cloned()
426425
.unwrap()
@@ -429,16 +428,16 @@ impl DepGraph {
429428
#[inline]
430429
pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool {
431430
if let Some(ref data) = self.data {
432-
data.current.borrow_mut().node_to_node_index.contains_key(dep_node)
431+
data.current.node_to_node_index.lock().contains_key(dep_node)
433432
} else {
434433
false
435434
}
436435
}
437436

438437
#[inline]
439438
pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint {
440-
let current = self.data.as_ref().expect("dep graph enabled").current.borrow_mut();
441-
current.data[dep_node_index].fingerprint
439+
let data = self.data.as_ref().expect("dep graph enabled").current.data.lock();
440+
data[dep_node_index].fingerprint
442441
}
443442

444443
pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
@@ -492,32 +491,29 @@ impl DepGraph {
492491

493492
pub fn edge_deduplication_data(&self) -> Option<(u64, u64)> {
494493
if cfg!(debug_assertions) {
495-
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
494+
let current_dep_graph = &self.data.as_ref().unwrap().current;
496495

497-
Some((current_dep_graph.total_read_count,
498-
current_dep_graph.total_duplicate_read_count))
496+
Some((current_dep_graph.total_read_count.load(Acquire),
497+
current_dep_graph.total_duplicate_read_count.load(Acquire)))
499498
} else {
500499
None
501500
}
502501
}
503502

504503
pub fn serialize(&self) -> SerializedDepGraph {
505-
let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
504+
let data = self.data.as_ref().unwrap().current.data.lock();
506505

507506
let fingerprints: IndexVec<SerializedDepNodeIndex, _> =
508-
current_dep_graph.data.iter().map(|d| d.fingerprint).collect();
507+
data.iter().map(|d| d.fingerprint).collect();
509508
let nodes: IndexVec<SerializedDepNodeIndex, _> =
510-
current_dep_graph.data.iter().map(|d| d.node).collect();
509+
data.iter().map(|d| d.node).collect();
511510

512-
let total_edge_count: usize = current_dep_graph.data.iter()
513-
.map(|d| d.edges.len())
514-
.sum();
511+
let total_edge_count: usize = data.iter().map(|d| d.edges.len()).sum();
515512

516513
let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
517514
let mut edge_list_data = Vec::with_capacity(total_edge_count);
518515

519-
for (current_dep_node_index, edges) in current_dep_graph.data.iter_enumerated()
520-
.map(|(i, d)| (i, &d.edges)) {
516+
for (current_dep_node_index, edges) in data.iter_enumerated().map(|(i, d)| (i, &d.edges)) {
521517
let start = edge_list_data.len() as u32;
522518
// This should really just be a memcpy :/
523519
edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index())));
@@ -746,15 +742,13 @@ impl DepGraph {
746742
// There may be multiple threads trying to mark the same dep node green concurrently
747743

748744
let dep_node_index = {
749-
let mut current = data.current.borrow_mut();
750-
751745
// Copy the fingerprint from the previous graph,
752746
// so we don't have to recompute it
753747
let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index);
754748

755749
// We allocating an entry for the node in the current dependency graph and
756750
// adding all the appropriate edges imported from the previous graph
757-
current.intern_node(*dep_node, current_deps, fingerprint)
751+
data.current.intern_node(*dep_node, current_deps, fingerprint)
758752
};
759753

760754
// ... emitting any stored diagnostic ...
@@ -889,23 +883,21 @@ impl DepGraph {
889883
}
890884
}
891885

892-
pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) {
893-
debug!("mark_loaded_from_cache({:?}, {})",
894-
self.data.as_ref().unwrap().current.borrow().data[dep_node_index].node,
895-
state);
886+
pub fn mark_loaded_from_cache(&self, dep_node: DepNode, state: bool) {
887+
debug!("mark_loaded_from_cache({:?}, {})", dep_node, state);
896888

897889
self.data
898890
.as_ref()
899891
.unwrap()
900892
.loaded_from_cache
901893
.borrow_mut()
902-
.insert(dep_node_index, state);
894+
.insert(dep_node, state);
903895
}
904896

897+
// FIXME: Remove this since it appears to be unused?
905898
pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option<bool> {
906899
let data = self.data.as_ref().unwrap();
907-
let dep_node_index = data.current.borrow().node_to_node_index[dep_node];
908-
data.loaded_from_cache.borrow().get(&dep_node_index).cloned()
900+
data.loaded_from_cache.borrow().get(&dep_node).cloned()
909901
}
910902
}
911903

@@ -962,8 +954,8 @@ struct DepNodeData {
962954
}
963955

964956
pub(super) struct CurrentDepGraph {
965-
data: IndexVec<DepNodeIndex, DepNodeData>,
966-
node_to_node_index: FxHashMap<DepNode, DepNodeIndex>,
957+
data: Lock<IndexVec<DepNodeIndex, DepNodeData>>,
958+
node_to_node_index: Lock<FxHashMap<DepNode, DepNodeIndex>>,
967959
#[allow(dead_code)]
968960
forbidden_edge: Option<EdgeFilter>,
969961

@@ -980,8 +972,8 @@ pub(super) struct CurrentDepGraph {
980972
/// the `DepGraph` is created.
981973
anon_id_seed: Fingerprint,
982974

983-
total_read_count: u64,
984-
total_duplicate_read_count: u64,
975+
total_read_count: AtomicU64,
976+
total_duplicate_read_count: AtomicU64,
985977
}
986978

987979
impl CurrentDepGraph {
@@ -1015,28 +1007,28 @@ impl CurrentDepGraph {
10151007
let new_node_count_estimate = (prev_graph_node_count * 102) / 100 + 200;
10161008

10171009
CurrentDepGraph {
1018-
data: IndexVec::with_capacity(new_node_count_estimate),
1019-
node_to_node_index: FxHashMap::with_capacity_and_hasher(
1010+
data: Lock::new(IndexVec::with_capacity(new_node_count_estimate)),
1011+
node_to_node_index: Lock::new(FxHashMap::with_capacity_and_hasher(
10201012
new_node_count_estimate,
10211013
Default::default(),
1022-
),
1014+
)),
10231015
anon_id_seed: stable_hasher.finish(),
10241016
forbidden_edge,
1025-
total_read_count: 0,
1026-
total_duplicate_read_count: 0,
1017+
total_read_count: AtomicU64::new(0),
1018+
total_duplicate_read_count: AtomicU64::new(0),
10271019
}
10281020
}
10291021

10301022
fn complete_task(
1031-
&mut self,
1023+
&self,
10321024
node: DepNode,
10331025
task_deps: TaskDeps,
10341026
fingerprint: Fingerprint
10351027
) -> DepNodeIndex {
10361028
self.alloc_node(node, task_deps.reads, fingerprint)
10371029
}
10381030

1039-
fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex {
1031+
fn complete_anon_task(&self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex {
10401032
debug_assert!(!kind.is_eval_always());
10411033

10421034
let mut hasher = StableHasher::new();
@@ -1061,28 +1053,27 @@ impl CurrentDepGraph {
10611053
}
10621054

10631055
fn alloc_node(
1064-
&mut self,
1056+
&self,
10651057
dep_node: DepNode,
10661058
edges: SmallVec<[DepNodeIndex; 8]>,
10671059
fingerprint: Fingerprint
10681060
) -> DepNodeIndex {
1069-
debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
1061+
debug_assert!(!self.node_to_node_index.lock().contains_key(&dep_node));
10701062
self.intern_node(dep_node, edges, fingerprint)
10711063
}
10721064

10731065
fn intern_node(
1074-
&mut self,
1066+
&self,
10751067
dep_node: DepNode,
10761068
edges: SmallVec<[DepNodeIndex; 8]>,
10771069
fingerprint: Fingerprint
10781070
) -> DepNodeIndex {
1079-
debug_assert_eq!(self.node_to_node_index.len(), self.data.len());
1080-
1081-
match self.node_to_node_index.entry(dep_node) {
1071+
match self.node_to_node_index.lock().entry(dep_node) {
10821072
Entry::Occupied(entry) => *entry.get(),
10831073
Entry::Vacant(entry) => {
1084-
let dep_node_index = DepNodeIndex::new(self.data.len());
1085-
self.data.push(DepNodeData {
1074+
let mut data = self.data.lock();
1075+
let dep_node_index = DepNodeIndex::new(data.len());
1076+
data.push(DepNodeData {
10861077
node: dep_node,
10871078
edges,
10881079
fingerprint
@@ -1101,17 +1092,17 @@ impl DepGraphData {
11011092
if let Some(task_deps) = icx.task_deps {
11021093
let mut task_deps = task_deps.lock();
11031094
if cfg!(debug_assertions) {
1104-
self.current.lock().total_read_count += 1;
1095+
self.current.total_read_count.fetch_add(1, SeqCst);
11051096
}
11061097
if task_deps.read_set.insert(source) {
11071098
task_deps.reads.push(source);
11081099

11091100
#[cfg(debug_assertions)]
11101101
{
11111102
if let Some(target) = task_deps.node {
1112-
let graph = self.current.lock();
1113-
if let Some(ref forbidden_edge) = graph.forbidden_edge {
1114-
let source = graph.data[source].node;
1103+
let data = self.current.data.lock();
1104+
if let Some(ref forbidden_edge) = self.current.forbidden_edge {
1105+
let source = data[source].node;
11151106
if forbidden_edge.test(&source, &target) {
11161107
bug!("forbidden edge {:?} -> {:?} created",
11171108
source,
@@ -1121,7 +1112,7 @@ impl DepGraphData {
11211112
}
11221113
}
11231114
} else if cfg!(debug_assertions) {
1124-
self.current.lock().total_duplicate_read_count += 1;
1115+
self.current.total_duplicate_read_count.fetch_add(1, SeqCst);
11251116
}
11261117
}
11271118
})

src/librustc/ty/query/plumbing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ impl<'tcx> TyCtxt<'tcx> {
492492
}
493493

494494
if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) {
495-
self.dep_graph.mark_loaded_from_cache(dep_node_index, true);
495+
self.dep_graph.mark_loaded_from_cache(*dep_node, true);
496496
}
497497

498498
result
@@ -568,7 +568,7 @@ impl<'tcx> TyCtxt<'tcx> {
568568
profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
569569

570570
if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) {
571-
self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
571+
self.dep_graph.mark_loaded_from_cache(dep_node, false);
572572
}
573573

574574
if dep_node.kind != crate::dep_graph::DepKind::Null {

0 commit comments

Comments
 (0)