@@ -3,7 +3,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
3
3
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4
4
use rustc_index:: vec:: { Idx , IndexVec } ;
5
5
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 :: SeqCst ;
7
8
use std:: env;
8
9
use std:: hash:: Hash ;
9
10
use std:: collections:: hash_map:: Entry ;
@@ -53,7 +54,7 @@ struct DepGraphData {
53
54
/// tracking. The `current` field is the dependency graph of only the
54
55
/// current compilation session: We don't merge the previous dep-graph into
55
56
/// current one anymore.
56
- current : Lock < CurrentDepGraph > ,
57
+ current : CurrentDepGraph ,
57
58
58
59
/// The dep-graph from the previous compilation session. It contains all
59
60
/// nodes and edges as well as all fingerprints of nodes that have them.
@@ -95,7 +96,7 @@ impl DepGraph {
95
96
data : Some ( Lrc :: new ( DepGraphData {
96
97
previous_work_products : prev_work_products,
97
98
dep_node_debug : Default :: default ( ) ,
98
- current : Lock :: new ( CurrentDepGraph :: new ( prev_graph_node_count) ) ,
99
+ current : CurrentDepGraph :: new ( prev_graph_node_count) ,
99
100
emitting_diagnostics : Default :: default ( ) ,
100
101
emitting_diagnostics_cond_var : Condvar :: new ( ) ,
101
102
previous : prev_graph,
@@ -117,13 +118,12 @@ impl DepGraph {
117
118
}
118
119
119
120
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 ( ) ;
122
123
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 ) ) {
125
125
for & edge_target in edge_targets. iter ( ) {
126
- let to = current_dep_graph . data [ edge_target] . node ;
126
+ let to = data[ edge_target] . node ;
127
127
edges. push ( ( from, to) ) ;
128
128
}
129
129
}
@@ -202,7 +202,7 @@ impl DepGraph {
202
202
read_set : Default :: default ( ) ,
203
203
} ) ,
204
204
|data, key, fingerprint, task| {
205
- data. borrow_mut ( ) . complete_task ( key, task. unwrap ( ) , fingerprint)
205
+ data. complete_task ( key, task. unwrap ( ) , fingerprint)
206
206
} ,
207
207
hash_result)
208
208
}
@@ -223,7 +223,7 @@ impl DepGraph {
223
223
self . with_task_impl ( key, cx, input, true , identity_fn,
224
224
|_| None ,
225
225
|data, key, fingerprint, _| {
226
- data. borrow_mut ( ) . alloc_node ( key, SmallVec :: new ( ) , fingerprint)
226
+ data. alloc_node ( key, SmallVec :: new ( ) , fingerprint)
227
227
} ,
228
228
hash_result :: < R > )
229
229
}
@@ -236,7 +236,7 @@ impl DepGraph {
236
236
no_tcx : bool ,
237
237
task : fn ( C , A ) -> R ,
238
238
create_task : fn ( DepNode ) -> Option < TaskDeps > ,
239
- finish_task_and_alloc_depnode : fn ( & Lock < CurrentDepGraph > ,
239
+ finish_task_and_alloc_depnode : fn ( & CurrentDepGraph ,
240
240
DepNode ,
241
241
Fingerprint ,
242
242
Option < TaskDeps > ) -> DepNodeIndex ,
@@ -350,7 +350,6 @@ impl DepGraph {
350
350
( r, task_deps. into_inner ( ) )
351
351
} ) ;
352
352
let dep_node_index = data. current
353
- . borrow_mut ( )
354
353
. complete_anon_task ( dep_kind, task_deps) ;
355
354
( result, dep_node_index)
356
355
} else {
@@ -374,18 +373,17 @@ impl DepGraph {
374
373
self . with_task_impl ( key, cx, arg, false , task,
375
374
|_| None ,
376
375
|data, key, fingerprint, _| {
377
- let mut current = data. borrow_mut ( ) ;
378
- current. alloc_node ( key, smallvec ! [ ] , fingerprint)
376
+ data. alloc_node ( key, smallvec ! [ ] , fingerprint)
379
377
} ,
380
378
hash_result)
381
379
}
382
380
383
381
#[ inline]
384
382
pub fn read ( & self , v : DepNode ) {
385
383
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 ) ;
389
387
data. read_index ( dep_node_index) ;
390
388
} else {
391
389
bug ! ( "DepKind {:?} should be pre-allocated but isn't." , v. kind)
@@ -406,8 +404,8 @@ impl DepGraph {
406
404
. as_ref ( )
407
405
. unwrap ( )
408
406
. current
409
- . borrow_mut ( )
410
407
. node_to_node_index
408
+ . lock ( )
411
409
. get ( dep_node)
412
410
. cloned ( )
413
411
. unwrap ( )
@@ -416,16 +414,16 @@ impl DepGraph {
416
414
#[ inline]
417
415
pub fn dep_node_exists ( & self , dep_node : & DepNode ) -> bool {
418
416
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)
420
418
} else {
421
419
false
422
420
}
423
421
}
424
422
425
423
#[ inline]
426
424
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
429
427
}
430
428
431
429
pub fn prev_fingerprint_of ( & self , dep_node : & DepNode ) -> Option < Fingerprint > {
@@ -479,32 +477,29 @@ impl DepGraph {
479
477
480
478
pub fn edge_deduplication_data ( & self ) -> Option < ( u64 , u64 ) > {
481
479
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 ;
483
481
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 ) ) )
486
484
} else {
487
485
None
488
486
}
489
487
}
490
488
491
489
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 ( ) ;
493
491
494
492
let fingerprints: IndexVec < SerializedDepNodeIndex , _ > =
495
- current_dep_graph . data . iter ( ) . map ( |d| d. fingerprint ) . collect ( ) ;
493
+ data. iter ( ) . map ( |d| d. fingerprint ) . collect ( ) ;
496
494
let nodes: IndexVec < SerializedDepNodeIndex , _ > =
497
- current_dep_graph . data . iter ( ) . map ( |d| d. node ) . collect ( ) ;
495
+ data. iter ( ) . map ( |d| d. node ) . collect ( ) ;
498
496
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 ( ) ;
502
498
503
499
let mut edge_list_indices = IndexVec :: with_capacity ( nodes. len ( ) ) ;
504
500
let mut edge_list_data = Vec :: with_capacity ( total_edge_count) ;
505
501
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 ) ) {
508
503
let start = edge_list_data. len ( ) as u32 ;
509
504
// This should really just be a memcpy :/
510
505
edge_list_data. extend ( edges. iter ( ) . map ( |i| SerializedDepNodeIndex :: new ( i. index ( ) ) ) ) ;
@@ -600,7 +595,7 @@ impl DepGraph {
600
595
601
596
#[ cfg( not( parallel_compiler) ) ]
602
597
{
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) ) ;
604
599
debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ) ;
605
600
}
606
601
@@ -733,15 +728,13 @@ impl DepGraph {
733
728
// There may be multiple threads trying to mark the same dep node green concurrently
734
729
735
730
let dep_node_index = {
736
- let mut current = data. current . borrow_mut ( ) ;
737
-
738
731
// Copy the fingerprint from the previous graph,
739
732
// so we don't have to recompute it
740
733
let fingerprint = data. previous . fingerprint_by_index ( prev_dep_node_index) ;
741
734
742
735
// We allocating an entry for the node in the current dependency graph and
743
736
// 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)
745
738
} ;
746
739
747
740
// ... emitting any stored diagnostic ...
@@ -917,9 +910,27 @@ struct DepNodeData {
917
910
fingerprint : Fingerprint ,
918
911
}
919
912
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.`
920
928
pub ( 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`.
923
934
#[ allow( dead_code) ]
924
935
forbidden_edge : Option < EdgeFilter > ,
925
936
@@ -936,8 +947,10 @@ pub(super) struct CurrentDepGraph {
936
947
/// the `DepGraph` is created.
937
948
anon_id_seed : Fingerprint ,
938
949
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 ,
941
954
}
942
955
943
956
impl CurrentDepGraph {
@@ -971,28 +984,28 @@ impl CurrentDepGraph {
971
984
let new_node_count_estimate = ( prev_graph_node_count * 102 ) / 100 + 200 ;
972
985
973
986
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 (
976
989
new_node_count_estimate,
977
990
Default :: default ( ) ,
978
- ) ,
991
+ ) ) ,
979
992
anon_id_seed : stable_hasher. finish ( ) ,
980
993
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 ) ,
983
996
}
984
997
}
985
998
986
999
fn complete_task (
987
- & mut self ,
1000
+ & self ,
988
1001
node : DepNode ,
989
1002
task_deps : TaskDeps ,
990
1003
fingerprint : Fingerprint
991
1004
) -> DepNodeIndex {
992
1005
self . alloc_node ( node, task_deps. reads , fingerprint)
993
1006
}
994
1007
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 {
996
1009
debug_assert ! ( !kind. is_eval_always( ) ) ;
997
1010
998
1011
let mut hasher = StableHasher :: new ( ) ;
@@ -1017,28 +1030,27 @@ impl CurrentDepGraph {
1017
1030
}
1018
1031
1019
1032
fn alloc_node (
1020
- & mut self ,
1033
+ & self ,
1021
1034
dep_node : DepNode ,
1022
1035
edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
1023
1036
fingerprint : Fingerprint
1024
1037
) -> 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) ) ;
1026
1039
self . intern_node ( dep_node, edges, fingerprint)
1027
1040
}
1028
1041
1029
1042
fn intern_node (
1030
- & mut self ,
1043
+ & self ,
1031
1044
dep_node : DepNode ,
1032
1045
edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
1033
1046
fingerprint : Fingerprint
1034
1047
) -> 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) {
1038
1049
Entry :: Occupied ( entry) => * entry. get ( ) ,
1039
1050
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 {
1042
1054
node : dep_node,
1043
1055
edges,
1044
1056
fingerprint
@@ -1057,17 +1069,17 @@ impl DepGraphData {
1057
1069
if let Some ( task_deps) = icx. task_deps {
1058
1070
let mut task_deps = task_deps. lock ( ) ;
1059
1071
if cfg ! ( debug_assertions) {
1060
- self . current . lock ( ) . total_read_count += 1 ;
1072
+ self . current . total_read_count . fetch_add ( 1 , SeqCst ) ;
1061
1073
}
1062
1074
if task_deps. read_set . insert ( source) {
1063
1075
task_deps. reads . push ( source) ;
1064
1076
1065
1077
#[ cfg( debug_assertions) ]
1066
1078
{
1067
1079
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 ;
1071
1083
if forbidden_edge. test ( & source, & target) {
1072
1084
bug ! ( "forbidden edge {:?} -> {:?} created" ,
1073
1085
source,
@@ -1077,7 +1089,7 @@ impl DepGraphData {
1077
1089
}
1078
1090
}
1079
1091
} 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 ) ;
1081
1093
}
1082
1094
}
1083
1095
} )
0 commit comments