@@ -51,7 +51,7 @@ use rustc_data_structures::outline;
5151use rustc_data_structures:: profiling:: SelfProfilerRef ;
5252use rustc_data_structures:: sync:: { AtomicU64 , Lock , WorkerLocal , broadcast} ;
5353use rustc_data_structures:: unhash:: UnhashMap ;
54- use rustc_index:: IndexVec ;
54+ use rustc_index:: { IndexSlice , IndexVec } ;
5555use rustc_serialize:: opaque:: mem_encoder:: MemEncoder ;
5656use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder , IntEncodedWithFixedSize , MemDecoder } ;
5757use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
@@ -116,7 +116,7 @@ pub struct SerializedDepGraph {
116116 /// The lazily-built inverse of `nodes`: maps a [`DepNode`] back to its
117117 /// [`SerializedDepNodeIndex`] via the node's key fingerprint. See
118118 /// [`LazyNodeIndex`].
119- index : LazyNodeIndex ,
119+ reverse_index : LazyNodeIndex ,
120120 /// The number of previous compilation sessions. This is used to generate
121121 /// unique anon dep nodes per session.
122122 session_count : u64 ,
@@ -158,6 +158,42 @@ struct LazyKindIndex {
158158 map : OnceLock < UnhashMap < PackedFingerprint , SerializedDepNodeIndex > > ,
159159}
160160
161+ impl LazyKindIndex {
162+ /// Returns this kind's `key_fingerprint -> node index` map, building it from
163+ /// the kind's range of `nodes_by_kind` on the first call. Building does the
164+ /// per-node hash-map inserts that decode used to perform eagerly for every
165+ /// kind; here we only pay it for kinds that are actually looked up.
166+ fn fingerprint_map (
167+ & self ,
168+ kind : DepKind ,
169+ nodes : & IndexSlice < SerializedDepNodeIndex , DepNode > ,
170+ nodes_by_kind : & [ SerializedDepNodeIndex ] ,
171+ ) -> & UnhashMap < PackedFingerprint , SerializedDepNodeIndex > {
172+ self . map . get_or_init ( || {
173+ let range = ( self . start as usize ) ..( self . start as usize + self . len as usize ) ;
174+ let mut map =
175+ UnhashMap :: with_capacity_and_hasher ( self . len as usize , Default :: default ( ) ) ;
176+ for & idx in & nodes_by_kind[ range] {
177+ let node = & nodes[ idx] ;
178+ debug_assert_eq ! ( node. kind, kind) ;
179+ if map. insert ( node. key_fingerprint , idx) . is_some ( )
180+ // Side effect nodes can legitimately share a fingerprint.
181+ && node. kind != DepKind :: SideEffect
182+ {
183+ panic ! (
184+ "Error: A dep graph node ({kind:?}) does not have an unique index. \
185+ Running a clean build on a nightly compiler with \
186+ `-Z incremental-verify-ich` can help narrow down the issue for reporting. \
187+ A clean build may also work around the issue.\n
188+ DepNode: {node:?}"
189+ )
190+ }
191+ }
192+ map
193+ } )
194+ }
195+ }
196+
161197impl SerializedDepGraph {
162198 #[ inline]
163199 pub fn edge_targets_from (
@@ -188,28 +224,9 @@ impl SerializedDepGraph {
188224
189225 #[ inline]
190226 pub fn node_to_index_opt ( & self , dep_node : & DepNode ) -> Option < SerializedDepNodeIndex > {
191- let kind = self . index . kinds . get ( dep_node. kind . as_usize ( ) ) ?;
192- let map = kind. map . get_or_init ( || {
193- let range = ( kind. start as usize ) ..( kind. start as usize + kind. len as usize ) ;
194- let mut map = UnhashMap :: with_capacity_and_hasher ( kind. len as usize , Default :: default ( ) ) ;
195- for & idx in & self . index . nodes_by_kind [ range] {
196- let node = & self . nodes [ idx] ;
197- if map. insert ( node. key_fingerprint , idx) . is_some ( )
198- // Side effect nodes can legitimately share a fingerprint.
199- && node. kind != DepKind :: SideEffect
200- {
201- panic ! (
202- "Error: A dep graph node ({:?}) does not have an unique index. \
203- Running a clean build on a nightly compiler with \
204- `-Z incremental-verify-ich` can help narrow down the issue for reporting. \
205- A clean build may also work around the issue.\n
206- DepNode: {node:?}" ,
207- node. kind
208- )
209- }
210- }
211- map
212- } ) ;
227+ let kind = self . reverse_index . kinds . get ( dep_node. kind . as_usize ( ) ) ?;
228+ let map =
229+ kind. fingerprint_map ( dep_node. kind , & self . nodes , & self . reverse_index . nodes_by_kind ) ;
213230 map. get ( & dep_node. key_fingerprint ) . copied ( )
214231 }
215232
@@ -345,43 +362,50 @@ impl SerializedDepGraph {
345362 // end of the array. This padding ensure it doesn't.
346363 edge_list_data. extend ( & [ 0u8 ; DEP_NODE_PAD ] ) ;
347364
348- // Read the number of nodes of each dep kind. These per-kind counts let us
349- // group node indices by kind below; the fingerprint -> index maps
350- // themselves are built lazily, per kind, on first lookup (see
351- // `LazyNodeIndex`).
352- let kind_counts: Vec < u32 > = ( 0 ..( DepKind :: MAX + 1 ) ) . map ( |_| d. read_u32 ( ) ) . collect ( ) ;
353-
354- let session_count = d. read_u64 ( ) ;
355-
356- // Counting sort: place every (non-`Null`) node index into a contiguous
357- // per-kind range of `nodes_by_kind`, using the per-kind counts to compute
358- // each kind's start offset. Padding gaps (`DepKind::Null`) are never
359- // looked up by fingerprint, so we skip them.
360- let mut kinds = Vec :: with_capacity ( kind_counts. len ( ) ) ;
365+ // Read the number of nodes of each dep kind, turning each per-kind count
366+ // into a contiguous, still-empty range of `nodes_by_kind` as we go (a
367+ // prefix sum of the counts gives each kind's start offset). The
368+ // fingerprint -> index map for a kind is built lazily, on the first lookup
369+ // of that kind (see `LazyKindIndex::fingerprint_map`).
370+ let mut kinds = Vec :: with_capacity ( DepKind :: MAX as usize + 1 ) ;
361371 let mut offset = 0u32 ;
362- for & len in & kind_counts {
372+ for _ in 0 ..( DepKind :: MAX + 1 ) {
373+ let len = d. read_u32 ( ) ;
363374 kinds. push ( LazyKindIndex { start : offset, len, map : OnceLock :: new ( ) } ) ;
364375 offset += len;
365376 }
377+ // Every encoded node has a (non-`Null`) kind, so the per-kind counts sum to
378+ // `node_count`; `Null` nodes are never encoded, so no range is reserved for
379+ // them.
366380 debug_assert_eq ! ( offset as usize , node_count) ;
367- let mut nodes_by_kind = vec ! [ SerializedDepNodeIndex :: from_u32( 0 ) ; offset as usize ] ;
381+
382+ let session_count = d. read_u64 ( ) ;
383+
384+ // Counting sort: place each node index into its kind's range. `fill[k]`
385+ // points at the next free slot in kind `k`'s range, so a kind's nodes end
386+ // up contiguous. Every slot is written exactly once (the counts sum to the
387+ // number of non-`Null` nodes), so the placeholder index used to size the
388+ // vector is always overwritten before it can be read.
389+ let mut nodes_by_kind = vec ! [ SerializedDepNodeIndex :: from_u32( 0 ) ; node_count] ;
368390 let mut fill: Vec < u32 > = kinds. iter ( ) . map ( |k| k. start ) . collect ( ) ;
369391 for ( idx, node) in nodes. iter_enumerated ( ) {
392+ // Unused indices from batch allocation stay `Null`; they carry no
393+ // encoded node and are never looked up by fingerprint, so skip them.
370394 if node. kind == DepKind :: Null {
371395 continue ;
372396 }
373397 let k = node. kind . as_usize ( ) ;
374398 nodes_by_kind[ fill[ k] as usize ] = idx;
375399 fill[ k] += 1 ;
376400 }
377- let index = LazyNodeIndex { nodes_by_kind, kinds } ;
401+ let reverse_index = LazyNodeIndex { nodes_by_kind, kinds } ;
378402
379403 Arc :: new ( SerializedDepGraph {
380404 nodes,
381405 value_fingerprints,
382406 edge_list_indices,
383407 edge_list_data,
384- index ,
408+ reverse_index ,
385409 session_count,
386410 } )
387411 }
0 commit comments