@@ -46,6 +46,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
46
46
use rustc_data_structures:: sync:: Lock ;
47
47
use rustc_data_structures:: unhash:: UnhashMap ;
48
48
use rustc_index:: { Idx , IndexVec } ;
49
+ use rustc_serialize:: opaque:: mem_encoder:: MemEncoder ;
49
50
use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder , IntEncodedWithFixedSize , MemDecoder } ;
50
51
use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
51
52
use tracing:: { debug, instrument} ;
@@ -102,18 +103,11 @@ impl SerializedDepGraph {
102
103
) -> impl Iterator < Item = SerializedDepNodeIndex > + Clone {
103
104
let header = self . edge_list_indices [ source] ;
104
105
let mut raw = & self . edge_list_data [ header. start ( ) ..] ;
105
- // Figure out where the edge list for `source` ends by getting the start index of the next
106
- // edge list, or the end of the array if this is the last edge.
107
- let end = self
108
- . edge_list_indices
109
- . get ( source + 1 )
110
- . map ( |h| h. start ( ) )
111
- . unwrap_or_else ( || self . edge_list_data . len ( ) - DEP_NODE_PAD ) ;
112
106
113
107
// The number of edges for this node is implicitly stored in the combination of the byte
114
108
// width and the length.
115
109
let bytes_per_index = header. bytes_per_index ( ) ;
116
- let len = ( end - header. start ( ) ) / bytes_per_index ;
110
+ let len = header. edges ;
117
111
118
112
// LLVM doesn't hoist EdgeHeader::mask so we do it ourselves.
119
113
let mask = header. mask ( ) ;
@@ -155,6 +149,7 @@ impl SerializedDepGraph {
155
149
#[ derive( Debug , Clone , Copy ) ]
156
150
struct EdgeHeader {
157
151
repr : usize ,
152
+ edges : u32 ,
158
153
}
159
154
160
155
impl EdgeHeader {
@@ -197,9 +192,17 @@ impl SerializedDepGraph {
197
192
198
193
let graph_bytes = d. len ( ) - ( 2 * IntEncodedWithFixedSize :: ENCODED_SIZE ) - d. position ( ) ;
199
194
200
- let mut nodes = IndexVec :: with_capacity ( node_count) ;
201
- let mut fingerprints = IndexVec :: with_capacity ( node_count) ;
202
- let mut edge_list_indices = IndexVec :: with_capacity ( node_count) ;
195
+ let mut nodes: IndexVec < SerializedDepNodeIndex , _ > = ( 0 ..node_count)
196
+ . map ( |_| DepNode {
197
+ kind : D :: DEP_KIND_NULL ,
198
+ hash : PackedFingerprint :: from ( Fingerprint :: ZERO ) ,
199
+ } )
200
+ . collect ( ) ;
201
+ let mut fingerprints: IndexVec < SerializedDepNodeIndex , _ > =
202
+ ( 0 ..node_count) . map ( |_| Fingerprint :: ZERO ) . collect ( ) ;
203
+ let mut edge_list_indices: IndexVec < SerializedDepNodeIndex , _ > =
204
+ ( 0 ..node_count) . map ( |_| EdgeHeader { repr : 0 , edges : 0 } ) . collect ( ) ;
205
+
203
206
// This estimation assumes that all of the encoded bytes are for the edge lists or for the
204
207
// fixed-size node headers. But that's not necessarily true; if any edge list has a length
205
208
// that spills out of the size we can bit-pack into SerializedNodeHeader then some of the
@@ -218,28 +221,26 @@ impl SerializedDepGraph {
218
221
let node_header =
219
222
SerializedNodeHeader :: < D > { bytes : d. read_array ( ) , _marker : PhantomData } ;
220
223
221
- let _i: SerializedDepNodeIndex = nodes. push ( node_header. node ( ) ) ;
222
- debug_assert_eq ! ( _i. index( ) , _index) ;
224
+ let index = node_header. index ( ) ;
223
225
224
- let _i : SerializedDepNodeIndex = fingerprints . push ( node_header. fingerprint ( ) ) ;
225
- debug_assert_eq ! ( _i . index( ) , _index ) ;
226
+ nodes [ index ] = node_header. node ( ) ;
227
+ fingerprints [ index] = node_header . fingerprint ( ) ;
226
228
227
229
// If the length of this node's edge list is small, the length is stored in the header.
228
230
// If it is not, we fall back to another decoder call.
229
- let num_edges = node_header. len ( ) . unwrap_or_else ( || d. read_usize ( ) ) ;
231
+ let num_edges = node_header. len ( ) . unwrap_or_else ( || d. read_u32 ( ) ) ;
230
232
231
233
// The edges index list uses the same varint strategy as rmeta tables; we select the
232
234
// number of byte elements per-array not per-element. This lets us read the whole edge
233
235
// list for a node with one decoder call and also use the on-disk format in memory.
234
- let edges_len_bytes = node_header. bytes_per_index ( ) * num_edges;
236
+ let edges_len_bytes = node_header. bytes_per_index ( ) * ( num_edges as usize ) ;
235
237
// The in-memory structure for the edges list stores the byte width of the edges on
236
238
// this node with the offset into the global edge data array.
237
- let edges_header = node_header. edges_header ( & edge_list_data) ;
239
+ let edges_header = node_header. edges_header ( & edge_list_data, num_edges ) ;
238
240
239
241
edge_list_data. extend ( d. read_raw_bytes ( edges_len_bytes) ) ;
240
242
241
- let _i: SerializedDepNodeIndex = edge_list_indices. push ( edges_header) ;
242
- debug_assert_eq ! ( _i. index( ) , _index) ;
243
+ edge_list_indices[ index] = edges_header;
243
244
}
244
245
245
246
// When we access the edge list data, we do a fixed-size read from the edge list data then
@@ -287,18 +288,20 @@ impl SerializedDepGraph {
287
288
/// * In whatever bits remain, the length of the edge list for this node, if it fits
288
289
struct SerializedNodeHeader < D > {
289
290
// 2 bytes for the DepNode
291
+ // 4 bytes for the index
290
292
// 16 for Fingerprint in DepNode
291
293
// 16 for Fingerprint in NodeInfo
292
- bytes : [ u8 ; 34 ] ,
294
+ bytes : [ u8 ; 38 ] ,
293
295
_marker : PhantomData < D > ,
294
296
}
295
297
296
298
// The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only
297
299
// to make the implementation of `SerializedNodeHeader` simpler.
298
300
struct Unpacked {
299
- len : Option < usize > ,
301
+ len : Option < u32 > ,
300
302
bytes_per_index : usize ,
301
303
kind : DepKind ,
304
+ index : SerializedDepNodeIndex ,
302
305
hash : PackedFingerprint ,
303
306
fingerprint : Fingerprint ,
304
307
}
@@ -320,6 +323,7 @@ impl<D: Deps> SerializedNodeHeader<D> {
320
323
#[ inline]
321
324
fn new (
322
325
node : DepNode ,
326
+ index : DepNodeIndex ,
323
327
fingerprint : Fingerprint ,
324
328
edge_max_index : u32 ,
325
329
edge_count : usize ,
@@ -341,18 +345,19 @@ impl<D: Deps> SerializedNodeHeader<D> {
341
345
let hash: Fingerprint = node. hash . into ( ) ;
342
346
343
347
// Using half-open ranges ensures an unconditional panic if we get the magic numbers wrong.
344
- let mut bytes = [ 0u8 ; 34 ] ;
348
+ let mut bytes = [ 0u8 ; 38 ] ;
345
349
bytes[ ..2 ] . copy_from_slice ( & head. to_le_bytes ( ) ) ;
346
- bytes[ 2 ..18 ] . copy_from_slice ( & hash. to_le_bytes ( ) ) ;
347
- bytes[ 18 ..] . copy_from_slice ( & fingerprint. to_le_bytes ( ) ) ;
350
+ bytes[ 2 ..6 ] . copy_from_slice ( & index. as_u32 ( ) . to_le_bytes ( ) ) ;
351
+ bytes[ 6 ..22 ] . copy_from_slice ( & hash. to_le_bytes ( ) ) ;
352
+ bytes[ 22 ..] . copy_from_slice ( & fingerprint. to_le_bytes ( ) ) ;
348
353
349
354
#[ cfg( debug_assertions) ]
350
355
{
351
356
let res = Self { bytes, _marker : PhantomData } ;
352
357
assert_eq ! ( fingerprint, res. fingerprint( ) ) ;
353
358
assert_eq ! ( node, res. node( ) ) ;
354
359
if let Some ( len) = res. len ( ) {
355
- assert_eq ! ( edge_count, len) ;
360
+ assert_eq ! ( edge_count, len as usize ) ;
356
361
}
357
362
}
358
363
Self { bytes, _marker : PhantomData }
@@ -361,24 +366,26 @@ impl<D: Deps> SerializedNodeHeader<D> {
361
366
#[ inline]
362
367
fn unpack ( & self ) -> Unpacked {
363
368
let head = u16:: from_le_bytes ( self . bytes [ ..2 ] . try_into ( ) . unwrap ( ) ) ;
364
- let hash = self . bytes [ 2 ..18 ] . try_into ( ) . unwrap ( ) ;
365
- let fingerprint = self . bytes [ 18 ..] . try_into ( ) . unwrap ( ) ;
369
+ let index = u32:: from_le_bytes ( self . bytes [ 2 ..6 ] . try_into ( ) . unwrap ( ) ) ;
370
+ let hash = self . bytes [ 6 ..22 ] . try_into ( ) . unwrap ( ) ;
371
+ let fingerprint = self . bytes [ 22 ..] . try_into ( ) . unwrap ( ) ;
366
372
367
373
let kind = head & mask ( Self :: KIND_BITS ) as u16 ;
368
374
let bytes_per_index = ( head >> Self :: KIND_BITS ) & mask ( Self :: WIDTH_BITS ) as u16 ;
369
- let len = ( head as usize ) >> ( Self :: WIDTH_BITS + Self :: KIND_BITS ) ;
375
+ let len = ( head as u32 ) >> ( Self :: WIDTH_BITS + Self :: KIND_BITS ) ;
370
376
371
377
Unpacked {
372
378
len : len. checked_sub ( 1 ) ,
373
379
bytes_per_index : bytes_per_index as usize + 1 ,
374
380
kind : DepKind :: new ( kind) ,
381
+ index : SerializedDepNodeIndex :: from_u32 ( index) ,
375
382
hash : Fingerprint :: from_le_bytes ( hash) . into ( ) ,
376
383
fingerprint : Fingerprint :: from_le_bytes ( fingerprint) ,
377
384
}
378
385
}
379
386
380
387
#[ inline]
381
- fn len ( & self ) -> Option < usize > {
388
+ fn len ( & self ) -> Option < u32 > {
382
389
self . unpack ( ) . len
383
390
}
384
391
@@ -387,6 +394,11 @@ impl<D: Deps> SerializedNodeHeader<D> {
387
394
self . unpack ( ) . bytes_per_index
388
395
}
389
396
397
+ #[ inline]
398
+ fn index ( & self ) -> SerializedDepNodeIndex {
399
+ self . unpack ( ) . index
400
+ }
401
+
390
402
#[ inline]
391
403
fn fingerprint ( & self ) -> Fingerprint {
392
404
self . unpack ( ) . fingerprint
@@ -399,9 +411,10 @@ impl<D: Deps> SerializedNodeHeader<D> {
399
411
}
400
412
401
413
#[ inline]
402
- fn edges_header ( & self , edge_list_data : & [ u8 ] ) -> EdgeHeader {
414
+ fn edges_header ( & self , edge_list_data : & [ u8 ] , edges : u32 ) -> EdgeHeader {
403
415
EdgeHeader {
404
416
repr : ( edge_list_data. len ( ) << DEP_NODE_WIDTH_BITS ) | ( self . bytes_per_index ( ) - 1 ) ,
417
+ edges,
405
418
}
406
419
}
407
420
}
@@ -414,14 +427,20 @@ struct NodeInfo {
414
427
}
415
428
416
429
impl NodeInfo {
417
- fn encode < D : Deps > ( & self , e : & mut FileEncoder ) {
430
+ fn encode < D : Deps > ( & self , e : & mut MemEncoder , index : DepNodeIndex ) {
418
431
let NodeInfo { node, fingerprint, ref edges } = * self ;
419
- let header =
420
- SerializedNodeHeader :: < D > :: new ( node, fingerprint, edges. max_index ( ) , edges. len ( ) ) ;
432
+ let header = SerializedNodeHeader :: < D > :: new (
433
+ node,
434
+ index,
435
+ fingerprint,
436
+ edges. max_index ( ) ,
437
+ edges. len ( ) ,
438
+ ) ;
421
439
e. write_array ( header. bytes ) ;
422
440
423
441
if header. len ( ) . is_none ( ) {
424
- e. emit_usize ( edges. len ( ) ) ;
442
+ // The edges are all unique and the number of unique indices is less than u32::MAX.
443
+ e. emit_u32 ( edges. len ( ) . try_into ( ) . unwrap ( ) ) ;
425
444
}
426
445
427
446
let bytes_per_index = header. bytes_per_index ( ) ;
@@ -438,8 +457,9 @@ impl NodeInfo {
438
457
/// This avoids the overhead of constructing `EdgesVec`, which would be needed to call `encode`.
439
458
#[ inline]
440
459
fn encode_promoted < D : Deps > (
441
- e : & mut FileEncoder ,
460
+ e : & mut MemEncoder ,
442
461
node : DepNode ,
462
+ index : DepNodeIndex ,
443
463
fingerprint : Fingerprint ,
444
464
prev_index : SerializedDepNodeIndex ,
445
465
colors : & DepNodeColorMap ,
@@ -452,11 +472,12 @@ impl NodeInfo {
452
472
let edge_max =
453
473
edges. clone ( ) . map ( |i| colors. current ( i) . unwrap ( ) . as_u32 ( ) ) . max ( ) . unwrap_or ( 0 ) ;
454
474
455
- let header = SerializedNodeHeader :: < D > :: new ( node, fingerprint, edge_max, edge_count) ;
475
+ let header = SerializedNodeHeader :: < D > :: new ( node, index , fingerprint, edge_max, edge_count) ;
456
476
e. write_array ( header. bytes ) ;
457
477
458
478
if header. len ( ) . is_none ( ) {
459
- e. emit_usize ( edge_count) ;
479
+ // The edges are all unique and the number of unique indices is less than u32::MAX.
480
+ e. emit_u32 ( edge_count. try_into ( ) . unwrap ( ) ) ;
460
481
}
461
482
462
483
let bytes_per_index = header. bytes_per_index ( ) ;
@@ -485,6 +506,8 @@ struct EncoderState<D: Deps> {
485
506
total_edge_count : usize ,
486
507
stats : Option < FxHashMap < DepKind , Stat > > ,
487
508
509
+ mem_encoder : MemEncoder ,
510
+
488
511
/// Stores the number of times we've encoded each dep kind.
489
512
kind_stats : Vec < u32 > ,
490
513
marker : PhantomData < D > ,
@@ -498,22 +521,28 @@ impl<D: Deps> EncoderState<D> {
498
521
total_edge_count : 0 ,
499
522
total_node_count : 0 ,
500
523
stats : record_stats. then ( FxHashMap :: default) ,
524
+ mem_encoder : MemEncoder :: new ( ) ,
501
525
kind_stats : iter:: repeat ( 0 ) . take ( D :: DEP_KIND_MAX as usize + 1 ) . collect ( ) ,
502
526
marker : PhantomData ,
503
527
}
504
528
}
505
529
530
+ #[ inline]
531
+ fn alloc_index ( & mut self ) -> DepNodeIndex {
532
+ let index = DepNodeIndex :: new ( self . total_node_count ) ;
533
+ self . total_node_count += 1 ;
534
+ index
535
+ }
536
+
506
537
#[ inline]
507
538
fn record (
508
539
& mut self ,
509
540
node : DepNode ,
541
+ index : DepNodeIndex ,
510
542
edge_count : usize ,
511
543
edges : impl FnOnce ( & mut Self ) -> Vec < DepNodeIndex > ,
512
544
record_graph : & Option < Lock < DepGraphQuery > > ,
513
545
) -> DepNodeIndex {
514
- let index = DepNodeIndex :: new ( self . total_node_count ) ;
515
-
516
- self . total_node_count += 1 ;
517
546
self . kind_stats [ node. kind . as_usize ( ) ] += 1 ;
518
547
self . total_edge_count += edge_count;
519
548
@@ -545,14 +574,25 @@ impl<D: Deps> EncoderState<D> {
545
574
index
546
575
}
547
576
577
+ #[ inline]
578
+ fn flush_mem_encoder ( & mut self ) {
579
+ let data = & mut self . mem_encoder . data ;
580
+ if data. len ( ) > 64 * 1024 {
581
+ self . encoder . emit_raw_bytes ( & data[ ..] ) ;
582
+ data. clear ( ) ;
583
+ }
584
+ }
585
+
548
586
/// Encodes a node to the current graph.
549
587
fn encode_node (
550
588
& mut self ,
551
589
node : & NodeInfo ,
552
590
record_graph : & Option < Lock < DepGraphQuery > > ,
553
591
) -> DepNodeIndex {
554
- node. encode :: < D > ( & mut self . encoder ) ;
555
- self . record ( node. node , node. edges . len ( ) , |_| node. edges [ ..] . to_vec ( ) , record_graph)
592
+ let index = self . alloc_index ( ) ;
593
+ node. encode :: < D > ( & mut self . mem_encoder , index) ;
594
+ self . flush_mem_encoder ( ) ;
595
+ self . record ( node. node , index, node. edges . len ( ) , |_| node. edges [ ..] . to_vec ( ) , record_graph)
556
596
}
557
597
558
598
/// Encodes a node that was promoted from the previous graph. It reads the information directly from
@@ -568,20 +608,22 @@ impl<D: Deps> EncoderState<D> {
568
608
record_graph : & Option < Lock < DepGraphQuery > > ,
569
609
colors : & DepNodeColorMap ,
570
610
) -> DepNodeIndex {
611
+ let index = self . alloc_index ( ) ;
571
612
let node = self . previous . index_to_node ( prev_index) ;
572
-
573
613
let fingerprint = self . previous . fingerprint_by_index ( prev_index) ;
574
614
let edge_count = NodeInfo :: encode_promoted :: < D > (
575
- & mut self . encoder ,
615
+ & mut self . mem_encoder ,
576
616
node,
617
+ index,
577
618
fingerprint,
578
619
prev_index,
579
620
colors,
580
621
& self . previous ,
581
622
) ;
582
-
623
+ self . flush_mem_encoder ( ) ;
583
624
self . record (
584
625
node,
626
+ index,
585
627
edge_count,
586
628
|this| {
587
629
this. previous
@@ -590,12 +632,14 @@ impl<D: Deps> EncoderState<D> {
590
632
. collect ( )
591
633
} ,
592
634
record_graph,
593
- )
635
+ ) ;
636
+ index
594
637
}
595
638
596
639
fn finish ( self , profiler : & SelfProfilerRef ) -> FileEncodeResult {
597
640
let Self {
598
641
mut encoder,
642
+ mem_encoder,
599
643
total_node_count,
600
644
total_edge_count,
601
645
stats : _,
@@ -604,6 +648,8 @@ impl<D: Deps> EncoderState<D> {
604
648
previous : _,
605
649
} = self ;
606
650
651
+ encoder. emit_raw_bytes ( & mem_encoder. data ) ;
652
+
607
653
let node_count = total_node_count. try_into ( ) . unwrap ( ) ;
608
654
let edge_count = total_edge_count. try_into ( ) . unwrap ( ) ;
609
655
0 commit comments