@@ -41,6 +41,7 @@ use crate::dep_graph::edges::EdgesVec;
41
41
use rustc_data_structures:: fingerprint:: Fingerprint ;
42
42
use rustc_data_structures:: fingerprint:: PackedFingerprint ;
43
43
use rustc_data_structures:: fx:: FxHashMap ;
44
+ use rustc_data_structures:: outline;
44
45
use rustc_data_structures:: profiling:: SelfProfilerRef ;
45
46
use rustc_data_structures:: sync:: Lock ;
46
47
use rustc_data_structures:: unhash:: UnhashMap ;
@@ -49,6 +50,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed
49
50
use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
50
51
use std:: iter;
51
52
use std:: marker:: PhantomData ;
53
+ use std:: sync:: Arc ;
52
54
53
55
// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
54
56
// unused so that we can store multiple index types in `CompressedHybridIndex`,
@@ -94,7 +96,7 @@ impl SerializedDepGraph {
94
96
pub fn edge_targets_from (
95
97
& self ,
96
98
source : SerializedDepNodeIndex ,
97
- ) -> impl Iterator < Item = SerializedDepNodeIndex > + ' _ {
99
+ ) -> impl Iterator < Item = SerializedDepNodeIndex > + Clone + ' _ {
98
100
let header = self . edge_list_indices [ source] ;
99
101
let mut raw = & self . edge_list_data [ header. start ( ) ..] ;
100
102
// Figure out where the edge list for `source` ends by getting the start index of the next
@@ -176,7 +178,7 @@ fn mask(bits: usize) -> usize {
176
178
177
179
impl SerializedDepGraph {
178
180
#[ instrument( level = "debug" , skip( d) ) ]
179
- pub fn decode < D : Deps > ( d : & mut MemDecoder < ' _ > ) -> SerializedDepGraph {
181
+ pub fn decode < D : Deps > ( d : & mut MemDecoder < ' _ > ) -> Arc < SerializedDepGraph > {
180
182
// The last 16 bytes are the node count and edge count.
181
183
debug ! ( "position: {:?}" , d. position( ) ) ;
182
184
let ( node_count, edge_count, graph_size) =
@@ -254,7 +256,13 @@ impl SerializedDepGraph {
254
256
index[ node. kind . as_usize ( ) ] . insert ( node. hash , idx) ;
255
257
}
256
258
257
- SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data, index }
259
+ Arc :: new ( SerializedDepGraph {
260
+ nodes,
261
+ fingerprints,
262
+ edge_list_indices,
263
+ edge_list_data,
264
+ index,
265
+ } )
258
266
}
259
267
}
260
268
@@ -299,21 +307,24 @@ impl<D: Deps> SerializedNodeHeader<D> {
299
307
const MAX_INLINE_LEN : usize = ( u16:: MAX as usize >> ( Self :: TOTAL_BITS - Self :: LEN_BITS ) ) - 1 ;
300
308
301
309
#[ inline]
302
- fn new ( node_info : & NodeInfo ) -> Self {
310
+ fn new (
311
+ node : DepNode ,
312
+ fingerprint : Fingerprint ,
313
+ edge_max_index : u32 ,
314
+ edge_count : usize ,
315
+ ) -> Self {
303
316
debug_assert_eq ! ( Self :: TOTAL_BITS , Self :: LEN_BITS + Self :: WIDTH_BITS + Self :: KIND_BITS ) ;
304
317
305
- let NodeInfo { node, fingerprint, edges } = node_info;
306
-
307
318
let mut head = node. kind . as_inner ( ) ;
308
319
309
- let free_bytes = edges . max_index ( ) . leading_zeros ( ) as usize / 8 ;
320
+ let free_bytes = edge_max_index . leading_zeros ( ) as usize / 8 ;
310
321
let bytes_per_index = ( DEP_NODE_SIZE - free_bytes) . saturating_sub ( 1 ) ;
311
322
head |= ( bytes_per_index as u16 ) << Self :: KIND_BITS ;
312
323
313
324
// Encode number of edges + 1 so that we can reserve 0 to indicate that the len doesn't fit
314
325
// in this bitfield.
315
- if edges . len ( ) <= Self :: MAX_INLINE_LEN {
316
- head |= ( edges . len ( ) as u16 + 1 ) << ( Self :: KIND_BITS + Self :: WIDTH_BITS ) ;
326
+ if edge_count <= Self :: MAX_INLINE_LEN {
327
+ head |= ( edge_count as u16 + 1 ) << ( Self :: KIND_BITS + Self :: WIDTH_BITS ) ;
317
328
}
318
329
319
330
let hash: Fingerprint = node. hash . into ( ) ;
@@ -327,10 +338,10 @@ impl<D: Deps> SerializedNodeHeader<D> {
327
338
#[ cfg( debug_assertions) ]
328
339
{
329
340
let res = Self { bytes, _marker : PhantomData } ;
330
- assert_eq ! ( node_info . fingerprint, res. fingerprint( ) ) ;
331
- assert_eq ! ( node_info . node, res. node( ) ) ;
341
+ assert_eq ! ( fingerprint, res. fingerprint( ) ) ;
342
+ assert_eq ! ( node, res. node( ) ) ;
332
343
if let Some ( len) = res. len ( ) {
333
- assert_eq ! ( node_info . edges . len ( ) , len) ;
344
+ assert_eq ! ( edge_count , len) ;
334
345
}
335
346
}
336
347
Self { bytes, _marker : PhantomData }
@@ -393,21 +404,61 @@ struct NodeInfo {
393
404
394
405
impl NodeInfo {
395
406
fn encode < D : Deps > ( & self , e : & mut FileEncoder ) {
396
- let header = SerializedNodeHeader :: < D > :: new ( self ) ;
407
+ let NodeInfo { node, fingerprint, ref edges } = * self ;
408
+ let header =
409
+ SerializedNodeHeader :: < D > :: new ( node, fingerprint, edges. max_index ( ) , edges. len ( ) ) ;
397
410
e. write_array ( header. bytes ) ;
398
411
399
412
if header. len ( ) . is_none ( ) {
400
- e. emit_usize ( self . edges . len ( ) ) ;
413
+ e. emit_usize ( edges. len ( ) ) ;
401
414
}
402
415
403
416
let bytes_per_index = header. bytes_per_index ( ) ;
404
- for node_index in self . edges . iter ( ) {
417
+ for node_index in edges. iter ( ) {
405
418
e. write_with ( |dest| {
406
419
* dest = node_index. as_u32 ( ) . to_le_bytes ( ) ;
407
420
bytes_per_index
408
421
} ) ;
409
422
}
410
423
}
424
+
425
+ /// Encode a node that was promoted from the previous graph. It reads the edges directly from
426
+ /// the previous dep graph and expects all edges to already have a new dep node index assigned.
427
+ /// This avoids the overhead of constructing `EdgesVec`, which would be needed to call `encode`.
428
+ #[ inline]
429
+ fn encode_promoted < D : Deps > (
430
+ e : & mut FileEncoder ,
431
+ node : DepNode ,
432
+ fingerprint : Fingerprint ,
433
+ prev_index : SerializedDepNodeIndex ,
434
+ prev_index_to_index : & IndexVec < SerializedDepNodeIndex , Option < DepNodeIndex > > ,
435
+ previous : & SerializedDepGraph ,
436
+ ) -> usize {
437
+ let edges = previous. edge_targets_from ( prev_index) ;
438
+ let edge_count = edges. size_hint ( ) . 0 ;
439
+
440
+ // Find the highest edge in the new dep node indices
441
+ let edge_max =
442
+ edges. clone ( ) . map ( |i| prev_index_to_index[ i] . unwrap ( ) . as_u32 ( ) ) . max ( ) . unwrap_or ( 0 ) ;
443
+
444
+ let header = SerializedNodeHeader :: < D > :: new ( node, fingerprint, edge_max, edge_count) ;
445
+ e. write_array ( header. bytes ) ;
446
+
447
+ if header. len ( ) . is_none ( ) {
448
+ e. emit_usize ( edge_count) ;
449
+ }
450
+
451
+ let bytes_per_index = header. bytes_per_index ( ) ;
452
+ for node_index in edges {
453
+ let node_index = prev_index_to_index[ node_index] . unwrap ( ) ;
454
+ e. write_with ( |dest| {
455
+ * dest = node_index. as_u32 ( ) . to_le_bytes ( ) ;
456
+ bytes_per_index
457
+ } ) ;
458
+ }
459
+
460
+ edge_count
461
+ }
411
462
}
412
463
413
464
struct Stat {
@@ -417,6 +468,7 @@ struct Stat {
417
468
}
418
469
419
470
struct EncoderState < D : Deps > {
471
+ previous : Arc < SerializedDepGraph > ,
420
472
encoder : FileEncoder ,
421
473
total_node_count : usize ,
422
474
total_edge_count : usize ,
@@ -428,8 +480,9 @@ struct EncoderState<D: Deps> {
428
480
}
429
481
430
482
impl < D : Deps > EncoderState < D > {
431
- fn new ( encoder : FileEncoder , record_stats : bool ) -> Self {
483
+ fn new ( encoder : FileEncoder , record_stats : bool , previous : Arc < SerializedDepGraph > ) -> Self {
432
484
Self {
485
+ previous,
433
486
encoder,
434
487
total_edge_count : 0 ,
435
488
total_node_count : 0 ,
@@ -439,38 +492,101 @@ impl<D: Deps> EncoderState<D> {
439
492
}
440
493
}
441
494
442
- fn encode_node (
495
+ #[ inline]
496
+ fn record (
443
497
& mut self ,
444
- node : & NodeInfo ,
498
+ node : DepNode ,
499
+ edge_count : usize ,
500
+ edges : impl FnOnce ( & mut Self ) -> Vec < DepNodeIndex > ,
445
501
record_graph : & Option < Lock < DepGraphQuery > > ,
446
502
) -> DepNodeIndex {
447
503
let index = DepNodeIndex :: new ( self . total_node_count ) ;
448
- self . total_node_count += 1 ;
449
- self . kind_stats [ node. node . kind . as_usize ( ) ] += 1 ;
450
504
451
- let edge_count = node. edges . len ( ) ;
505
+ self . total_node_count += 1 ;
506
+ self . kind_stats [ node. kind . as_usize ( ) ] += 1 ;
452
507
self . total_edge_count += edge_count;
453
508
454
509
if let Some ( record_graph) = & record_graph {
455
- // Do not ICE when a query is called from within `with_query`.
456
- if let Some ( record_graph) = & mut record_graph. try_lock ( ) {
457
- record_graph. push ( index, node. node , & node. edges ) ;
458
- }
510
+ // Call `edges` before the outlined code to allow the closure to be optimized out.
511
+ let edges = edges ( self ) ;
512
+
513
+ // Outline the build of the full dep graph as it's typically disabled and cold.
514
+ outline ( move || {
515
+ // Do not ICE when a query is called from within `with_query`.
516
+ if let Some ( record_graph) = & mut record_graph. try_lock ( ) {
517
+ record_graph. push ( index, node, & edges) ;
518
+ }
519
+ } ) ;
459
520
}
460
521
461
522
if let Some ( stats) = & mut self . stats {
462
- let kind = node. node . kind ;
463
-
464
- let stat = stats. entry ( kind) . or_insert ( Stat { kind, node_counter : 0 , edge_counter : 0 } ) ;
465
- stat. node_counter += 1 ;
466
- stat. edge_counter += edge_count as u64 ;
523
+ let kind = node. kind ;
524
+
525
+ // Outline the stats code as it's typically disabled and cold.
526
+ outline ( move || {
527
+ let stat =
528
+ stats. entry ( kind) . or_insert ( Stat { kind, node_counter : 0 , edge_counter : 0 } ) ;
529
+ stat. node_counter += 1 ;
530
+ stat. edge_counter += edge_count as u64 ;
531
+ } ) ;
467
532
}
468
533
469
- let encoder = & mut self . encoder ;
470
- node. encode :: < D > ( encoder) ;
471
534
index
472
535
}
473
536
537
+ /// Encodes a node to the current graph.
538
+ fn encode_node (
539
+ & mut self ,
540
+ node : & NodeInfo ,
541
+ record_graph : & Option < Lock < DepGraphQuery > > ,
542
+ ) -> DepNodeIndex {
543
+ node. encode :: < D > ( & mut self . encoder ) ;
544
+ self . record (
545
+ node. node ,
546
+ node. edges . len ( ) ,
547
+ |_| node. edges [ ..] . iter ( ) . copied ( ) . collect ( ) ,
548
+ record_graph,
549
+ )
550
+ }
551
+
552
+ /// Encodes a node that was promoted from the previous graph. It reads the information directly from
553
+ /// the previous dep graph for performance reasons.
554
+ ///
555
+ /// This differs from `encode_node` where you have to explictly provide the relevant `NodeInfo`.
556
+ ///
557
+ /// It expects all edges to already have a new dep node index assigned.
558
+ #[ inline]
559
+ fn encode_promoted_node (
560
+ & mut self ,
561
+ prev_index : SerializedDepNodeIndex ,
562
+ record_graph : & Option < Lock < DepGraphQuery > > ,
563
+ prev_index_to_index : & IndexVec < SerializedDepNodeIndex , Option < DepNodeIndex > > ,
564
+ ) -> DepNodeIndex {
565
+ let node = self . previous . index_to_node ( prev_index) ;
566
+
567
+ let fingerprint = self . previous . fingerprint_by_index ( prev_index) ;
568
+ let edge_count = NodeInfo :: encode_promoted :: < D > (
569
+ & mut self . encoder ,
570
+ node,
571
+ fingerprint,
572
+ prev_index,
573
+ prev_index_to_index,
574
+ & self . previous ,
575
+ ) ;
576
+
577
+ self . record (
578
+ node,
579
+ edge_count,
580
+ |this| {
581
+ this. previous
582
+ . edge_targets_from ( prev_index)
583
+ . map ( |i| prev_index_to_index[ i] . unwrap ( ) )
584
+ . collect ( )
585
+ } ,
586
+ record_graph,
587
+ )
588
+ }
589
+
474
590
fn finish ( self , profiler : & SelfProfilerRef ) -> FileEncodeResult {
475
591
let Self {
476
592
mut encoder,
@@ -479,6 +595,7 @@ impl<D: Deps> EncoderState<D> {
479
595
stats : _,
480
596
kind_stats,
481
597
marker : _,
598
+ previous : _,
482
599
} = self ;
483
600
484
601
let node_count = total_node_count. try_into ( ) . unwrap ( ) ;
@@ -520,9 +637,10 @@ impl<D: Deps> GraphEncoder<D> {
520
637
record_graph : bool ,
521
638
record_stats : bool ,
522
639
profiler : & SelfProfilerRef ,
640
+ previous : Arc < SerializedDepGraph > ,
523
641
) -> Self {
524
642
let record_graph = record_graph. then ( || Lock :: new ( DepGraphQuery :: new ( prev_node_count) ) ) ;
525
- let status = Lock :: new ( Some ( EncoderState :: new ( encoder, record_stats) ) ) ;
643
+ let status = Lock :: new ( Some ( EncoderState :: new ( encoder, record_stats, previous ) ) ) ;
526
644
GraphEncoder { status, record_graph, profiler : profiler. clone ( ) }
527
645
}
528
646
@@ -596,6 +714,22 @@ impl<D: Deps> GraphEncoder<D> {
596
714
self . status . lock ( ) . as_mut ( ) . unwrap ( ) . encode_node ( & node, & self . record_graph )
597
715
}
598
716
717
+ /// Encodes a node that was promoted from the previous graph. It reads the information directly from
718
+ /// the previous dep graph and expects all edges to already have a new dep node index assigned.
719
+ #[ inline]
720
+ pub ( crate ) fn send_promoted (
721
+ & self ,
722
+ prev_index : SerializedDepNodeIndex ,
723
+ prev_index_to_index : & IndexVec < SerializedDepNodeIndex , Option < DepNodeIndex > > ,
724
+ ) -> DepNodeIndex {
725
+ let _prof_timer = self . profiler . generic_activity ( "incr_comp_encode_dep_graph" ) ;
726
+ self . status . lock ( ) . as_mut ( ) . unwrap ( ) . encode_promoted_node (
727
+ prev_index,
728
+ & self . record_graph ,
729
+ prev_index_to_index,
730
+ )
731
+ }
732
+
599
733
pub fn finish ( & self ) -> FileEncodeResult {
600
734
let _prof_timer = self . profiler . generic_activity ( "incr_comp_encode_dep_graph_finish" ) ;
601
735
0 commit comments