@@ -3,7 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
3
3
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4
4
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
5
5
use smallvec:: SmallVec ;
6
- use rustc_data_structures:: sync:: { Lrc , Lock } ;
6
+ use rustc_data_structures:: sync:: { Lrc , Lock , AtomicU32 , Ordering } ;
7
7
use std:: env;
8
8
use std:: hash:: Hash ;
9
9
use std:: collections:: hash_map:: Entry ;
@@ -58,7 +58,7 @@ struct DepGraphData {
58
58
/// nodes and edges as well as all fingerprints of nodes that have them.
59
59
previous : PreviousDepGraph ,
60
60
61
- colors : Lock < DepNodeColorMap > ,
61
+ colors : DepNodeColorMap ,
62
62
63
63
/// When we load, there may be `.o` files, cached mir, or other such
64
64
/// things available to us. If we find that they are not dirty, we
@@ -84,7 +84,7 @@ impl DepGraph {
84
84
dep_node_debug : Default :: default ( ) ,
85
85
current : Lock :: new ( CurrentDepGraph :: new ( prev_graph_node_count) ) ,
86
86
previous : prev_graph,
87
- colors : Lock :: new ( DepNodeColorMap :: new ( prev_graph_node_count) ) ,
87
+ colors : DepNodeColorMap :: new ( prev_graph_node_count) ,
88
88
loaded_from_cache : Default :: default ( ) ,
89
89
} ) ) ,
90
90
}
@@ -282,12 +282,11 @@ impl DepGraph {
282
282
DepNodeColor :: Red
283
283
} ;
284
284
285
- let mut colors = data. colors . borrow_mut ( ) ;
286
- debug_assert ! ( colors. get( prev_index) . is_none( ) ,
285
+ debug_assert ! ( data. colors. get( prev_index) . is_none( ) ,
287
286
"DepGraph::with_task() - Duplicate DepNodeColor \
288
287
insertion for {:?}", key) ;
289
288
290
- colors. insert ( prev_index, color) ;
289
+ data . colors . insert ( prev_index, color) ;
291
290
}
292
291
293
292
( result, dep_node_index)
@@ -502,7 +501,7 @@ impl DepGraph {
502
501
pub fn node_color ( & self , dep_node : & DepNode ) -> Option < DepNodeColor > {
503
502
if let Some ( ref data) = self . data {
504
503
if let Some ( prev_index) = data. previous . node_to_index_opt ( dep_node) {
505
- return data. colors . borrow ( ) . get ( prev_index)
504
+ return data. colors . get ( prev_index)
506
505
} else {
507
506
// This is a node that did not exist in the previous compilation
508
507
// session, so we consider it to be red.
@@ -513,56 +512,89 @@ impl DepGraph {
513
512
None
514
513
}
515
514
516
- pub fn try_mark_green < ' tcx > ( & self ,
517
- tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
518
- dep_node : & DepNode )
519
- -> Option < DepNodeIndex > {
520
- debug ! ( "try_mark_green({:?}) - BEGIN" , dep_node) ;
521
- let data = self . data . as_ref ( ) . unwrap ( ) ;
515
+ /// Try to read a node index for the node dep_node.
516
+ /// A node will have an index, when it's already been marked green, or when we can mark it
517
+ /// green. This function will mark the current task as a reader of the specified node, when
518
+ /// a node index can be found for that node.
519
+ pub fn try_mark_green_and_read (
520
+ & self ,
521
+ tcx : TyCtxt < ' _ , ' _ , ' _ > ,
522
+ dep_node : & DepNode
523
+ ) -> Option < ( SerializedDepNodeIndex , DepNodeIndex ) > {
524
+ self . try_mark_green ( tcx, dep_node) . map ( |( prev_index, dep_node_index) | {
525
+ debug_assert ! ( self . is_green( & dep_node) ) ;
526
+ self . read_index ( dep_node_index) ;
527
+ ( prev_index, dep_node_index)
528
+ } )
529
+ }
522
530
523
- # [ cfg ( not ( parallel_queries ) ) ]
524
- debug_assert ! ( !data . current . borrow ( ) . node_to_node_index . contains_key ( dep_node ) ) ;
525
-
526
- if dep_node. kind . is_input ( ) {
527
- // We should only hit try_mark_green() for inputs that do not exist
528
- // anymore in the current compilation session. Existing inputs are
529
- // eagerly marked as either red/green before any queries are
530
- // executed.
531
- debug_assert ! ( dep_node . extract_def_id ( tcx ) . is_none ( ) ) ;
532
- debug ! ( "try_mark_green({:?}) - END - DepNode is deleted input" , dep_node ) ;
533
- return None ;
534
- }
531
+ pub fn try_mark_green (
532
+ & self ,
533
+ tcx : TyCtxt < ' _ , ' _ , ' _ > ,
534
+ dep_node : & DepNode
535
+ ) -> Option < ( SerializedDepNodeIndex , DepNodeIndex ) > {
536
+ debug_assert ! ( !dep_node . kind . is_input ( ) ) ;
537
+
538
+ // Return None if the dep graph is disabled
539
+ let data = self . data . as_ref ( ) ? ;
540
+
541
+ // Return None if the dep node didn't exist in the previous session
542
+ let prev_index = data . previous . node_to_index_opt ( dep_node ) ? ;
535
543
536
- let ( prev_deps, prev_dep_node_index) = match data. previous . edges_from ( dep_node) {
537
- Some ( prev) => {
544
+ match data. colors . get ( prev_index) {
545
+ Some ( DepNodeColor :: Green ( dep_node_index) ) => Some ( ( prev_index, dep_node_index) ) ,
546
+ Some ( DepNodeColor :: Red ) => None ,
547
+ None => {
538
548
// This DepNode and the corresponding query invocation existed
539
549
// in the previous compilation session too, so we can try to
540
550
// mark it as green by recursively marking all of its
541
551
// dependencies green.
542
- prev
543
- }
544
- None => {
545
- // This DepNode did not exist in the previous compilation session ,
546
- // so we cannot mark it as green.
547
- debug ! ( "try_mark_green({:?}) - END - DepNode does not exist in \
548
- current compilation session anymore" , dep_node ) ;
549
- return None
552
+ self . try_mark_previous_green (
553
+ tcx . global_tcx ( ) ,
554
+ data ,
555
+ prev_index ,
556
+ & dep_node
557
+ ) . map ( |dep_node_index| {
558
+ ( prev_index , dep_node_index )
559
+ } )
550
560
}
551
- } ;
561
+ }
562
+ }
563
+
564
+ /// Try to mark a dep-node which existed in the previous compilation session as green
565
+ fn try_mark_previous_green < ' tcx > (
566
+ & self ,
567
+ tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
568
+ data : & DepGraphData ,
569
+ prev_dep_node_index : SerializedDepNodeIndex ,
570
+ dep_node : & DepNode
571
+ ) -> Option < DepNodeIndex > {
572
+ debug ! ( "try_mark_previous_green({:?}) - BEGIN" , dep_node) ;
552
573
553
- debug_assert ! ( data. colors. borrow( ) . get( prev_dep_node_index) . is_none( ) ) ;
574
+ #[ cfg( not( parallel_queries) ) ]
575
+ {
576
+ debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
577
+ debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ) ;
578
+ }
579
+
580
+ // We never try to mark inputs as green
581
+ debug_assert ! ( !dep_node. kind. is_input( ) ) ;
582
+
583
+ debug_assert_eq ! ( data. previous. index_to_node( prev_dep_node_index) , * dep_node) ;
584
+
585
+ let prev_deps = data. previous . edge_targets_from ( prev_dep_node_index) ;
554
586
555
587
let mut current_deps = SmallVec :: new ( ) ;
556
588
557
589
for & dep_dep_node_index in prev_deps {
558
- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
590
+ let dep_dep_node_color = data. colors . get ( dep_dep_node_index) ;
559
591
560
592
match dep_dep_node_color {
561
593
Some ( DepNodeColor :: Green ( node_index) ) => {
562
594
// This dependency has been marked as green before, we are
563
595
// still fine and can continue with checking the other
564
596
// dependencies.
565
- debug ! ( "try_mark_green ({:?}) --- found dependency {:?} to \
597
+ debug ! ( "try_mark_previous_green ({:?}) --- found dependency {:?} to \
566
598
be immediately green",
567
599
dep_node,
568
600
data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -573,7 +605,7 @@ impl DepGraph {
573
605
// compared to the previous compilation session. We cannot
574
606
// mark the DepNode as green and also don't need to bother
575
607
// with checking any of the other dependencies.
576
- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} was \
608
+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} was \
577
609
immediately red",
578
610
dep_node,
579
611
data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -585,12 +617,18 @@ impl DepGraph {
585
617
// We don't know the state of this dependency. If it isn't
586
618
// an input node, let's try to mark it green recursively.
587
619
if !dep_dep_node. kind . is_input ( ) {
588
- debug ! ( "try_mark_green ({:?}) --- state of dependency {:?} \
620
+ debug ! ( "try_mark_previous_green ({:?}) --- state of dependency {:?} \
589
621
is unknown, trying to mark it green", dep_node,
590
622
dep_dep_node) ;
591
623
592
- if let Some ( node_index) = self . try_mark_green ( tcx, dep_dep_node) {
593
- debug ! ( "try_mark_green({:?}) --- managed to MARK \
624
+ let node_index = self . try_mark_previous_green (
625
+ tcx,
626
+ data,
627
+ dep_dep_node_index,
628
+ dep_dep_node
629
+ ) ;
630
+ if let Some ( node_index) = node_index {
631
+ debug ! ( "try_mark_previous_green({:?}) --- managed to MARK \
594
632
dependency {:?} as green", dep_node, dep_dep_node) ;
595
633
current_deps. push ( node_index) ;
596
634
continue ;
@@ -620,28 +658,28 @@ impl DepGraph {
620
658
}
621
659
622
660
// We failed to mark it green, so we try to force the query.
623
- debug ! ( "try_mark_green ({:?}) --- trying to force \
661
+ debug ! ( "try_mark_previous_green ({:?}) --- trying to force \
624
662
dependency {:?}", dep_node, dep_dep_node) ;
625
663
if :: ty:: query:: force_from_dep_node ( tcx, dep_dep_node) {
626
- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
664
+ let dep_dep_node_color = data. colors . get ( dep_dep_node_index) ;
627
665
628
666
match dep_dep_node_color {
629
667
Some ( DepNodeColor :: Green ( node_index) ) => {
630
- debug ! ( "try_mark_green ({:?}) --- managed to \
668
+ debug ! ( "try_mark_previous_green ({:?}) --- managed to \
631
669
FORCE dependency {:?} to green",
632
670
dep_node, dep_dep_node) ;
633
671
current_deps. push ( node_index) ;
634
672
}
635
673
Some ( DepNodeColor :: Red ) => {
636
- debug ! ( "try_mark_green ({:?}) - END - \
674
+ debug ! ( "try_mark_previous_green ({:?}) - END - \
637
675
dependency {:?} was red after forcing",
638
676
dep_node,
639
677
dep_dep_node) ;
640
678
return None
641
679
}
642
680
None => {
643
681
if !tcx. sess . has_errors ( ) {
644
- bug ! ( "try_mark_green () - Forcing the DepNode \
682
+ bug ! ( "try_mark_previous_green () - Forcing the DepNode \
645
683
should have set its color")
646
684
} else {
647
685
// If the query we just forced has resulted
@@ -653,7 +691,7 @@ impl DepGraph {
653
691
}
654
692
} else {
655
693
// The DepNode could not be forced.
656
- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} \
694
+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} \
657
695
could not be forced", dep_node, dep_dep_node) ;
658
696
return None
659
697
}
@@ -705,16 +743,15 @@ impl DepGraph {
705
743
}
706
744
707
745
// ... and finally storing a "Green" entry in the color map.
708
- let mut colors = data. colors . borrow_mut ( ) ;
709
746
// Multiple threads can all write the same color here
710
747
#[ cfg( not( parallel_queries) ) ]
711
- debug_assert ! ( colors. get( prev_dep_node_index) . is_none( ) ,
712
- "DepGraph::try_mark_green () - Duplicate DepNodeColor \
748
+ debug_assert ! ( data . colors. get( prev_dep_node_index) . is_none( ) ,
749
+ "DepGraph::try_mark_previous_green () - Duplicate DepNodeColor \
713
750
insertion for {:?}", dep_node) ;
714
751
715
- colors. insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
752
+ data . colors . insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
716
753
717
- debug ! ( "try_mark_green ({:?}) - END - successfully marked as green" , dep_node) ;
754
+ debug ! ( "try_mark_previous_green ({:?}) - END - successfully marked as green" , dep_node) ;
718
755
Some ( dep_node_index)
719
756
}
720
757
@@ -735,9 +772,8 @@ impl DepGraph {
735
772
pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
736
773
let green_nodes: Vec < DepNode > = {
737
774
let data = self . data . as_ref ( ) . unwrap ( ) ;
738
- let colors = data. colors . borrow ( ) ;
739
- colors. values . indices ( ) . filter_map ( |prev_index| {
740
- match colors. get ( prev_index) {
775
+ data. colors . values . indices ( ) . filter_map ( |prev_index| {
776
+ match data. colors . get ( prev_index) {
741
777
Some ( DepNodeColor :: Green ( _) ) => {
742
778
let dep_node = data. previous . index_to_node ( prev_index) ;
743
779
if dep_node. cache_on_disk ( tcx) {
@@ -1035,7 +1071,7 @@ pub struct TaskDeps {
1035
1071
// A data structure that stores Option<DepNodeColor> values as a contiguous
1036
1072
// array, using one u32 per entry.
1037
1073
struct DepNodeColorMap {
1038
- values : IndexVec < SerializedDepNodeIndex , u32 > ,
1074
+ values : IndexVec < SerializedDepNodeIndex , AtomicU32 > ,
1039
1075
}
1040
1076
1041
1077
const COMPRESSED_NONE : u32 = 0 ;
@@ -1045,12 +1081,12 @@ const COMPRESSED_FIRST_GREEN: u32 = 2;
1045
1081
impl DepNodeColorMap {
1046
1082
fn new ( size : usize ) -> DepNodeColorMap {
1047
1083
DepNodeColorMap {
1048
- values : IndexVec :: from_elem_n ( COMPRESSED_NONE , size )
1084
+ values : ( 0 ..size ) . map ( |_| AtomicU32 :: new ( COMPRESSED_NONE ) ) . collect ( ) ,
1049
1085
}
1050
1086
}
1051
1087
1052
1088
fn get ( & self , index : SerializedDepNodeIndex ) -> Option < DepNodeColor > {
1053
- match self . values [ index] {
1089
+ match self . values [ index] . load ( Ordering :: Acquire ) {
1054
1090
COMPRESSED_NONE => None ,
1055
1091
COMPRESSED_RED => Some ( DepNodeColor :: Red ) ,
1056
1092
value => Some ( DepNodeColor :: Green ( DepNodeIndex :: from_u32 (
@@ -1059,10 +1095,10 @@ impl DepNodeColorMap {
1059
1095
}
1060
1096
}
1061
1097
1062
- fn insert ( & mut self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1063
- self . values [ index] = match color {
1098
+ fn insert ( & self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1099
+ self . values [ index] . store ( match color {
1064
1100
DepNodeColor :: Red => COMPRESSED_RED ,
1065
1101
DepNodeColor :: Green ( index) => index. as_u32 ( ) + COMPRESSED_FIRST_GREEN ,
1066
- }
1102
+ } , Ordering :: Release )
1067
1103
}
1068
1104
}
0 commit comments