@@ -13,7 +13,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
13
13
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
14
14
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
15
15
use smallvec:: SmallVec ;
16
- use rustc_data_structures:: sync:: { Lrc , Lock } ;
16
+ use rustc_data_structures:: sync:: { Lrc , Lock , AtomicU32 , Ordering } ;
17
17
use std:: env;
18
18
use std:: hash:: Hash ;
19
19
use std:: collections:: hash_map:: Entry ;
@@ -68,7 +68,7 @@ struct DepGraphData {
68
68
/// nodes and edges as well as all fingerprints of nodes that have them.
69
69
previous : PreviousDepGraph ,
70
70
71
- colors : Lock < DepNodeColorMap > ,
71
+ colors : DepNodeColorMap ,
72
72
73
73
/// When we load, there may be `.o` files, cached mir, or other such
74
74
/// things available to us. If we find that they are not dirty, we
@@ -94,7 +94,7 @@ impl DepGraph {
94
94
dep_node_debug : Default :: default ( ) ,
95
95
current : Lock :: new ( CurrentDepGraph :: new ( prev_graph_node_count) ) ,
96
96
previous : prev_graph,
97
- colors : Lock :: new ( DepNodeColorMap :: new ( prev_graph_node_count) ) ,
97
+ colors : DepNodeColorMap :: new ( prev_graph_node_count) ,
98
98
loaded_from_cache : Default :: default ( ) ,
99
99
} ) ) ,
100
100
}
@@ -292,12 +292,11 @@ impl DepGraph {
292
292
DepNodeColor :: Red
293
293
} ;
294
294
295
- let mut colors = data. colors . borrow_mut ( ) ;
296
- debug_assert ! ( colors. get( prev_index) . is_none( ) ,
295
+ debug_assert ! ( data. colors. get( prev_index) . is_none( ) ,
297
296
"DepGraph::with_task() - Duplicate DepNodeColor \
298
297
insertion for {:?}", key) ;
299
298
300
- colors. insert ( prev_index, color) ;
299
+ data . colors . insert ( prev_index, color) ;
301
300
}
302
301
303
302
( result, dep_node_index)
@@ -498,7 +497,7 @@ impl DepGraph {
498
497
pub fn node_color ( & self , dep_node : & DepNode ) -> Option < DepNodeColor > {
499
498
if let Some ( ref data) = self . data {
500
499
if let Some ( prev_index) = data. previous . node_to_index_opt ( dep_node) {
501
- return data. colors . borrow ( ) . get ( prev_index)
500
+ return data. colors . get ( prev_index)
502
501
} else {
503
502
// This is a node that did not exist in the previous compilation
504
503
// session, so we consider it to be red.
@@ -509,56 +508,86 @@ impl DepGraph {
509
508
None
510
509
}
511
510
512
- pub fn try_mark_green < ' tcx > ( & self ,
513
- tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
514
- dep_node : & DepNode )
515
- -> Option < DepNodeIndex > {
516
- debug ! ( "try_mark_green({:?}) - BEGIN" , dep_node) ;
517
- let data = self . data . as_ref ( ) . unwrap ( ) ;
511
+ /// Try to read a node index for the node dep_node.
512
+ /// A node will have an index, when it's already been marked green, or when we can mark it
513
+ /// green. This function will mark the current task as a reader of the specified node, when
514
+ /// a node index can be found for that node.
515
+ pub fn try_mark_green_and_read (
516
+ & self ,
517
+ tcx : TyCtxt < ' _ , ' _ , ' _ > ,
518
+ dep_node : & DepNode
519
+ ) -> Option < ( SerializedDepNodeIndex , DepNodeIndex ) > {
520
+ self . try_mark_green ( tcx, dep_node) . map ( |( prev_index, dep_node_index) | {
521
+ debug_assert ! ( self . is_green( & dep_node) ) ;
522
+ self . read_index ( dep_node_index) ;
523
+ ( prev_index, dep_node_index)
524
+ } )
525
+ }
518
526
519
- #[ cfg( not( parallel_queries) ) ]
520
- debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
521
-
522
- if dep_node. kind . is_input ( ) {
523
- // We should only hit try_mark_green() for inputs that do not exist
524
- // anymore in the current compilation session. Existing inputs are
525
- // eagerly marked as either red/green before any queries are
526
- // executed.
527
- debug_assert ! ( dep_node. extract_def_id( tcx) . is_none( ) ) ;
528
- debug ! ( "try_mark_green({:?}) - END - DepNode is deleted input" , dep_node) ;
529
- return None ;
530
- }
527
+ pub fn try_mark_green (
528
+ & self ,
529
+ tcx : TyCtxt < ' _ , ' _ , ' _ > ,
530
+ dep_node : & DepNode
531
+ ) -> Option < ( SerializedDepNodeIndex , DepNodeIndex ) > {
532
+ debug_assert ! ( !dep_node. kind. is_input( ) ) ;
531
533
532
- let ( prev_deps, prev_dep_node_index) = match data. previous . edges_from ( dep_node) {
533
- Some ( prev) => {
534
- // This DepNode and the corresponding query invocation existed
535
- // in the previous compilation session too, so we can try to
536
- // mark it as green by recursively marking all of its
537
- // dependencies green.
538
- prev
539
- }
534
+ // Return None if the dep graph is disabled
535
+ let data = self . data . as_ref ( ) ?;
536
+
537
+ // Return None if the dep node didn't exist in the previous session
538
+ let prev_index = data. previous . node_to_index_opt ( dep_node) ?;
539
+
540
+ match data. colors . get ( prev_index) {
541
+ Some ( DepNodeColor :: Green ( dep_node_index) ) => Some ( ( prev_index, dep_node_index) ) ,
542
+ Some ( DepNodeColor :: Red ) => None ,
540
543
None => {
541
- // This DepNode did not exist in the previous compilation session,
542
- // so we cannot mark it as green.
543
- debug ! ( "try_mark_green({:?}) - END - DepNode does not exist in \
544
- current compilation session anymore", dep_node) ;
545
- return None
544
+ self . try_mark_previous_green (
545
+ tcx. global_tcx ( ) ,
546
+ data,
547
+ prev_index,
548
+ & dep_node
549
+ ) . map ( |dep_node_index| {
550
+ ( prev_index, dep_node_index)
551
+ } )
546
552
}
547
- } ;
553
+ }
554
+ }
548
555
549
- debug_assert ! ( data. colors. borrow( ) . get( prev_dep_node_index) . is_none( ) ) ;
556
+ fn try_mark_previous_green < ' tcx > (
557
+ & self ,
558
+ tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
559
+ data : & DepGraphData ,
560
+ prev_dep_node_index : SerializedDepNodeIndex ,
561
+ dep_node : & DepNode
562
+ ) -> Option < DepNodeIndex > {
563
+ debug ! ( "try_mark_previous_green({:?}) - BEGIN" , dep_node) ;
564
+
565
+ #[ cfg( not( parallel_queries) ) ]
566
+ {
567
+ debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
568
+ debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ) ;
569
+ }
570
+
571
+ debug_assert ! ( !dep_node. kind. is_input( ) ) ;
572
+ debug_assert_eq ! ( data. previous. index_to_node( prev_dep_node_index) , * dep_node) ;
573
+
574
+ // We never try to mark inputs as green
575
+ // FIXME: Make an debug_assert!
576
+ assert ! ( !dep_node. kind. is_input( ) ) ;
577
+
578
+ let prev_deps = data. previous . edge_targets_from ( prev_dep_node_index) ;
550
579
551
580
let mut current_deps = SmallVec :: new ( ) ;
552
581
553
582
for & dep_dep_node_index in prev_deps {
554
- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
583
+ let dep_dep_node_color = data. colors . get ( dep_dep_node_index) ;
555
584
556
585
match dep_dep_node_color {
557
586
Some ( DepNodeColor :: Green ( node_index) ) => {
558
587
// This dependency has been marked as green before, we are
559
588
// still fine and can continue with checking the other
560
589
// dependencies.
561
- debug ! ( "try_mark_green ({:?}) --- found dependency {:?} to \
590
+ debug ! ( "try_mark_previous_green ({:?}) --- found dependency {:?} to \
562
591
be immediately green",
563
592
dep_node,
564
593
data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -569,7 +598,7 @@ impl DepGraph {
569
598
// compared to the previous compilation session. We cannot
570
599
// mark the DepNode as green and also don't need to bother
571
600
// with checking any of the other dependencies.
572
- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} was \
601
+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} was \
573
602
immediately red",
574
603
dep_node,
575
604
data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -581,12 +610,18 @@ impl DepGraph {
581
610
// We don't know the state of this dependency. If it isn't
582
611
// an input node, let's try to mark it green recursively.
583
612
if !dep_dep_node. kind . is_input ( ) {
584
- debug ! ( "try_mark_green ({:?}) --- state of dependency {:?} \
613
+ debug ! ( "try_mark_previous_green ({:?}) --- state of dependency {:?} \
585
614
is unknown, trying to mark it green", dep_node,
586
615
dep_dep_node) ;
587
616
588
- if let Some ( node_index) = self . try_mark_green ( tcx, dep_dep_node) {
589
- debug ! ( "try_mark_green({:?}) --- managed to MARK \
617
+ let node_index = self . try_mark_previous_green (
618
+ tcx,
619
+ data,
620
+ dep_dep_node_index,
621
+ dep_dep_node
622
+ ) ;
623
+ if let Some ( node_index) = node_index {
624
+ debug ! ( "try_mark_previous_green({:?}) --- managed to MARK \
590
625
dependency {:?} as green", dep_node, dep_dep_node) ;
591
626
current_deps. push ( node_index) ;
592
627
continue ;
@@ -616,28 +651,28 @@ impl DepGraph {
616
651
}
617
652
618
653
// We failed to mark it green, so we try to force the query.
619
- debug ! ( "try_mark_green ({:?}) --- trying to force \
654
+ debug ! ( "try_mark_previous_green ({:?}) --- trying to force \
620
655
dependency {:?}", dep_node, dep_dep_node) ;
621
656
if :: ty:: query:: force_from_dep_node ( tcx, dep_dep_node) {
622
- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
657
+ let dep_dep_node_color = data. colors . get ( dep_dep_node_index) ;
623
658
624
659
match dep_dep_node_color {
625
660
Some ( DepNodeColor :: Green ( node_index) ) => {
626
- debug ! ( "try_mark_green ({:?}) --- managed to \
661
+ debug ! ( "try_mark_previous_green ({:?}) --- managed to \
627
662
FORCE dependency {:?} to green",
628
663
dep_node, dep_dep_node) ;
629
664
current_deps. push ( node_index) ;
630
665
}
631
666
Some ( DepNodeColor :: Red ) => {
632
- debug ! ( "try_mark_green ({:?}) - END - \
667
+ debug ! ( "try_mark_previous_green ({:?}) - END - \
633
668
dependency {:?} was red after forcing",
634
669
dep_node,
635
670
dep_dep_node) ;
636
671
return None
637
672
}
638
673
None => {
639
674
if !tcx. sess . has_errors ( ) {
640
- bug ! ( "try_mark_green () - Forcing the DepNode \
675
+ bug ! ( "try_mark_previous_green () - Forcing the DepNode \
641
676
should have set its color")
642
677
} else {
643
678
// If the query we just forced has resulted
@@ -649,7 +684,7 @@ impl DepGraph {
649
684
}
650
685
} else {
651
686
// The DepNode could not be forced.
652
- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} \
687
+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} \
653
688
could not be forced", dep_node, dep_dep_node) ;
654
689
return None
655
690
}
@@ -701,16 +736,15 @@ impl DepGraph {
701
736
}
702
737
703
738
// ... and finally storing a "Green" entry in the color map.
704
- let mut colors = data. colors . borrow_mut ( ) ;
705
739
// Multiple threads can all write the same color here
706
740
#[ cfg( not( parallel_queries) ) ]
707
- debug_assert ! ( colors. get( prev_dep_node_index) . is_none( ) ,
708
- "DepGraph::try_mark_green () - Duplicate DepNodeColor \
741
+ debug_assert ! ( data . colors. get( prev_dep_node_index) . is_none( ) ,
742
+ "DepGraph::try_mark_previous_green () - Duplicate DepNodeColor \
709
743
insertion for {:?}", dep_node) ;
710
744
711
- colors. insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
745
+ data . colors . insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
712
746
713
- debug ! ( "try_mark_green ({:?}) - END - successfully marked as green" , dep_node) ;
747
+ debug ! ( "try_mark_previous_green ({:?}) - END - successfully marked as green" , dep_node) ;
714
748
Some ( dep_node_index)
715
749
}
716
750
@@ -731,9 +765,8 @@ impl DepGraph {
731
765
pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
732
766
let green_nodes: Vec < DepNode > = {
733
767
let data = self . data . as_ref ( ) . unwrap ( ) ;
734
- let colors = data. colors . borrow ( ) ;
735
- colors. values . indices ( ) . filter_map ( |prev_index| {
736
- match colors. get ( prev_index) {
768
+ data. colors . values . indices ( ) . filter_map ( |prev_index| {
769
+ match data. colors . get ( prev_index) {
737
770
Some ( DepNodeColor :: Green ( _) ) => {
738
771
let dep_node = data. previous . index_to_node ( prev_index) ;
739
772
if dep_node. cache_on_disk ( tcx) {
@@ -1083,7 +1116,7 @@ pub enum OpenTask {
1083
1116
// A data structure that stores Option<DepNodeColor> values as a contiguous
1084
1117
// array, using one u32 per entry.
1085
1118
struct DepNodeColorMap {
1086
- values : IndexVec < SerializedDepNodeIndex , u32 > ,
1119
+ values : IndexVec < SerializedDepNodeIndex , AtomicU32 > ,
1087
1120
}
1088
1121
1089
1122
const COMPRESSED_NONE : u32 = 0 ;
@@ -1093,12 +1126,12 @@ const COMPRESSED_FIRST_GREEN: u32 = 2;
1093
1126
impl DepNodeColorMap {
1094
1127
fn new ( size : usize ) -> DepNodeColorMap {
1095
1128
DepNodeColorMap {
1096
- values : IndexVec :: from_elem_n ( COMPRESSED_NONE , size )
1129
+ values : ( 0 ..size ) . map ( |_| AtomicU32 :: new ( COMPRESSED_NONE ) ) . collect ( ) ,
1097
1130
}
1098
1131
}
1099
1132
1100
1133
fn get ( & self , index : SerializedDepNodeIndex ) -> Option < DepNodeColor > {
1101
- match self . values [ index] {
1134
+ match self . values [ index] . load ( Ordering :: Acquire ) {
1102
1135
COMPRESSED_NONE => None ,
1103
1136
COMPRESSED_RED => Some ( DepNodeColor :: Red ) ,
1104
1137
value => Some ( DepNodeColor :: Green ( DepNodeIndex :: from_u32 (
@@ -1107,10 +1140,10 @@ impl DepNodeColorMap {
1107
1140
}
1108
1141
}
1109
1142
1110
- fn insert ( & mut self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1111
- self . values [ index] = match color {
1143
+ fn insert ( & self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1144
+ self . values [ index] . store ( match color {
1112
1145
DepNodeColor :: Red => COMPRESSED_RED ,
1113
1146
DepNodeColor :: Green ( index) => index. as_u32 ( ) + COMPRESSED_FIRST_GREEN ,
1114
- }
1147
+ } , Ordering :: Release )
1115
1148
}
1116
1149
}
0 commit comments