@@ -3,7 +3,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
33use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
44use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
55use smallvec:: SmallVec ;
6- use rustc_data_structures:: sync:: { Lrc , Lock } ;
6+ use rustc_data_structures:: sync:: { Lrc , Lock , AtomicU32 , Ordering } ;
77use std:: env;
88use std:: hash:: Hash ;
99use std:: collections:: hash_map:: Entry ;
@@ -58,7 +58,7 @@ struct DepGraphData {
5858 /// nodes and edges as well as all fingerprints of nodes that have them.
5959 previous : PreviousDepGraph ,
6060
61- colors : Lock < DepNodeColorMap > ,
61+ colors : DepNodeColorMap ,
6262
6363 /// When we load, there may be `.o` files, cached mir, or other such
6464 /// things available to us. If we find that they are not dirty, we
@@ -84,7 +84,7 @@ impl DepGraph {
8484 dep_node_debug : Default :: default ( ) ,
8585 current : Lock :: new ( CurrentDepGraph :: new ( prev_graph_node_count) ) ,
8686 previous : prev_graph,
87- colors : Lock :: new ( DepNodeColorMap :: new ( prev_graph_node_count) ) ,
87+ colors : DepNodeColorMap :: new ( prev_graph_node_count) ,
8888 loaded_from_cache : Default :: default ( ) ,
8989 } ) ) ,
9090 }
@@ -282,12 +282,11 @@ impl DepGraph {
282282 DepNodeColor :: Red
283283 } ;
284284
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( ) ,
287286 "DepGraph::with_task() - Duplicate DepNodeColor \
288287 insertion for {:?}", key) ;
289288
290- colors. insert ( prev_index, color) ;
289+ data . colors . insert ( prev_index, color) ;
291290 }
292291
293292 ( result, dep_node_index)
@@ -502,7 +501,7 @@ impl DepGraph {
502501 pub fn node_color ( & self , dep_node : & DepNode ) -> Option < DepNodeColor > {
503502 if let Some ( ref data) = self . data {
504503 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)
506505 } else {
507506 // This is a node that did not exist in the previous compilation
508507 // session, so we consider it to be red.
@@ -513,56 +512,89 @@ impl DepGraph {
513512 None
514513 }
515514
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+ }
522530
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 ) ? ;
535543
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 => {
538548 // This DepNode and the corresponding query invocation existed
539549 // in the previous compilation session too, so we can try to
540550 // mark it as green by recursively marking all of its
541551 // 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+ } )
550560 }
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) ;
552573
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) ;
554586
555587 let mut current_deps = SmallVec :: new ( ) ;
556588
557589 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) ;
559591
560592 match dep_dep_node_color {
561593 Some ( DepNodeColor :: Green ( node_index) ) => {
562594 // This dependency has been marked as green before, we are
563595 // still fine and can continue with checking the other
564596 // dependencies.
565- debug ! ( "try_mark_green ({:?}) --- found dependency {:?} to \
597+ debug ! ( "try_mark_previous_green ({:?}) --- found dependency {:?} to \
566598 be immediately green",
567599 dep_node,
568600 data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -573,7 +605,7 @@ impl DepGraph {
573605 // compared to the previous compilation session. We cannot
574606 // mark the DepNode as green and also don't need to bother
575607 // with checking any of the other dependencies.
576- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} was \
608+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} was \
577609 immediately red",
578610 dep_node,
579611 data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -585,12 +617,18 @@ impl DepGraph {
585617 // We don't know the state of this dependency. If it isn't
586618 // an input node, let's try to mark it green recursively.
587619 if !dep_dep_node. kind . is_input ( ) {
588- debug ! ( "try_mark_green ({:?}) --- state of dependency {:?} \
620+ debug ! ( "try_mark_previous_green ({:?}) --- state of dependency {:?} \
589621 is unknown, trying to mark it green", dep_node,
590622 dep_dep_node) ;
591623
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 \
594632 dependency {:?} as green", dep_node, dep_dep_node) ;
595633 current_deps. push ( node_index) ;
596634 continue ;
@@ -620,28 +658,28 @@ impl DepGraph {
620658 }
621659
622660 // 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 \
624662 dependency {:?}", dep_node, dep_dep_node) ;
625663 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) ;
627665
628666 match dep_dep_node_color {
629667 Some ( DepNodeColor :: Green ( node_index) ) => {
630- debug ! ( "try_mark_green ({:?}) --- managed to \
668+ debug ! ( "try_mark_previous_green ({:?}) --- managed to \
631669 FORCE dependency {:?} to green",
632670 dep_node, dep_dep_node) ;
633671 current_deps. push ( node_index) ;
634672 }
635673 Some ( DepNodeColor :: Red ) => {
636- debug ! ( "try_mark_green ({:?}) - END - \
674+ debug ! ( "try_mark_previous_green ({:?}) - END - \
637675 dependency {:?} was red after forcing",
638676 dep_node,
639677 dep_dep_node) ;
640678 return None
641679 }
642680 None => {
643681 if !tcx. sess . has_errors ( ) {
644- bug ! ( "try_mark_green () - Forcing the DepNode \
682+ bug ! ( "try_mark_previous_green () - Forcing the DepNode \
645683 should have set its color")
646684 } else {
647685 // If the query we just forced has resulted
@@ -653,7 +691,7 @@ impl DepGraph {
653691 }
654692 } else {
655693 // The DepNode could not be forced.
656- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} \
694+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} \
657695 could not be forced", dep_node, dep_dep_node) ;
658696 return None
659697 }
@@ -705,16 +743,15 @@ impl DepGraph {
705743 }
706744
707745 // ... and finally storing a "Green" entry in the color map.
708- let mut colors = data. colors . borrow_mut ( ) ;
709746 // Multiple threads can all write the same color here
710747 #[ 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 \
713750 insertion for {:?}", dep_node) ;
714751
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) ) ;
716753
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) ;
718755 Some ( dep_node_index)
719756 }
720757
@@ -735,9 +772,8 @@ impl DepGraph {
735772 pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
736773 let green_nodes: Vec < DepNode > = {
737774 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) {
741777 Some ( DepNodeColor :: Green ( _) ) => {
742778 let dep_node = data. previous . index_to_node ( prev_index) ;
743779 if dep_node. cache_on_disk ( tcx) {
@@ -1035,7 +1071,7 @@ pub struct TaskDeps {
10351071// A data structure that stores Option<DepNodeColor> values as a contiguous
10361072// array, using one u32 per entry.
10371073struct DepNodeColorMap {
1038- values : IndexVec < SerializedDepNodeIndex , u32 > ,
1074+ values : IndexVec < SerializedDepNodeIndex , AtomicU32 > ,
10391075}
10401076
10411077const COMPRESSED_NONE : u32 = 0 ;
@@ -1045,12 +1081,12 @@ const COMPRESSED_FIRST_GREEN: u32 = 2;
10451081impl DepNodeColorMap {
10461082 fn new ( size : usize ) -> DepNodeColorMap {
10471083 DepNodeColorMap {
1048- values : IndexVec :: from_elem_n ( COMPRESSED_NONE , size )
1084+ values : ( 0 ..size ) . map ( |_| AtomicU32 :: new ( COMPRESSED_NONE ) ) . collect ( ) ,
10491085 }
10501086 }
10511087
10521088 fn get ( & self , index : SerializedDepNodeIndex ) -> Option < DepNodeColor > {
1053- match self . values [ index] {
1089+ match self . values [ index] . load ( Ordering :: Acquire ) {
10541090 COMPRESSED_NONE => None ,
10551091 COMPRESSED_RED => Some ( DepNodeColor :: Red ) ,
10561092 value => Some ( DepNodeColor :: Green ( DepNodeIndex :: from_u32 (
@@ -1059,10 +1095,10 @@ impl DepNodeColorMap {
10591095 }
10601096 }
10611097
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 {
10641100 DepNodeColor :: Red => COMPRESSED_RED ,
10651101 DepNodeColor :: Green ( index) => index. as_u32 ( ) + COMPRESSED_FIRST_GREEN ,
1066- }
1102+ } , Ordering :: Release )
10671103 }
10681104}
0 commit comments