@@ -3,7 +3,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
33use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
44use rustc_index:: vec:: { Idx , IndexVec } ;
55use 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 :: SeqCst ;
78use std:: env;
89use std:: hash:: Hash ;
910use std:: collections:: hash_map:: Entry ;
@@ -53,7 +54,7 @@ struct DepGraphData {
5354 /// tracking. The `current` field is the dependency graph of only the
5455 /// current compilation session: We don't merge the previous dep-graph into
5556 /// current one anymore.
56- current : Lock < CurrentDepGraph > ,
57+ current : CurrentDepGraph ,
5758
5859 /// The dep-graph from the previous compilation session. It contains all
5960 /// nodes and edges as well as all fingerprints of nodes that have them.
@@ -95,7 +96,7 @@ impl DepGraph {
9596 data : Some ( Lrc :: new ( DepGraphData {
9697 previous_work_products : prev_work_products,
9798 dep_node_debug : Default :: default ( ) ,
98- current : Lock :: new ( CurrentDepGraph :: new ( prev_graph_node_count) ) ,
99+ current : CurrentDepGraph :: new ( prev_graph_node_count) ,
99100 emitting_diagnostics : Default :: default ( ) ,
100101 emitting_diagnostics_cond_var : Condvar :: new ( ) ,
101102 previous : prev_graph,
@@ -117,13 +118,12 @@ impl DepGraph {
117118 }
118119
119120 pub fn query ( & self ) -> DepGraphQuery {
120- let current_dep_graph = self . data . as_ref ( ) . unwrap ( ) . current . borrow ( ) ;
121- let nodes: Vec < _ > = current_dep_graph . data . iter ( ) . map ( |n| n. node ) . collect ( ) ;
121+ let data = self . data . as_ref ( ) . unwrap ( ) . current . data . lock ( ) ;
122+ let nodes: Vec < _ > = data. iter ( ) . map ( |n| n. node ) . collect ( ) ;
122123 let mut edges = Vec :: new ( ) ;
123- for ( from, edge_targets) in current_dep_graph. data . iter ( )
124- . map ( |d| ( d. node , & d. edges ) ) {
124+ for ( from, edge_targets) in data. iter ( ) . map ( |d| ( d. node , & d. edges ) ) {
125125 for & edge_target in edge_targets. iter ( ) {
126- let to = current_dep_graph . data [ edge_target] . node ;
126+ let to = data[ edge_target] . node ;
127127 edges. push ( ( from, to) ) ;
128128 }
129129 }
@@ -202,7 +202,7 @@ impl DepGraph {
202202 read_set : Default :: default ( ) ,
203203 } ) ,
204204 |data, key, fingerprint, task| {
205- data. borrow_mut ( ) . complete_task ( key, task. unwrap ( ) , fingerprint)
205+ data. complete_task ( key, task. unwrap ( ) , fingerprint)
206206 } ,
207207 hash_result)
208208 }
@@ -223,7 +223,7 @@ impl DepGraph {
223223 self . with_task_impl ( key, cx, input, true , identity_fn,
224224 |_| None ,
225225 |data, key, fingerprint, _| {
226- data. borrow_mut ( ) . alloc_node ( key, SmallVec :: new ( ) , fingerprint)
226+ data. alloc_node ( key, SmallVec :: new ( ) , fingerprint)
227227 } ,
228228 hash_result :: < R > )
229229 }
@@ -236,7 +236,7 @@ impl DepGraph {
236236 no_tcx : bool ,
237237 task : fn ( C , A ) -> R ,
238238 create_task : fn ( DepNode ) -> Option < TaskDeps > ,
239- finish_task_and_alloc_depnode : fn ( & Lock < CurrentDepGraph > ,
239+ finish_task_and_alloc_depnode : fn ( & CurrentDepGraph ,
240240 DepNode ,
241241 Fingerprint ,
242242 Option < TaskDeps > ) -> DepNodeIndex ,
@@ -350,7 +350,6 @@ impl DepGraph {
350350 ( r, task_deps. into_inner ( ) )
351351 } ) ;
352352 let dep_node_index = data. current
353- . borrow_mut ( )
354353 . complete_anon_task ( dep_kind, task_deps) ;
355354 ( result, dep_node_index)
356355 } else {
@@ -374,18 +373,17 @@ impl DepGraph {
374373 self . with_task_impl ( key, cx, arg, false , task,
375374 |_| None ,
376375 |data, key, fingerprint, _| {
377- let mut current = data. borrow_mut ( ) ;
378- current. alloc_node ( key, smallvec ! [ ] , fingerprint)
376+ data. alloc_node ( key, smallvec ! [ ] , fingerprint)
379377 } ,
380378 hash_result)
381379 }
382380
383381 #[ inline]
384382 pub fn read ( & self , v : DepNode ) {
385383 if let Some ( ref data) = self . data {
386- let current = data. current . borrow_mut ( ) ;
387- if let Some ( & dep_node_index) = current . node_to_node_index . get ( & v) {
388- std:: mem:: drop ( current ) ;
384+ let map = data. current . node_to_node_index . lock ( ) ;
385+ if let Some ( dep_node_index) = map . get ( & v) . copied ( ) {
386+ std:: mem:: drop ( map ) ;
389387 data. read_index ( dep_node_index) ;
390388 } else {
391389 bug ! ( "DepKind {:?} should be pre-allocated but isn't." , v. kind)
@@ -406,8 +404,8 @@ impl DepGraph {
406404 . as_ref ( )
407405 . unwrap ( )
408406 . current
409- . borrow_mut ( )
410407 . node_to_node_index
408+ . lock ( )
411409 . get ( dep_node)
412410 . cloned ( )
413411 . unwrap ( )
@@ -416,16 +414,16 @@ impl DepGraph {
416414 #[ inline]
417415 pub fn dep_node_exists ( & self , dep_node : & DepNode ) -> bool {
418416 if let Some ( ref data) = self . data {
419- data. current . borrow_mut ( ) . node_to_node_index . contains_key ( dep_node)
417+ data. current . node_to_node_index . lock ( ) . contains_key ( dep_node)
420418 } else {
421419 false
422420 }
423421 }
424422
425423 #[ inline]
426424 pub fn fingerprint_of ( & self , dep_node_index : DepNodeIndex ) -> Fingerprint {
427- let current = self . data . as_ref ( ) . expect ( "dep graph enabled" ) . current . borrow_mut ( ) ;
428- current . data [ dep_node_index] . fingerprint
425+ let data = self . data . as_ref ( ) . expect ( "dep graph enabled" ) . current . data . lock ( ) ;
426+ data[ dep_node_index] . fingerprint
429427 }
430428
431429 pub fn prev_fingerprint_of ( & self , dep_node : & DepNode ) -> Option < Fingerprint > {
@@ -479,32 +477,29 @@ impl DepGraph {
479477
480478 pub fn edge_deduplication_data ( & self ) -> Option < ( u64 , u64 ) > {
481479 if cfg ! ( debug_assertions) {
482- let current_dep_graph = self . data . as_ref ( ) . unwrap ( ) . current . borrow ( ) ;
480+ let current_dep_graph = & self . data . as_ref ( ) . unwrap ( ) . current ;
483481
484- Some ( ( current_dep_graph. total_read_count ,
485- current_dep_graph. total_duplicate_read_count ) )
482+ Some ( ( current_dep_graph. total_read_count . load ( SeqCst ) ,
483+ current_dep_graph. total_duplicate_read_count . load ( SeqCst ) ) )
486484 } else {
487485 None
488486 }
489487 }
490488
491489 pub fn serialize ( & self ) -> SerializedDepGraph {
492- let current_dep_graph = self . data . as_ref ( ) . unwrap ( ) . current . borrow ( ) ;
490+ let data = self . data . as_ref ( ) . unwrap ( ) . current . data . lock ( ) ;
493491
494492 let fingerprints: IndexVec < SerializedDepNodeIndex , _ > =
495- current_dep_graph . data . iter ( ) . map ( |d| d. fingerprint ) . collect ( ) ;
493+ data. iter ( ) . map ( |d| d. fingerprint ) . collect ( ) ;
496494 let nodes: IndexVec < SerializedDepNodeIndex , _ > =
497- current_dep_graph . data . iter ( ) . map ( |d| d. node ) . collect ( ) ;
495+ data. iter ( ) . map ( |d| d. node ) . collect ( ) ;
498496
499- let total_edge_count: usize = current_dep_graph. data . iter ( )
500- . map ( |d| d. edges . len ( ) )
501- . sum ( ) ;
497+ let total_edge_count: usize = data. iter ( ) . map ( |d| d. edges . len ( ) ) . sum ( ) ;
502498
503499 let mut edge_list_indices = IndexVec :: with_capacity ( nodes. len ( ) ) ;
504500 let mut edge_list_data = Vec :: with_capacity ( total_edge_count) ;
505501
506- for ( current_dep_node_index, edges) in current_dep_graph. data . iter_enumerated ( )
507- . map ( |( i, d) | ( i, & d. edges ) ) {
502+ for ( current_dep_node_index, edges) in data. iter_enumerated ( ) . map ( |( i, d) | ( i, & d. edges ) ) {
508503 let start = edge_list_data. len ( ) as u32 ;
509504 // This should really just be a memcpy :/
510505 edge_list_data. extend ( edges. iter ( ) . map ( |i| SerializedDepNodeIndex :: new ( i. index ( ) ) ) ) ;
@@ -600,7 +595,7 @@ impl DepGraph {
600595
601596 #[ cfg( not( parallel_compiler) ) ]
602597 {
603- debug_assert ! ( !data. current. borrow ( ) . node_to_node_index . contains_key( dep_node) ) ;
598+ debug_assert ! ( !data. current. node_to_node_index . lock ( ) . contains_key( dep_node) ) ;
604599 debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ) ;
605600 }
606601
@@ -733,15 +728,13 @@ impl DepGraph {
733728 // There may be multiple threads trying to mark the same dep node green concurrently
734729
735730 let dep_node_index = {
736- let mut current = data. current . borrow_mut ( ) ;
737-
738731 // Copy the fingerprint from the previous graph,
739732 // so we don't have to recompute it
740733 let fingerprint = data. previous . fingerprint_by_index ( prev_dep_node_index) ;
741734
742735 // We allocating an entry for the node in the current dependency graph and
743736 // adding all the appropriate edges imported from the previous graph
744- current. intern_node ( * dep_node, current_deps, fingerprint)
737+ data . current . intern_node ( * dep_node, current_deps, fingerprint)
745738 } ;
746739
747740 // ... emitting any stored diagnostic ...
@@ -917,9 +910,27 @@ struct DepNodeData {
917910 fingerprint : Fingerprint ,
918911}
919912
913+ /// `CurrentDepGraph` stores the dependency graph for the current session.
914+ /// It will be populated as we run queries or tasks.
915+ ///
916+ /// The nodes in it are identified by an index (`DepNodeIndex`).
917+ /// The data for each node is stored in its `DepNodeData`, found in the `data` field.
918+ ///
919+ /// We never remove nodes from the graph: they are only added.
920+ ///
921+ /// This struct uses two locks internally. The `data` and `node_to_node_index` fields are
922+ /// locked separately. Operations that take a `DepNodeIndex` typically just access
923+ /// the data field.
924+ ///
925+ /// The only operation that must manipulate both locks is adding new nodes, in which case
926+ /// we first acquire the `node_to_node_index` lock and then, once a new node is to be inserted,
927+ /// acquire the lock on `data.`
920928pub ( super ) struct CurrentDepGraph {
921- data : IndexVec < DepNodeIndex , DepNodeData > ,
922- node_to_node_index : FxHashMap < DepNode , DepNodeIndex > ,
929+ data : Lock < IndexVec < DepNodeIndex , DepNodeData > > ,
930+ node_to_node_index : Lock < FxHashMap < DepNode , DepNodeIndex > > ,
931+
932+ /// Used to trap when a specific edge is added to the graph.
933+ /// This is used for debug purposes and is only active with `debug_assertions`.
923934 #[ allow( dead_code) ]
924935 forbidden_edge : Option < EdgeFilter > ,
925936
@@ -936,8 +947,10 @@ pub(super) struct CurrentDepGraph {
936947 /// the `DepGraph` is created.
937948 anon_id_seed : Fingerprint ,
938949
939- total_read_count : u64 ,
940- total_duplicate_read_count : u64 ,
950+ /// These are simple counters that are for profiling and
951+ /// debugging and only active with `debug_assertions`.
952+ total_read_count : AtomicU64 ,
953+ total_duplicate_read_count : AtomicU64 ,
941954}
942955
943956impl CurrentDepGraph {
@@ -971,28 +984,28 @@ impl CurrentDepGraph {
971984 let new_node_count_estimate = ( prev_graph_node_count * 102 ) / 100 + 200 ;
972985
973986 CurrentDepGraph {
974- data : IndexVec :: with_capacity ( new_node_count_estimate) ,
975- node_to_node_index : FxHashMap :: with_capacity_and_hasher (
987+ data : Lock :: new ( IndexVec :: with_capacity ( new_node_count_estimate) ) ,
988+ node_to_node_index : Lock :: new ( FxHashMap :: with_capacity_and_hasher (
976989 new_node_count_estimate,
977990 Default :: default ( ) ,
978- ) ,
991+ ) ) ,
979992 anon_id_seed : stable_hasher. finish ( ) ,
980993 forbidden_edge,
981- total_read_count : 0 ,
982- total_duplicate_read_count : 0 ,
994+ total_read_count : AtomicU64 :: new ( 0 ) ,
995+ total_duplicate_read_count : AtomicU64 :: new ( 0 ) ,
983996 }
984997 }
985998
986999 fn complete_task (
987- & mut self ,
1000+ & self ,
9881001 node : DepNode ,
9891002 task_deps : TaskDeps ,
9901003 fingerprint : Fingerprint
9911004 ) -> DepNodeIndex {
9921005 self . alloc_node ( node, task_deps. reads , fingerprint)
9931006 }
9941007
995- fn complete_anon_task ( & mut self , kind : DepKind , task_deps : TaskDeps ) -> DepNodeIndex {
1008+ fn complete_anon_task ( & self , kind : DepKind , task_deps : TaskDeps ) -> DepNodeIndex {
9961009 debug_assert ! ( !kind. is_eval_always( ) ) ;
9971010
9981011 let mut hasher = StableHasher :: new ( ) ;
@@ -1017,28 +1030,27 @@ impl CurrentDepGraph {
10171030 }
10181031
10191032 fn alloc_node (
1020- & mut self ,
1033+ & self ,
10211034 dep_node : DepNode ,
10221035 edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
10231036 fingerprint : Fingerprint
10241037 ) -> DepNodeIndex {
1025- debug_assert ! ( !self . node_to_node_index. contains_key( & dep_node) ) ;
1038+ debug_assert ! ( !self . node_to_node_index. lock ( ) . contains_key( & dep_node) ) ;
10261039 self . intern_node ( dep_node, edges, fingerprint)
10271040 }
10281041
10291042 fn intern_node (
1030- & mut self ,
1043+ & self ,
10311044 dep_node : DepNode ,
10321045 edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
10331046 fingerprint : Fingerprint
10341047 ) -> DepNodeIndex {
1035- debug_assert_eq ! ( self . node_to_node_index. len( ) , self . data. len( ) ) ;
1036-
1037- match self . node_to_node_index . entry ( dep_node) {
1048+ match self . node_to_node_index . lock ( ) . entry ( dep_node) {
10381049 Entry :: Occupied ( entry) => * entry. get ( ) ,
10391050 Entry :: Vacant ( entry) => {
1040- let dep_node_index = DepNodeIndex :: new ( self . data . len ( ) ) ;
1041- self . data . push ( DepNodeData {
1051+ let mut data = self . data . lock ( ) ;
1052+ let dep_node_index = DepNodeIndex :: new ( data. len ( ) ) ;
1053+ data. push ( DepNodeData {
10421054 node : dep_node,
10431055 edges,
10441056 fingerprint
@@ -1057,17 +1069,17 @@ impl DepGraphData {
10571069 if let Some ( task_deps) = icx. task_deps {
10581070 let mut task_deps = task_deps. lock ( ) ;
10591071 if cfg ! ( debug_assertions) {
1060- self . current . lock ( ) . total_read_count += 1 ;
1072+ self . current . total_read_count . fetch_add ( 1 , SeqCst ) ;
10611073 }
10621074 if task_deps. read_set . insert ( source) {
10631075 task_deps. reads . push ( source) ;
10641076
10651077 #[ cfg( debug_assertions) ]
10661078 {
10671079 if let Some ( target) = task_deps. node {
1068- let graph = self . current . lock ( ) ;
1069- if let Some ( ref forbidden_edge) = graph . forbidden_edge {
1070- let source = graph . data [ source] . node ;
1080+ let data = self . current . data . lock ( ) ;
1081+ if let Some ( ref forbidden_edge) = self . current . forbidden_edge {
1082+ let source = data[ source] . node ;
10711083 if forbidden_edge. test ( & source, & target) {
10721084 bug ! ( "forbidden edge {:?} -> {:?} created" ,
10731085 source,
@@ -1077,7 +1089,7 @@ impl DepGraphData {
10771089 }
10781090 }
10791091 } else if cfg ! ( debug_assertions) {
1080- self . current . lock ( ) . total_duplicate_read_count += 1 ;
1092+ self . current . total_duplicate_read_count . fetch_add ( 1 , SeqCst ) ;
10811093 }
10821094 }
10831095 } )
0 commit comments