@@ -13,7 +13,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13
13
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
14
14
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
15
15
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 ;
17
18
use std:: env;
18
19
use std:: hash:: Hash ;
19
20
use ty:: { self , TyCtxt } ;
@@ -69,6 +70,8 @@ struct DepGraphData {
69
70
/// current one anymore.
70
71
current : Lock < CurrentDepGraph > ,
71
72
73
+ current_atomic : CurrentDepGraphAtomic ,
74
+
72
75
/// The dep-graph from the previous compilation session. It contains all
73
76
/// nodes and edges as well as all fingerprints of nodes that have them.
74
77
previous : PreviousDepGraph ,
@@ -98,11 +101,13 @@ impl DepGraph {
98
101
99
102
let fingerprints = IndexVec :: from_elem_n ( Fingerprint :: ZERO ,
100
103
( prev_graph_node_count * 115 ) / 100 ) ;
104
+ let ( current, current_atomic) = CurrentDepGraph :: new ( ) ;
101
105
DepGraph {
102
106
data : Some ( Lrc :: new ( DepGraphData {
103
107
previous_work_products : prev_work_products,
104
108
dep_node_debug : Default :: default ( ) ,
105
- current : Lock :: new ( CurrentDepGraph :: new ( ) ) ,
109
+ current : Lock :: new ( current) ,
110
+ current_atomic,
106
111
previous : prev_graph,
107
112
colors : Lock :: new ( DepNodeColorMap :: new ( prev_graph_node_count) ) ,
108
113
loaded_from_cache : Default :: default ( ) ,
@@ -446,9 +451,10 @@ impl DepGraph {
446
451
#[ inline]
447
452
pub fn read ( & self , v : DepNode ) {
448
453
if let Some ( ref data) = self . data {
449
- let mut current = data. current . borrow_mut ( ) ;
454
+ let current = data. current . borrow_mut ( ) ;
450
455
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) ;
452
458
} else {
453
459
bug ! ( "DepKind {:?} should be pre-allocated but isn't." , v. kind)
454
460
}
@@ -458,7 +464,7 @@ impl DepGraph {
458
464
#[ inline]
459
465
pub fn read_index ( & self , dep_node_index : DepNodeIndex ) {
460
466
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) ;
462
468
}
463
469
}
464
470
@@ -549,9 +555,10 @@ impl DepGraph {
549
555
}
550
556
551
557
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 ;
553
559
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 ) )
555
562
}
556
563
557
564
pub fn serialize ( & self ) -> SerializedDepGraph {
@@ -936,6 +943,11 @@ pub enum WorkProductFileKind {
936
943
BytecodeCompressed ,
937
944
}
938
945
946
+ pub ( super ) struct CurrentDepGraphAtomic {
947
+ total_read_count : AtomicU64 ,
948
+ total_duplicate_read_count : AtomicU64 ,
949
+ }
950
+
939
951
pub ( super ) struct CurrentDepGraph {
940
952
nodes : IndexVec < DepNodeIndex , DepNode > ,
941
953
edges : IndexVec < DepNodeIndex , SmallVec < [ DepNodeIndex ; 8 ] > > ,
@@ -954,13 +966,10 @@ pub(super) struct CurrentDepGraph {
954
966
// each anon node. The session-key is just a random number generated when
955
967
// the DepGraph is created.
956
968
anon_id_seed : Fingerprint ,
957
-
958
- total_read_count : u64 ,
959
- total_duplicate_read_count : u64 ,
960
969
}
961
970
962
971
impl CurrentDepGraph {
963
- fn new ( ) -> CurrentDepGraph {
972
+ fn new ( ) -> ( CurrentDepGraph , CurrentDepGraphAtomic ) {
964
973
use std:: time:: { SystemTime , UNIX_EPOCH } ;
965
974
966
975
let duration = SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . unwrap ( ) ;
@@ -983,15 +992,16 @@ impl CurrentDepGraph {
983
992
None
984
993
} ;
985
994
986
- CurrentDepGraph {
995
+ ( CurrentDepGraph {
987
996
nodes : IndexVec :: new ( ) ,
988
997
edges : IndexVec :: new ( ) ,
989
998
node_to_node_index : Default :: default ( ) ,
990
999
anon_id_seed : stable_hasher. finish ( ) ,
991
1000
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
+ } )
995
1005
}
996
1006
997
1007
#[ inline( always) ]
@@ -1085,22 +1095,39 @@ impl CurrentDepGraph {
1085
1095
}
1086
1096
}
1087
1097
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 ) {
1089
1115
ty:: tls:: with_context_opt ( |icx| {
1090
1116
let icx = if let Some ( icx) = icx { icx } else { return } ;
1091
1117
match * icx. task {
1092
1118
OpenTask :: Regular ( ref task) => {
1093
1119
let mut task = task. lock ( ) ;
1094
- self . total_read_count += 1 ;
1120
+ self . total_read_count . fetch_add ( 1 , Relaxed ) ;
1095
1121
// FIXME: Only use the set of the SmallVec moved to the heap
1096
1122
// Use an array and switch to the set after?
1097
1123
if task. read_set . insert ( source) {
1098
- task. reads . push ( source) ;
1124
+ task. reads . push_light ( source) ;
1099
1125
1100
1126
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 {
1102
1129
let target = & task. node ;
1103
- let source = self . nodes [ source] ;
1130
+ let source = graph . nodes [ source] ;
1104
1131
if forbidden_edge. test ( & source, & target) {
1105
1132
bug ! ( "forbidden edge {:?} -> {:?} created" ,
1106
1133
source,
@@ -1109,7 +1136,7 @@ impl CurrentDepGraph {
1109
1136
}
1110
1137
}
1111
1138
} else {
1112
- self . total_duplicate_read_count += 1 ;
1139
+ self . total_duplicate_read_count . fetch_add ( 1 , Relaxed ) ;
1113
1140
}
1114
1141
}
1115
1142
OpenTask :: Anon ( ref task) => {
@@ -1124,20 +1151,6 @@ impl CurrentDepGraph {
1124
1151
}
1125
1152
} )
1126
1153
}
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
- }
1141
1154
}
1142
1155
1143
1156
pub struct RegularOpenTask {
0 commit comments