@@ -16,6 +16,7 @@ use session::config::OutputType;
1616use std:: cell:: { Ref , RefCell } ;
1717use std:: hash:: Hash ;
1818use std:: rc:: Rc ;
19+ use ty:: TyCtxt ;
1920use util:: common:: { ProfileQueriesMsg , profq_msg} ;
2021
2122use ich:: Fingerprint ;
@@ -28,6 +29,7 @@ use super::edges::{self, DepGraphEdges};
2829use super :: serialized:: { SerializedDepGraph , SerializedDepNodeIndex } ;
2930use super :: prev:: PreviousDepGraph ;
3031
32+
3133#[ derive( Clone ) ]
3234pub struct DepGraph {
3335 data : Option < Rc < DepGraphData > > ,
@@ -62,8 +64,7 @@ impl DepNodeIndex {
6264#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
6365pub enum DepNodeColor {
6466 Red ,
65- Green ,
66- Gray
67+ Green ( DepNodeIndex )
6768}
6869
6970struct DepGraphData {
@@ -178,6 +179,8 @@ impl DepGraph {
178179 R : HashStable < HCX > ,
179180 {
180181 if let Some ( ref data) = self . data {
182+ debug_assert ! ( !data. colors. borrow( ) . contains_key( & key) ) ;
183+
181184 data. edges . borrow_mut ( ) . push_task ( key) ;
182185 data. current . borrow_mut ( ) . push_task ( key) ;
183186 if cfg ! ( debug_assertions) {
@@ -212,7 +215,10 @@ impl DepGraph {
212215 let prev_fingerprint = data. previous . fingerprint_of ( & key) ;
213216
214217 let color = if Some ( current_fingerprint) == prev_fingerprint {
215- DepNodeColor :: Green
218+ DepNodeColor :: Green ( DepNodeIndex {
219+ legacy : dep_node_index_legacy,
220+ new : dep_node_index_new,
221+ } )
216222 } else {
217223 DepNodeColor :: Red
218224 } ;
@@ -310,18 +316,6 @@ impl DepGraph {
310316 self . data . as_ref ( ) . unwrap ( ) . previous . fingerprint_of ( dep_node)
311317 }
312318
313- pub fn node_color ( & self , dep_node : & DepNode ) -> DepNodeColor {
314- match self . data . as_ref ( ) . unwrap ( ) . colors . borrow ( ) . get ( dep_node) {
315- Some ( & color) => {
316- debug_assert ! ( color != DepNodeColor :: Gray ) ;
317- color
318- }
319- None => {
320- DepNodeColor :: Gray
321- }
322- }
323- }
324-
325319 /// Indicates that a previous work product exists for `v`. This is
326320 /// invoked during initial start-up based on what nodes are clean
327321 /// (and what files exist in the incr. directory).
@@ -426,6 +420,128 @@ impl DepGraph {
426420 edge_list_data,
427421 }
428422 }
423+
424+ pub fn node_color ( & self , dep_node : & DepNode ) -> Option < DepNodeColor > {
425+ self . data . as_ref ( ) . and_then ( |data| data. colors . borrow ( ) . get ( dep_node) . cloned ( ) )
426+ }
427+
428+ pub fn try_mark_green ( & self ,
429+ tcx : TyCtxt ,
430+ dep_node : & DepNode )
431+ -> Option < DepNodeIndex > {
432+ let data = self . data . as_ref ( ) . unwrap ( ) ;
433+
434+ debug_assert ! ( !data. colors. borrow( ) . contains_key( dep_node) ) ;
435+ debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
436+
437+ if dep_node. kind . is_input ( ) {
438+ // We should only hit try_mark_green() for inputs that do not exist
439+ // anymore in the current compilation session. Existing inputs are
440+ // eagerly marked as either red/green before any queries are
441+ // executed.
442+ debug_assert ! ( dep_node. extract_def_id( tcx) . is_none( ) ) ;
443+ return None ;
444+ }
445+
446+ let ( prev_deps, prev_dep_node_index) = match data. previous . edges_from ( dep_node) {
447+ Some ( prev) => {
448+ // This DepNode and the corresponding query invocation existed
449+ // in the previous compilation session too, so we can try to
450+ // mark it as green by recursively marking all of its
451+ // dependencies green.
452+ prev
453+ }
454+ None => {
455+ // This DepNode did not exist in the previous compilation session,
456+ // so we cannot mark it as green.
457+ return None
458+ }
459+ } ;
460+
461+ let mut current_deps = Vec :: new ( ) ;
462+
463+ for & dep_dep_node in prev_deps {
464+ let dep_dep_node = & data. previous . index_to_node ( dep_dep_node) ;
465+ let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node) . cloned ( ) ;
466+ match dep_dep_node_color {
467+ Some ( DepNodeColor :: Green ( node_index) ) => {
468+ // This dependency has been marked as green before, we are
469+ // still fine and can continue with checking the other
470+ // dependencies.
471+ current_deps. push ( node_index) ;
472+ }
473+ Some ( DepNodeColor :: Red ) => {
474+ // We found a dependency the value of which has changed
475+ // compared to the previous compilation session. We cannot
476+ // mark the DepNode as green and also don't need to bother
477+ // with checking any of the other dependencies.
478+ return None
479+ }
480+ None => {
481+ // We don't know the state of this dependency. Let's try to
482+ // mark it green.
483+ if let Some ( node_index) = self . try_mark_green ( tcx, dep_dep_node) {
484+ current_deps. push ( node_index) ;
485+ } else {
486+ // We failed to mark it green. This can have various
487+ // reasons.
488+ return None
489+ }
490+ }
491+ }
492+ }
493+
494+ // If we got here without hitting a `return` that means that all
495+ // dependencies of this DepNode could be marked as green. Therefore we
496+ // can also mark this DepNode as green. We do so by...
497+
498+ // ... allocating an entry for it in the current dependency graph and
499+ // adding all the appropriate edges imported from the previous graph ...
500+ let node_index_new = data. current
501+ . borrow_mut ( )
502+ . alloc_node ( * dep_node,
503+ current_deps. iter ( ) . map ( |n| n. new ) . collect ( ) ) ;
504+ let dep_node_index_legacy = {
505+ let mut legacy_graph = data. edges . borrow_mut ( ) ;
506+ legacy_graph. push_task ( * dep_node) ;
507+ for node_index in current_deps. into_iter ( ) . map ( |n| n. legacy ) {
508+ legacy_graph. read_index ( node_index) ;
509+ }
510+ legacy_graph. pop_task ( * dep_node)
511+ } ;
512+
513+ // ... copying the fingerprint from the previous graph too, so we don't
514+ // have to recompute it ...
515+ let fingerprint = data. previous . fingerprint_by_index ( prev_dep_node_index) ;
516+ assert ! ( self . fingerprints
517+ . borrow_mut( )
518+ . insert( * dep_node, fingerprint)
519+ . is_none( ) ) ;
520+
521+ let node_index = DepNodeIndex {
522+ legacy : dep_node_index_legacy,
523+ new : node_index_new,
524+ } ;
525+
526+ // ... and finally storing a "Green" entry in the color map.
527+ assert ! ( data. colors
528+ . borrow_mut( )
529+ . insert( * dep_node, DepNodeColor :: Green ( node_index) )
530+ . is_none( ) ) ;
531+
532+ Some ( node_index)
533+ }
534+
535+ // Used in various assertions
536+ pub fn is_green ( & self , dep_node_index : DepNodeIndex ) -> bool {
537+ let dep_node = self . data . as_ref ( ) . unwrap ( ) . current . borrow ( ) . nodes [ dep_node_index. new ] ;
538+ self . data . as_ref ( ) . unwrap ( ) . colors . borrow ( ) . get ( & dep_node) . map ( |& color| {
539+ match color {
540+ DepNodeColor :: Red => false ,
541+ DepNodeColor :: Green ( _) => true ,
542+ }
543+ } ) . unwrap_or ( false )
544+ }
429545}
430546
431547/// A "work product" is an intermediate result that we save into the
0 commit comments