@@ -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,11 +221,10 @@ 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.
@@ -234,12 +236,11 @@ impl SerializedDepGraph {
234
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,9 +288,10 @@ 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
@@ -299,6 +301,7 @@ struct Unpacked {
299
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,10 +345,11 @@ 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
{
@@ -361,8 +366,9 @@ 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 ;
@@ -372,6 +378,7 @@ impl<D: Deps> SerializedNodeHeader<D> {
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
}
@@ -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,10 +427,15 @@ 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 ( ) {
@@ -439,8 +457,9 @@ impl NodeInfo {
439
457
/// This avoids the overhead of constructing `EdgesVec`, which would be needed to call `encode`.
440
458
#[ inline]
441
459
fn encode_promoted < D : Deps > (
442
- e : & mut FileEncoder ,
460
+ e : & mut MemEncoder ,
443
461
node : DepNode ,
462
+ index : DepNodeIndex ,
444
463
fingerprint : Fingerprint ,
445
464
prev_index : SerializedDepNodeIndex ,
446
465
colors : & DepNodeColorMap ,
@@ -453,7 +472,7 @@ impl NodeInfo {
453
472
let edge_max =
454
473
edges. clone ( ) . map ( |i| colors. current ( i) . unwrap ( ) . as_u32 ( ) ) . max ( ) . unwrap_or ( 0 ) ;
455
474
456
- let header = SerializedNodeHeader :: < D > :: new ( node, fingerprint, edge_max, edge_count) ;
475
+ let header = SerializedNodeHeader :: < D > :: new ( node, index , fingerprint, edge_max, edge_count) ;
457
476
e. write_array ( header. bytes ) ;
458
477
459
478
if header. len ( ) . is_none ( ) {
@@ -487,6 +506,8 @@ struct EncoderState<D: Deps> {
487
506
total_edge_count : usize ,
488
507
stats : Option < FxHashMap < DepKind , Stat > > ,
489
508
509
+ mem_encoder : MemEncoder ,
510
+
490
511
/// Stores the number of times we've encoded each dep kind.
491
512
kind_stats : Vec < u32 > ,
492
513
marker : PhantomData < D > ,
@@ -500,22 +521,28 @@ impl<D: Deps> EncoderState<D> {
500
521
total_edge_count : 0 ,
501
522
total_node_count : 0 ,
502
523
stats : record_stats. then ( FxHashMap :: default) ,
524
+ mem_encoder : MemEncoder :: new ( ) ,
503
525
kind_stats : iter:: repeat ( 0 ) . take ( D :: DEP_KIND_MAX as usize + 1 ) . collect ( ) ,
504
526
marker : PhantomData ,
505
527
}
506
528
}
507
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
+
508
537
#[ inline]
509
538
fn record (
510
539
& mut self ,
511
540
node : DepNode ,
541
+ index : DepNodeIndex ,
512
542
edge_count : usize ,
513
543
edges : impl FnOnce ( & mut Self ) -> Vec < DepNodeIndex > ,
514
544
record_graph : & Option < Lock < DepGraphQuery > > ,
515
545
) -> DepNodeIndex {
516
- let index = DepNodeIndex :: new ( self . total_node_count ) ;
517
-
518
- self . total_node_count += 1 ;
519
546
self . kind_stats [ node. kind . as_usize ( ) ] += 1 ;
520
547
self . total_edge_count += edge_count;
521
548
@@ -547,14 +574,25 @@ impl<D: Deps> EncoderState<D> {
547
574
index
548
575
}
549
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
+
550
586
/// Encodes a node to the current graph.
551
587
fn encode_node (
552
588
& mut self ,
553
589
node : & NodeInfo ,
554
590
record_graph : & Option < Lock < DepGraphQuery > > ,
555
591
) -> DepNodeIndex {
556
- node. encode :: < D > ( & mut self . encoder ) ;
557
- 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)
558
596
}
559
597
560
598
/// Encodes a node that was promoted from the previous graph. It reads the information directly from
@@ -570,20 +608,22 @@ impl<D: Deps> EncoderState<D> {
570
608
record_graph : & Option < Lock < DepGraphQuery > > ,
571
609
colors : & DepNodeColorMap ,
572
610
) -> DepNodeIndex {
611
+ let index = self . alloc_index ( ) ;
573
612
let node = self . previous . index_to_node ( prev_index) ;
574
-
575
613
let fingerprint = self . previous . fingerprint_by_index ( prev_index) ;
576
614
let edge_count = NodeInfo :: encode_promoted :: < D > (
577
- & mut self . encoder ,
615
+ & mut self . mem_encoder ,
578
616
node,
617
+ index,
579
618
fingerprint,
580
619
prev_index,
581
620
colors,
582
621
& self . previous ,
583
622
) ;
584
-
623
+ self . flush_mem_encoder ( ) ;
585
624
self . record (
586
625
node,
626
+ index,
587
627
edge_count,
588
628
|this| {
589
629
this. previous
@@ -592,12 +632,14 @@ impl<D: Deps> EncoderState<D> {
592
632
. collect ( )
593
633
} ,
594
634
record_graph,
595
- )
635
+ ) ;
636
+ index
596
637
}
597
638
598
639
fn finish ( self , profiler : & SelfProfilerRef ) -> FileEncodeResult {
599
640
let Self {
600
641
mut encoder,
642
+ mem_encoder,
601
643
total_node_count,
602
644
total_edge_count,
603
645
stats : _,
@@ -606,6 +648,8 @@ impl<D: Deps> EncoderState<D> {
606
648
previous : _,
607
649
} = self ;
608
650
651
+ encoder. emit_raw_bytes ( & mem_encoder. data ) ;
652
+
609
653
let node_count = total_node_count. try_into ( ) . unwrap ( ) ;
610
654
let edge_count = total_edge_count. try_into ( ) . unwrap ( ) ;
611
655
0 commit comments