@@ -16,6 +16,7 @@ use session::config::OutputType;
16
16
use std:: cell:: { Ref , RefCell } ;
17
17
use std:: hash:: Hash ;
18
18
use std:: rc:: Rc ;
19
+ use ty:: TyCtxt ;
19
20
use util:: common:: { ProfileQueriesMsg , profq_msg} ;
20
21
21
22
use ich:: Fingerprint ;
@@ -28,6 +29,7 @@ use super::edges::{self, DepGraphEdges};
28
29
use super :: serialized:: { SerializedDepGraph , SerializedDepNodeIndex } ;
29
30
use super :: prev:: PreviousDepGraph ;
30
31
32
+
31
33
#[ derive( Clone ) ]
32
34
pub struct DepGraph {
33
35
data : Option < Rc < DepGraphData > > ,
@@ -62,8 +64,7 @@ impl DepNodeIndex {
62
64
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
63
65
pub enum DepNodeColor {
64
66
Red ,
65
- Green ,
66
- Gray
67
+ Green ( DepNodeIndex )
67
68
}
68
69
69
70
struct DepGraphData {
@@ -178,6 +179,8 @@ impl DepGraph {
178
179
R : HashStable < HCX > ,
179
180
{
180
181
if let Some ( ref data) = self . data {
182
+ debug_assert ! ( !data. colors. borrow( ) . contains_key( & key) ) ;
183
+
181
184
data. edges . borrow_mut ( ) . push_task ( key) ;
182
185
data. current . borrow_mut ( ) . push_task ( key) ;
183
186
if cfg ! ( debug_assertions) {
@@ -212,7 +215,10 @@ impl DepGraph {
212
215
let prev_fingerprint = data. previous . fingerprint_of ( & key) ;
213
216
214
217
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
+ } )
216
222
} else {
217
223
DepNodeColor :: Red
218
224
} ;
@@ -310,18 +316,6 @@ impl DepGraph {
310
316
self . data . as_ref ( ) . unwrap ( ) . previous . fingerprint_of ( dep_node)
311
317
}
312
318
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
-
325
319
/// Indicates that a previous work product exists for `v`. This is
326
320
/// invoked during initial start-up based on what nodes are clean
327
321
/// (and what files exist in the incr. directory).
@@ -426,6 +420,128 @@ impl DepGraph {
426
420
edge_list_data,
427
421
}
428
422
}
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
+ }
429
545
}
430
546
431
547
/// A "work product" is an intermediate result that we save into the
0 commit comments