@@ -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,86 @@ 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( ) ) ;
535
537
536
- let ( prev_deps, prev_dep_node_index) = match data. previous . edges_from ( dep_node) {
537
- Some ( prev) => {
538
- // This DepNode and the corresponding query invocation existed
539
- // in the previous compilation session too, so we can try to
540
- // mark it as green by recursively marking all of its
541
- // dependencies green.
542
- prev
543
- }
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) ?;
543
+
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 ,
544
547
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
548
+ self . try_mark_previous_green (
549
+ tcx. global_tcx ( ) ,
550
+ data,
551
+ prev_index,
552
+ & dep_node
553
+ ) . map ( |dep_node_index| {
554
+ ( prev_index, dep_node_index)
555
+ } )
550
556
}
551
- } ;
557
+ }
558
+ }
552
559
553
- debug_assert ! ( data. colors. borrow( ) . get( prev_dep_node_index) . is_none( ) ) ;
560
+ fn try_mark_previous_green < ' tcx > (
561
+ & self ,
562
+ tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
563
+ data : & DepGraphData ,
564
+ prev_dep_node_index : SerializedDepNodeIndex ,
565
+ dep_node : & DepNode
566
+ ) -> Option < DepNodeIndex > {
567
+ debug ! ( "try_mark_previous_green({:?}) - BEGIN" , dep_node) ;
568
+
569
+ #[ cfg( not( parallel_queries) ) ]
570
+ {
571
+ debug_assert ! ( !data. current. borrow( ) . node_to_node_index. contains_key( dep_node) ) ;
572
+ debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ) ;
573
+ }
574
+
575
+ debug_assert ! ( !dep_node. kind. is_input( ) ) ;
576
+ debug_assert_eq ! ( data. previous. index_to_node( prev_dep_node_index) , * dep_node) ;
577
+
578
+ // We never try to mark inputs as green
579
+ // FIXME: Make an debug_assert!
580
+ assert ! ( !dep_node. kind. is_input( ) ) ;
581
+
582
+ let prev_deps = data. previous . edge_targets_from ( prev_dep_node_index) ;
554
583
555
584
let mut current_deps = SmallVec :: new ( ) ;
556
585
557
586
for & dep_dep_node_index in prev_deps {
558
- let dep_dep_node_color = data. colors . borrow ( ) . get ( dep_dep_node_index) ;
587
+ let dep_dep_node_color = data. colors . get ( dep_dep_node_index) ;
559
588
560
589
match dep_dep_node_color {
561
590
Some ( DepNodeColor :: Green ( node_index) ) => {
562
591
// This dependency has been marked as green before, we are
563
592
// still fine and can continue with checking the other
564
593
// dependencies.
565
- debug ! ( "try_mark_green ({:?}) --- found dependency {:?} to \
594
+ debug ! ( "try_mark_previous_green ({:?}) --- found dependency {:?} to \
566
595
be immediately green",
567
596
dep_node,
568
597
data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -573,7 +602,7 @@ impl DepGraph {
573
602
// compared to the previous compilation session. We cannot
574
603
// mark the DepNode as green and also don't need to bother
575
604
// with checking any of the other dependencies.
576
- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} was \
605
+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} was \
577
606
immediately red",
578
607
dep_node,
579
608
data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -585,12 +614,18 @@ impl DepGraph {
585
614
// We don't know the state of this dependency. If it isn't
586
615
// an input node, let's try to mark it green recursively.
587
616
if !dep_dep_node. kind . is_input ( ) {
588
- debug ! ( "try_mark_green ({:?}) --- state of dependency {:?} \
617
+ debug ! ( "try_mark_previous_green ({:?}) --- state of dependency {:?} \
589
618
is unknown, trying to mark it green", dep_node,
590
619
dep_dep_node) ;
591
620
592
- if let Some ( node_index) = self . try_mark_green ( tcx, dep_dep_node) {
593
- debug ! ( "try_mark_green({:?}) --- managed to MARK \
621
+ let node_index = self . try_mark_previous_green (
622
+ tcx,
623
+ data,
624
+ dep_dep_node_index,
625
+ dep_dep_node
626
+ ) ;
627
+ if let Some ( node_index) = node_index {
628
+ debug ! ( "try_mark_previous_green({:?}) --- managed to MARK \
594
629
dependency {:?} as green", dep_node, dep_dep_node) ;
595
630
current_deps. push ( node_index) ;
596
631
continue ;
@@ -620,28 +655,28 @@ impl DepGraph {
620
655
}
621
656
622
657
// We failed to mark it green, so we try to force the query.
623
- debug ! ( "try_mark_green ({:?}) --- trying to force \
658
+ debug ! ( "try_mark_previous_green ({:?}) --- trying to force \
624
659
dependency {:?}", dep_node, dep_dep_node) ;
625
660
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) ;
661
+ let dep_dep_node_color = data. colors . get ( dep_dep_node_index) ;
627
662
628
663
match dep_dep_node_color {
629
664
Some ( DepNodeColor :: Green ( node_index) ) => {
630
- debug ! ( "try_mark_green ({:?}) --- managed to \
665
+ debug ! ( "try_mark_previous_green ({:?}) --- managed to \
631
666
FORCE dependency {:?} to green",
632
667
dep_node, dep_dep_node) ;
633
668
current_deps. push ( node_index) ;
634
669
}
635
670
Some ( DepNodeColor :: Red ) => {
636
- debug ! ( "try_mark_green ({:?}) - END - \
671
+ debug ! ( "try_mark_previous_green ({:?}) - END - \
637
672
dependency {:?} was red after forcing",
638
673
dep_node,
639
674
dep_dep_node) ;
640
675
return None
641
676
}
642
677
None => {
643
678
if !tcx. sess . has_errors ( ) {
644
- bug ! ( "try_mark_green () - Forcing the DepNode \
679
+ bug ! ( "try_mark_previous_green () - Forcing the DepNode \
645
680
should have set its color")
646
681
} else {
647
682
// If the query we just forced has resulted
@@ -653,7 +688,7 @@ impl DepGraph {
653
688
}
654
689
} else {
655
690
// The DepNode could not be forced.
656
- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} \
691
+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} \
657
692
could not be forced", dep_node, dep_dep_node) ;
658
693
return None
659
694
}
@@ -705,16 +740,15 @@ impl DepGraph {
705
740
}
706
741
707
742
// ... and finally storing a "Green" entry in the color map.
708
- let mut colors = data. colors . borrow_mut ( ) ;
709
743
// Multiple threads can all write the same color here
710
744
#[ cfg( not( parallel_queries) ) ]
711
- debug_assert ! ( colors. get( prev_dep_node_index) . is_none( ) ,
712
- "DepGraph::try_mark_green () - Duplicate DepNodeColor \
745
+ debug_assert ! ( data . colors. get( prev_dep_node_index) . is_none( ) ,
746
+ "DepGraph::try_mark_previous_green () - Duplicate DepNodeColor \
713
747
insertion for {:?}", dep_node) ;
714
748
715
- colors. insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
749
+ data . colors . insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
716
750
717
- debug ! ( "try_mark_green ({:?}) - END - successfully marked as green" , dep_node) ;
751
+ debug ! ( "try_mark_previous_green ({:?}) - END - successfully marked as green" , dep_node) ;
718
752
Some ( dep_node_index)
719
753
}
720
754
@@ -735,9 +769,8 @@ impl DepGraph {
735
769
pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
736
770
let green_nodes: Vec < DepNode > = {
737
771
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) {
772
+ data. colors . values . indices ( ) . filter_map ( |prev_index| {
773
+ match data. colors . get ( prev_index) {
741
774
Some ( DepNodeColor :: Green ( _) ) => {
742
775
let dep_node = data. previous . index_to_node ( prev_index) ;
743
776
if dep_node. cache_on_disk ( tcx) {
@@ -1035,7 +1068,7 @@ pub struct TaskDeps {
1035
1068
// A data structure that stores Option<DepNodeColor> values as a contiguous
1036
1069
// array, using one u32 per entry.
1037
1070
struct DepNodeColorMap {
1038
- values : IndexVec < SerializedDepNodeIndex , u32 > ,
1071
+ values : IndexVec < SerializedDepNodeIndex , AtomicU32 > ,
1039
1072
}
1040
1073
1041
1074
const COMPRESSED_NONE : u32 = 0 ;
@@ -1045,12 +1078,12 @@ const COMPRESSED_FIRST_GREEN: u32 = 2;
1045
1078
impl DepNodeColorMap {
1046
1079
fn new ( size : usize ) -> DepNodeColorMap {
1047
1080
DepNodeColorMap {
1048
- values : IndexVec :: from_elem_n ( COMPRESSED_NONE , size )
1081
+ values : ( 0 ..size ) . map ( |_| AtomicU32 :: new ( COMPRESSED_NONE ) ) . collect ( ) ,
1049
1082
}
1050
1083
}
1051
1084
1052
1085
fn get ( & self , index : SerializedDepNodeIndex ) -> Option < DepNodeColor > {
1053
- match self . values [ index] {
1086
+ match self . values [ index] . load ( Ordering :: Acquire ) {
1054
1087
COMPRESSED_NONE => None ,
1055
1088
COMPRESSED_RED => Some ( DepNodeColor :: Red ) ,
1056
1089
value => Some ( DepNodeColor :: Green ( DepNodeIndex :: from_u32 (
@@ -1059,10 +1092,10 @@ impl DepNodeColorMap {
1059
1092
}
1060
1093
}
1061
1094
1062
- fn insert ( & mut self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1063
- self . values [ index] = match color {
1095
+ fn insert ( & self , index : SerializedDepNodeIndex , color : DepNodeColor ) {
1096
+ self . values [ index] . store ( match color {
1064
1097
DepNodeColor :: Red => COMPRESSED_RED ,
1065
1098
DepNodeColor :: Green ( index) => index. as_u32 ( ) + COMPRESSED_FIRST_GREEN ,
1066
- }
1099
+ } , Ordering :: Release )
1067
1100
}
1068
1101
}
0 commit comments