@@ -3,11 +3,15 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
3
3
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4
4
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
5
5
use smallvec:: SmallVec ;
6
- use rustc_data_structures:: sync:: { Lrc , Lock , AtomicU32 , AtomicU64 , Ordering } ;
6
+ use rustc_data_structures:: sync:: {
7
+ Lrc , Lock , LockGuard , MappedLockGuard , AtomicU32 , AtomicU64 , Ordering
8
+ } ;
7
9
use rustc_data_structures:: sharded:: { self , Sharded } ;
8
10
use std:: sync:: atomic:: Ordering :: { Acquire , SeqCst } ;
9
11
use std:: env;
12
+ use std:: iter;
10
13
use std:: hash:: Hash ;
14
+ use std:: convert:: TryFrom ;
11
15
use std:: collections:: hash_map:: Entry ;
12
16
use std:: mem;
13
17
use crate :: ty:: { self , TyCtxt } ;
@@ -124,7 +128,15 @@ impl DepGraph {
124
128
}
125
129
126
130
pub fn query ( & self ) -> DepGraphQuery {
127
- let data = self . data . as_ref ( ) . unwrap ( ) . current . data . lock ( ) ;
131
+ let current = & self . data . as_ref ( ) . unwrap ( ) . current ;
132
+ let shards = current. data . lock_shards ( ) ;
133
+ let node_count = current. node_count . load ( Acquire ) as usize ;
134
+ let data: IndexVec < DepNodeIndex , _ > = ( 0 ..node_count) . map ( |i| {
135
+ let shard = i % sharded:: SHARDS ;
136
+ let inner = i / sharded:: SHARDS ;
137
+ & shards[ shard] [ inner]
138
+ } ) . collect ( ) ;
139
+
128
140
let nodes: Vec < _ > = data. iter ( ) . map ( |n| n. node ) . collect ( ) ;
129
141
let mut edges = Vec :: new ( ) ;
130
142
for ( from, edge_targets) in data. iter ( )
@@ -442,8 +454,7 @@ impl DepGraph {
442
454
443
455
#[ inline]
444
456
pub fn fingerprint_of ( & self , dep_node_index : DepNodeIndex ) -> Fingerprint {
445
- let data = self . data . as_ref ( ) . expect ( "dep graph enabled" ) . current . data . lock ( ) ;
446
- data[ dep_node_index] . fingerprint
457
+ self . data . as_ref ( ) . expect ( "dep graph enabled" ) . current . data ( dep_node_index) . fingerprint
447
458
}
448
459
449
460
pub fn prev_fingerprint_of ( & self , dep_node : & DepNode ) -> Option < Fingerprint > {
@@ -507,25 +518,32 @@ impl DepGraph {
507
518
}
508
519
509
520
pub fn serialize ( & self ) -> SerializedDepGraph {
510
- let data = self . data . as_ref ( ) . unwrap ( ) . current . data . lock ( ) ;
521
+ let current = & self . data . as_ref ( ) . unwrap ( ) . current ;
522
+ let shards = current. data . lock_shards ( ) ;
523
+ let node_count = current. node_count . load ( Acquire ) as usize ;
524
+ let data = || ( 0 ..node_count) . map ( |i| {
525
+ let shard = i % sharded:: SHARDS ;
526
+ let inner = i / sharded:: SHARDS ;
527
+ & shards[ shard] [ inner]
528
+ } ) ;
511
529
512
530
let fingerprints: IndexVec < SerializedDepNodeIndex , _ > =
513
- data. iter ( ) . map ( |d| d. fingerprint ) . collect ( ) ;
531
+ data ( ) . map ( |d| d. fingerprint ) . collect ( ) ;
514
532
let nodes: IndexVec < SerializedDepNodeIndex , _ > =
515
- data. iter ( ) . map ( |d| d. node ) . collect ( ) ;
533
+ data ( ) . map ( |d| d. node ) . collect ( ) ;
516
534
517
- let total_edge_count: usize = data. iter ( ) . map ( |d| d. edges . len ( ) ) . sum ( ) ;
535
+ let total_edge_count: usize = data ( ) . map ( |d| d. edges . len ( ) ) . sum ( ) ;
518
536
519
537
let mut edge_list_indices = IndexVec :: with_capacity ( nodes. len ( ) ) ;
520
538
let mut edge_list_data = Vec :: with_capacity ( total_edge_count) ;
521
539
522
- for ( current_dep_node_index, edges) in data. iter_enumerated ( ) . map ( |( i, d) | ( i, & d. edges ) ) {
540
+ for ( current_dep_node_index, edges) in data ( ) . enumerate ( ) . map ( |( i, d) | ( i, & d. edges ) ) {
523
541
let start = edge_list_data. len ( ) as u32 ;
524
542
// This should really just be a memcpy :/
525
543
edge_list_data. extend ( edges. iter ( ) . map ( |i| SerializedDepNodeIndex :: new ( i. index ( ) ) ) ) ;
526
544
let end = edge_list_data. len ( ) as u32 ;
527
545
528
- debug_assert_eq ! ( current_dep_node_index. index ( ) , edge_list_indices. len( ) ) ;
546
+ debug_assert_eq ! ( current_dep_node_index, edge_list_indices. len( ) ) ;
529
547
edge_list_indices. push ( ( start, end) ) ;
530
548
}
531
549
@@ -964,7 +982,14 @@ struct DepNodeData {
964
982
}
965
983
966
984
pub ( super ) struct CurrentDepGraph {
967
- data : Lock < IndexVec < DepNodeIndex , DepNodeData > > ,
985
+ /// The current node count. Used to allocate an index before storing it in the
986
+ /// `data` and `node_to_node_index` field below.
987
+ node_count : AtomicU64 ,
988
+
989
+ /// Maps from a `DepNodeIndex` to `DepNodeData`. The lowest bits of `DepNodeIndex` determines
990
+ /// which shard is used and the higher bits are the index into the vector.
991
+ data : Sharded < Vec < DepNodeData > > ,
992
+
968
993
node_to_node_index : Sharded < FxHashMap < DepNode , DepNodeIndex > > ,
969
994
#[ allow( dead_code) ]
970
995
forbidden_edge : Option < EdgeFilter > ,
@@ -1017,7 +1042,8 @@ impl CurrentDepGraph {
1017
1042
let new_node_count_estimate = ( prev_graph_node_count * 102 ) / 100 + 200 ;
1018
1043
1019
1044
CurrentDepGraph {
1020
- data : Lock :: new ( IndexVec :: with_capacity ( new_node_count_estimate) ) ,
1045
+ node_count : AtomicU64 :: new ( 0 ) ,
1046
+ data : Sharded :: new ( || Vec :: with_capacity ( new_node_count_estimate / sharded:: SHARDS ) ) ,
1021
1047
node_to_node_index : Sharded :: new ( || FxHashMap :: with_capacity_and_hasher (
1022
1048
new_node_count_estimate / sharded:: SHARDS ,
1023
1049
Default :: default ( ) ,
@@ -1081,20 +1107,56 @@ impl CurrentDepGraph {
1081
1107
edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
1082
1108
fingerprint : Fingerprint
1083
1109
) -> DepNodeIndex {
1084
- match self . node_to_node_index . get_shard_by_value ( & dep_node) . lock ( ) . entry ( dep_node) {
1110
+ let ( index, inserted) = match self . node_to_node_index
1111
+ . get_shard_by_value ( & dep_node)
1112
+ . lock ( )
1113
+ . entry ( dep_node) {
1085
1114
Entry :: Occupied ( entry) => * entry. get ( ) ,
1086
1115
Entry :: Vacant ( entry) => {
1087
- let mut data = self . data . lock ( ) ;
1088
- let dep_node_index = DepNodeIndex :: new ( data. len ( ) ) ;
1089
- data. push ( DepNodeData {
1090
- node : dep_node,
1091
- edges,
1092
- fingerprint
1093
- } ) ;
1116
+ let index = self . node_count . fetch_add ( 1 , SeqCst ) ;
1117
+ // Cast to u32 to ensure we didn't overflow.
1118
+ let index = u32:: try_from ( index) . unwrap ( ) ;
1119
+
1120
+ let dep_node_index = DepNodeIndex :: new ( index as usize ) ;
1094
1121
entry. insert ( dep_node_index) ;
1095
1122
dep_node_index
1096
1123
}
1124
+ } ;
1125
+
1126
+ if inserted {
1127
+ let dep_node_data = DepNodeData {
1128
+ node : dep_node,
1129
+ edges,
1130
+ fingerprint
1131
+ } ;
1132
+ let inner_index = index. as_usize ( ) / sharded:: SHARDS ;
1133
+ let mut data = self . data . get_shard_by_index ( index. as_usize ( ) ) . lock ( ) ;
1134
+ let len = data. len ( ) ;
1135
+ if likely ! ( len == inner_index) {
1136
+ data. push ( dep_node_data)
1137
+ } else {
1138
+ let dummy_data = DepNodeData {
1139
+ node : DepNode :: new_no_params ( DepKind :: Null ) ,
1140
+ edges : SmallVec :: default ( ) ,
1141
+ fingerprint : Fingerprint :: ZERO ,
1142
+ } ;
1143
+ if inner_index >= len {
1144
+ data. extend ( iter:: repeat ( dummy_data) . take ( inner_index - len + 1 ) ) ;
1145
+ }
1146
+ data[ inner_index] = dep_node_data;
1147
+ }
1097
1148
}
1149
+
1150
+ ( index, inserted)
1151
+ }
1152
+
1153
+ fn data (
1154
+ & self ,
1155
+ index : DepNodeIndex ,
1156
+ ) -> MappedLockGuard < ' _ , DepNodeData > {
1157
+ LockGuard :: map ( self . data . get_shard_by_index ( index. as_usize ( ) ) . lock ( ) , |vec| {
1158
+ & mut vec[ index. as_usize ( ) / sharded:: SHARDS ]
1159
+ } )
1098
1160
}
1099
1161
}
1100
1162
@@ -1113,9 +1175,8 @@ impl DepGraphData {
1113
1175
#[ cfg( debug_assertions) ]
1114
1176
{
1115
1177
if let Some ( target) = task_deps. node {
1116
- let data = self . current . data . lock ( ) ;
1117
1178
if let Some ( ref forbidden_edge) = self . current . forbidden_edge {
1118
- let source = data[ source] . node ;
1179
+ let source = self . current . data ( source) . node ;
1119
1180
if forbidden_edge. test ( & source, & target) {
1120
1181
bug ! ( "forbidden edge {:?} -> {:?} created" ,
1121
1182
source,
0 commit comments