@@ -74,7 +74,7 @@ struct DepGraphData {
7474 /// nodes and edges as well as all fingerprints of nodes that have them.
7575 previous : PreviousDepGraph ,
7676
77- colors : RefCell < FxHashMap < DepNode , DepNodeColor > > ,
77+ colors : RefCell < DepNodeColorMap > ,
7878
7979 /// When we load, there may be `.o` files, cached mir, or other such
8080 /// things available to us. If we find that they are not dirty, we
@@ -97,16 +97,18 @@ impl DepGraph {
9797 // Pre-allocate the fingerprints array. We over-allocate a little so
9898 // that we hopefully don't have to re-allocate during this compilation
9999 // session.
100+ let prev_graph_node_count = prev_graph. node_count ( ) ;
101+
100102 let fingerprints = IndexVec :: from_elem_n ( Fingerprint :: ZERO ,
101- ( prev_graph . node_count ( ) * 115 ) / 100 ) ;
103+ ( prev_graph_node_count * 115 ) / 100 ) ;
102104 DepGraph {
103105 data : Some ( Rc :: new ( DepGraphData {
104106 previous_work_products : RefCell :: new ( FxHashMap ( ) ) ,
105107 work_products : RefCell :: new ( FxHashMap ( ) ) ,
106108 dep_node_debug : RefCell :: new ( FxHashMap ( ) ) ,
107109 current : RefCell :: new ( CurrentDepGraph :: new ( ) ) ,
108110 previous : prev_graph,
109- colors : RefCell :: new ( FxHashMap ( ) ) ,
111+ colors : RefCell :: new ( DepNodeColorMap :: new ( prev_graph_node_count ) ) ,
110112 loaded_from_cache : RefCell :: new ( FxHashMap ( ) ) ,
111113 } ) ) ,
112114 fingerprints : Rc :: new ( RefCell :: new ( fingerprints) ) ,
@@ -213,8 +215,6 @@ impl DepGraph {
213215 R : HashStable < HCX > ,
214216 {
215217 if let Some ( ref data) = self . data {
216- debug_assert ! ( !data. colors. borrow( ) . contains_key( & key) ) ;
217-
218218 push ( & data. current , key) ;
219219 if cfg ! ( debug_assertions) {
220220 profq_msg ( ProfileQueriesMsg :: TaskBegin ( key. clone ( ) ) )
@@ -254,19 +254,21 @@ impl DepGraph {
254254 }
255255
256256 // 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 ) ;
259259
260- let color = if Some ( current_fingerprint) == prev_fingerprint {
260+ let color = if current_fingerprint == prev_fingerprint {
261261 DepNodeColor :: Green ( dep_node_index)
262262 } else {
263263 DepNodeColor :: Red
264264 } ;
265265
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( ) ,
268268 "DepGraph::with_task() - Duplicate DepNodeColor \
269269 insertion for {:?}", key) ;
270+
271+ colors. insert ( prev_index, color) ;
270272 }
271273
272274 ( result, dep_node_index)
@@ -281,9 +283,11 @@ impl DepGraph {
281283 let mut fingerprints = self . fingerprints . borrow_mut ( ) ;
282284 let dep_node_index = DepNodeIndex :: new ( fingerprints. len ( ) ) ;
283285 fingerprints. push ( fingerprint) ;
286+
284287 debug_assert ! ( fingerprints[ dep_node_index] == fingerprint,
285288 "DepGraph::with_task() - Assigned fingerprint to \
286289 unexpected index for {:?}", key) ;
290+
287291 ( result, dep_node_index)
288292 } else {
289293 ( task ( cx, arg) , DepNodeIndex :: INVALID )
@@ -356,6 +360,15 @@ impl DepGraph {
356360 . unwrap ( )
357361 }
358362
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+
359372 #[ inline]
360373 pub fn fingerprint_of ( & self , dep_node_index : DepNodeIndex ) -> Fingerprint {
361374 match self . fingerprints . borrow ( ) . get ( dep_node_index) {
@@ -495,7 +508,17 @@ impl DepGraph {
495508 }
496509
497510 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
499522 }
500523
501524 pub fn try_mark_green < ' tcx > ( & self ,
@@ -505,7 +528,6 @@ impl DepGraph {
505528 debug ! ( "try_mark_green({:?}) - BEGIN" , dep_node) ;
506529 let data = self . data . as_ref ( ) . unwrap ( ) ;
507530
508- debug_assert ! ( !data. colors. borrow( ) . contains_key( dep_node) ) ;
509531 debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
510532
511533 if dep_node. kind . is_input ( ) {
@@ -535,19 +557,22 @@ impl DepGraph {
535557 }
536558 } ;
537559
560+ debug_assert ! ( data. colors. borrow( ) . get( prev_dep_node_index) . is_none( ) ) ;
561+
538562 let mut current_deps = Vec :: new ( ) ;
539563
540564 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) ;
542566
543- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node) . cloned ( ) ;
544567 match dep_dep_node_color {
545568 Some ( DepNodeColor :: Green ( node_index) ) => {
546569 // This dependency has been marked as green before, we are
547570 // still fine and can continue with checking the other
548571 // dependencies.
549572 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) ) ;
551576 current_deps. push ( node_index) ;
552577 }
553578 Some ( DepNodeColor :: Red ) => {
@@ -556,10 +581,14 @@ impl DepGraph {
556581 // mark the DepNode as green and also don't need to bother
557582 // with checking any of the other dependencies.
558583 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) ) ;
560587 return None
561588 }
562589 None => {
590+ let dep_dep_node = & data. previous . index_to_node ( dep_dep_node_index) ;
591+
563592 // We don't know the state of this dependency. If it isn't
564593 // an input node, let's try to mark it green recursively.
565594 if !dep_dep_node. kind . is_input ( ) {
@@ -601,10 +630,8 @@ impl DepGraph {
601630 debug ! ( "try_mark_green({:?}) --- trying to force \
602631 dependency {:?}", dep_node, dep_dep_node) ;
603632 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+
608635 match dep_dep_node_color {
609636 Some ( DepNodeColor :: Green ( node_index) ) => {
610637 debug ! ( "try_mark_green({:?}) --- managed to \
@@ -681,26 +708,21 @@ impl DepGraph {
681708 }
682709
683710 // ... 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( ) ,
688713 "DepGraph::try_mark_green() - Duplicate DepNodeColor \
689714 insertion for {:?}", dep_node) ;
690715
716+ colors. insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
717+
691718 debug ! ( "try_mark_green({:?}) - END - successfully marked as green" , dep_node) ;
692719 Some ( dep_node_index)
693720 }
694721
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 )
704726 }
705727
706728 // This method loads all on-disk cacheable query results into memory, so
@@ -714,20 +736,25 @@ impl DepGraph {
714736 pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
715737 let green_nodes: Vec < DepNode > = {
716738 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.
722755 None
723756 }
724757 }
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- }
731758 } ) . collect ( )
732759 } ;
733760
@@ -1052,3 +1079,36 @@ enum OpenTask {
10521079 node : DepNode ,
10531080 } ,
10541081}
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