@@ -74,7 +74,7 @@ struct DepGraphData {
74
74
/// nodes and edges as well as all fingerprints of nodes that have them.
75
75
previous : PreviousDepGraph ,
76
76
77
- colors : RefCell < FxHashMap < DepNode , DepNodeColor > > ,
77
+ colors : RefCell < DepNodeColorMap > ,
78
78
79
79
/// When we load, there may be `.o` files, cached mir, or other such
80
80
/// things available to us. If we find that they are not dirty, we
@@ -97,16 +97,18 @@ impl DepGraph {
97
97
// Pre-allocate the fingerprints array. We over-allocate a little so
98
98
// that we hopefully don't have to re-allocate during this compilation
99
99
// session.
100
+ let prev_graph_node_count = prev_graph. node_count ( ) ;
101
+
100
102
let fingerprints = IndexVec :: from_elem_n ( Fingerprint :: ZERO ,
101
- ( prev_graph . node_count ( ) * 115 ) / 100 ) ;
103
+ ( prev_graph_node_count * 115 ) / 100 ) ;
102
104
DepGraph {
103
105
data : Some ( Rc :: new ( DepGraphData {
104
106
previous_work_products : RefCell :: new ( FxHashMap ( ) ) ,
105
107
work_products : RefCell :: new ( FxHashMap ( ) ) ,
106
108
dep_node_debug : RefCell :: new ( FxHashMap ( ) ) ,
107
109
current : RefCell :: new ( CurrentDepGraph :: new ( ) ) ,
108
110
previous : prev_graph,
109
- colors : RefCell :: new ( FxHashMap ( ) ) ,
111
+ colors : RefCell :: new ( DepNodeColorMap :: new ( prev_graph_node_count ) ) ,
110
112
loaded_from_cache : RefCell :: new ( FxHashMap ( ) ) ,
111
113
} ) ) ,
112
114
fingerprints : Rc :: new ( RefCell :: new ( fingerprints) ) ,
@@ -213,8 +215,6 @@ impl DepGraph {
213
215
R : HashStable < HCX > ,
214
216
{
215
217
if let Some ( ref data) = self . data {
216
- debug_assert ! ( !data. colors. borrow( ) . contains_key( & key) ) ;
217
-
218
218
push ( & data. current , key) ;
219
219
if cfg ! ( debug_assertions) {
220
220
profq_msg ( ProfileQueriesMsg :: TaskBegin ( key. clone ( ) ) )
@@ -254,19 +254,21 @@ impl DepGraph {
254
254
}
255
255
256
256
// Determine the color of the new DepNode.
257
- {
258
- let prev_fingerprint = data. previous . fingerprint_of ( & key ) ;
257
+ if let Some ( prev_index ) = data . previous . node_to_index_opt ( & key ) {
258
+ let prev_fingerprint = data. previous . fingerprint_by_index ( prev_index ) ;
259
259
260
- let color = if Some ( current_fingerprint) == prev_fingerprint {
260
+ let color = if current_fingerprint == prev_fingerprint {
261
261
DepNodeColor :: Green ( dep_node_index)
262
262
} else {
263
263
DepNodeColor :: Red
264
264
} ;
265
265
266
- let old_value = data. colors . borrow_mut ( ) . insert ( key , color ) ;
267
- debug_assert ! ( old_value . is_none( ) ,
266
+ let mut colors = data. colors . borrow_mut ( ) ;
267
+ debug_assert ! ( colors . get ( prev_index ) . is_none( ) ,
268
268
"DepGraph::with_task() - Duplicate DepNodeColor \
269
269
insertion for {:?}", key) ;
270
+
271
+ colors. insert ( prev_index, color) ;
270
272
}
271
273
272
274
( result, dep_node_index)
@@ -281,9 +283,11 @@ impl DepGraph {
281
283
let mut fingerprints = self . fingerprints . borrow_mut ( ) ;
282
284
let dep_node_index = DepNodeIndex :: new ( fingerprints. len ( ) ) ;
283
285
fingerprints. push ( fingerprint) ;
286
+
284
287
debug_assert ! ( fingerprints[ dep_node_index] == fingerprint,
285
288
"DepGraph::with_task() - Assigned fingerprint to \
286
289
unexpected index for {:?}", key) ;
290
+
287
291
( result, dep_node_index)
288
292
} else {
289
293
( task ( cx, arg) , DepNodeIndex :: INVALID )
@@ -356,6 +360,15 @@ impl DepGraph {
356
360
. unwrap ( )
357
361
}
358
362
363
+ #[ inline]
364
+ pub fn dep_node_exists ( & self , dep_node : & DepNode ) -> bool {
365
+ if let Some ( ref data) = self . data {
366
+ data. current . borrow_mut ( ) . node_to_node_index . contains_key ( dep_node)
367
+ } else {
368
+ false
369
+ }
370
+ }
371
+
359
372
#[ inline]
360
373
pub fn fingerprint_of ( & self , dep_node_index : DepNodeIndex ) -> Fingerprint {
361
374
match self . fingerprints . borrow ( ) . get ( dep_node_index) {
@@ -495,7 +508,17 @@ impl DepGraph {
495
508
}
496
509
497
510
pub fn node_color ( & self , dep_node : & DepNode ) -> Option < DepNodeColor > {
498
- self . data . as_ref ( ) . and_then ( |data| data. colors . borrow ( ) . get ( dep_node) . cloned ( ) )
511
+ if let Some ( ref data) = self . data {
512
+ if let Some ( prev_index) = data. previous . node_to_index_opt ( dep_node) {
513
+ return data. colors . borrow ( ) . get ( prev_index)
514
+ } else {
515
+ // This is a node that did not exist in the previous compilation
516
+ // session, so we consider it to be red.
517
+ return Some ( DepNodeColor :: Red )
518
+ }
519
+ }
520
+
521
+ None
499
522
}
500
523
501
524
pub fn try_mark_green < ' tcx > ( & self ,
@@ -505,7 +528,6 @@ impl DepGraph {
505
528
debug ! ( "try_mark_green({:?}) - BEGIN" , dep_node) ;
506
529
let data = self . data . as_ref ( ) . unwrap ( ) ;
507
530
508
- debug_assert ! ( !data. colors. borrow( ) . contains_key( dep_node) ) ;
509
531
debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
510
532
511
533
if dep_node. kind . is_input ( ) {
@@ -535,19 +557,22 @@ impl DepGraph {
535
557
}
536
558
} ;
537
559
560
+ debug_assert ! ( data. colors. borrow( ) . get( prev_dep_node_index) . is_none( ) ) ;
561
+
538
562
let mut current_deps = Vec :: new ( ) ;
539
563
540
564
for & dep_dep_node_index in prev_deps {
541
- let dep_dep_node = & data. previous . index_to_node ( dep_dep_node_index) ;
565
+ let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
542
566
543
- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node) . cloned ( ) ;
544
567
match dep_dep_node_color {
545
568
Some ( DepNodeColor :: Green ( node_index) ) => {
546
569
// This dependency has been marked as green before, we are
547
570
// still fine and can continue with checking the other
548
571
// dependencies.
549
572
debug ! ( "try_mark_green({:?}) --- found dependency {:?} to \
550
- be immediately green", dep_node, dep_dep_node) ;
573
+ be immediately green",
574
+ dep_node,
575
+ data. previous. index_to_node( dep_dep_node_index) ) ;
551
576
current_deps. push ( node_index) ;
552
577
}
553
578
Some ( DepNodeColor :: Red ) => {
@@ -556,10 +581,14 @@ impl DepGraph {
556
581
// mark the DepNode as green and also don't need to bother
557
582
// with checking any of the other dependencies.
558
583
debug ! ( "try_mark_green({:?}) - END - dependency {:?} was \
559
- immediately red", dep_node, dep_dep_node) ;
584
+ immediately red",
585
+ dep_node,
586
+ data. previous. index_to_node( dep_dep_node_index) ) ;
560
587
return None
561
588
}
562
589
None => {
590
+ let dep_dep_node = & data. previous . index_to_node ( dep_dep_node_index) ;
591
+
563
592
// We don't know the state of this dependency. If it isn't
564
593
// an input node, let's try to mark it green recursively.
565
594
if !dep_dep_node. kind . is_input ( ) {
@@ -601,10 +630,8 @@ impl DepGraph {
601
630
debug ! ( "try_mark_green({:?}) --- trying to force \
602
631
dependency {:?}", dep_node, dep_dep_node) ;
603
632
if :: ty:: maps:: force_from_dep_node ( tcx, dep_dep_node) {
604
- let dep_dep_node_color = data. colors
605
- . borrow ( )
606
- . get ( dep_dep_node)
607
- . cloned ( ) ;
633
+ let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
634
+
608
635
match dep_dep_node_color {
609
636
Some ( DepNodeColor :: Green ( node_index) ) => {
610
637
debug ! ( "try_mark_green({:?}) --- managed to \
@@ -681,26 +708,21 @@ impl DepGraph {
681
708
}
682
709
683
710
// ... and finally storing a "Green" entry in the color map.
684
- let old_color = data. colors
685
- . borrow_mut ( )
686
- . insert ( * dep_node, DepNodeColor :: Green ( dep_node_index) ) ;
687
- debug_assert ! ( old_color. is_none( ) ,
711
+ let mut colors = data. colors . borrow_mut ( ) ;
712
+ debug_assert ! ( colors. get( prev_dep_node_index) . is_none( ) ,
688
713
"DepGraph::try_mark_green() - Duplicate DepNodeColor \
689
714
insertion for {:?}", dep_node) ;
690
715
716
+ colors. insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
717
+
691
718
debug ! ( "try_mark_green({:?}) - END - successfully marked as green" , dep_node) ;
692
719
Some ( dep_node_index)
693
720
}
694
721
695
- // Used in various assertions
696
- pub fn is_green ( & self , dep_node_index : DepNodeIndex ) -> bool {
697
- let dep_node = self . data . as_ref ( ) . unwrap ( ) . current . borrow ( ) . nodes [ dep_node_index] ;
698
- self . data . as_ref ( ) . unwrap ( ) . colors . borrow ( ) . get ( & dep_node) . map ( |& color| {
699
- match color {
700
- DepNodeColor :: Red => false ,
701
- DepNodeColor :: Green ( _) => true ,
702
- }
703
- } ) . unwrap_or ( false )
722
+ // Returns true if the given node has been marked as green during the
723
+ // current compilation session. Used in various assertions
724
+ pub fn is_green ( & self , dep_node : & DepNode ) -> bool {
725
+ self . node_color ( dep_node) . map ( |c| c. is_green ( ) ) . unwrap_or ( false )
704
726
}
705
727
706
728
// This method loads all on-disk cacheable query results into memory, so
@@ -714,20 +736,25 @@ impl DepGraph {
714
736
pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
715
737
let green_nodes: Vec < DepNode > = {
716
738
let data = self . data . as_ref ( ) . unwrap ( ) ;
717
- data. colors . borrow ( ) . iter ( ) . filter_map ( |( dep_node, color) | match color {
718
- DepNodeColor :: Green ( _) => {
719
- if dep_node. cache_on_disk ( tcx) {
720
- Some ( * dep_node)
721
- } else {
739
+ let colors = data. colors . borrow ( ) ;
740
+ colors. values . indices ( ) . filter_map ( |prev_index| {
741
+ match colors. get ( prev_index) {
742
+ Some ( DepNodeColor :: Green ( _) ) => {
743
+ let dep_node = data. previous . index_to_node ( prev_index) ;
744
+ if dep_node. cache_on_disk ( tcx) {
745
+ Some ( dep_node)
746
+ } else {
747
+ None
748
+ }
749
+ }
750
+ None |
751
+ Some ( DepNodeColor :: Red ) => {
752
+ // We can skip red nodes because a node can only be marked
753
+ // as red if the query result was recomputed and thus is
754
+ // already in memory.
722
755
None
723
756
}
724
757
}
725
- DepNodeColor :: Red => {
726
- // We can skip red nodes because a node can only be marked
727
- // as red if the query result was recomputed and thus is
728
- // already in memory.
729
- None
730
- }
731
758
} ) . collect ( )
732
759
} ;
733
760
@@ -1052,3 +1079,36 @@ enum OpenTask {
1052
1079
node : DepNode ,
1053
1080
} ,
1054
1081
}
1082
+
1083
+ // A data structure that stores Option<DepNodeColor> values as a contiguous
1084
+ // array, using one u32 per entry.
1085
+ struct DepNodeColorMap {
1086
+ values : IndexVec < SerializedDepNodeIndex , u32 > ,
1087
+ }
1088
+
1089
+ const COMPRESSED_NONE : u32 = 0 ;
1090
+ const COMPRESSED_RED : u32 = 1 ;
1091
+ const COMPRESSED_FIRST_GREEN : u32 = 2 ;
1092
+
1093
+ impl DepNodeColorMap {
1094
+ fn new ( size : usize ) -> DepNodeColorMap {
1095
+ DepNodeColorMap {
1096
+ values : IndexVec :: from_elem_n ( COMPRESSED_NONE , size)
1097
+ }
1098
+ }
1099
+
1100
+ fn get ( & self , index : SerializedDepNodeIndex ) -> Option < DepNodeColor > {
1101
+ match self . values [ index] {
1102
+ COMPRESSED_NONE => None ,
1103
+ COMPRESSED_RED => Some ( DepNodeColor :: Red ) ,
1104
+ value => Some ( DepNodeColor :: Green ( DepNodeIndex ( value - COMPRESSED_FIRST_GREEN ) ) )
1105
+ }
1106
+ }
1107
+
1108
+ fn insert ( & mut self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1109
+ self . values [ index] = match color {
1110
+ DepNodeColor :: Red => COMPRESSED_RED ,
1111
+ DepNodeColor :: Green ( index) => index. 0 + COMPRESSED_FIRST_GREEN ,
1112
+ }
1113
+ }
1114
+ }
0 commit comments