@@ -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,86 @@ 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( ) ) ;
535537
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 ,
544547 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+ } )
550556 }
551- } ;
557+ }
558+ }
552559
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) ;
554583
555584 let mut current_deps = SmallVec :: new ( ) ;
556585
557586 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) ;
559588
560589 match dep_dep_node_color {
561590 Some ( DepNodeColor :: Green ( node_index) ) => {
562591 // This dependency has been marked as green before, we are
563592 // still fine and can continue with checking the other
564593 // dependencies.
565- debug ! ( "try_mark_green ({:?}) --- found dependency {:?} to \
594+ debug ! ( "try_mark_previous_green ({:?}) --- found dependency {:?} to \
566595 be immediately green",
567596 dep_node,
568597 data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -573,7 +602,7 @@ impl DepGraph {
573602 // compared to the previous compilation session. We cannot
574603 // mark the DepNode as green and also don't need to bother
575604 // with checking any of the other dependencies.
576- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} was \
605+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} was \
577606 immediately red",
578607 dep_node,
579608 data. previous. index_to_node( dep_dep_node_index) ) ;
@@ -585,12 +614,18 @@ impl DepGraph {
585614 // We don't know the state of this dependency. If it isn't
586615 // an input node, let's try to mark it green recursively.
587616 if !dep_dep_node. kind . is_input ( ) {
588- debug ! ( "try_mark_green ({:?}) --- state of dependency {:?} \
617+ debug ! ( "try_mark_previous_green ({:?}) --- state of dependency {:?} \
589618 is unknown, trying to mark it green", dep_node,
590619 dep_dep_node) ;
591620
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 \
594629 dependency {:?} as green", dep_node, dep_dep_node) ;
595630 current_deps. push ( node_index) ;
596631 continue ;
@@ -620,28 +655,28 @@ impl DepGraph {
620655 }
621656
622657 // 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 \
624659 dependency {:?}", dep_node, dep_dep_node) ;
625660 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) ;
627662
628663 match dep_dep_node_color {
629664 Some ( DepNodeColor :: Green ( node_index) ) => {
630- debug ! ( "try_mark_green ({:?}) --- managed to \
665+ debug ! ( "try_mark_previous_green ({:?}) --- managed to \
631666 FORCE dependency {:?} to green",
632667 dep_node, dep_dep_node) ;
633668 current_deps. push ( node_index) ;
634669 }
635670 Some ( DepNodeColor :: Red ) => {
636- debug ! ( "try_mark_green ({:?}) - END - \
671+ debug ! ( "try_mark_previous_green ({:?}) - END - \
637672 dependency {:?} was red after forcing",
638673 dep_node,
639674 dep_dep_node) ;
640675 return None
641676 }
642677 None => {
643678 if !tcx. sess . has_errors ( ) {
644- bug ! ( "try_mark_green () - Forcing the DepNode \
679+ bug ! ( "try_mark_previous_green () - Forcing the DepNode \
645680 should have set its color")
646681 } else {
647682 // If the query we just forced has resulted
@@ -653,7 +688,7 @@ impl DepGraph {
653688 }
654689 } else {
655690 // The DepNode could not be forced.
656- debug ! ( "try_mark_green ({:?}) - END - dependency {:?} \
691+ debug ! ( "try_mark_previous_green ({:?}) - END - dependency {:?} \
657692 could not be forced", dep_node, dep_dep_node) ;
658693 return None
659694 }
@@ -705,16 +740,15 @@ impl DepGraph {
705740 }
706741
707742 // ... and finally storing a "Green" entry in the color map.
708- let mut colors = data. colors . borrow_mut ( ) ;
709743 // Multiple threads can all write the same color here
710744 #[ 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 \
713747 insertion for {:?}", dep_node) ;
714748
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) ) ;
716750
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) ;
718752 Some ( dep_node_index)
719753 }
720754
@@ -735,9 +769,8 @@ impl DepGraph {
735769 pub fn exec_cache_promotions < ' a , ' tcx > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
736770 let green_nodes: Vec < DepNode > = {
737771 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) {
741774 Some ( DepNodeColor :: Green ( _) ) => {
742775 let dep_node = data. previous . index_to_node ( prev_index) ;
743776 if dep_node. cache_on_disk ( tcx) {
@@ -1035,7 +1068,7 @@ pub struct TaskDeps {
10351068// A data structure that stores Option<DepNodeColor> values as a contiguous
10361069// array, using one u32 per entry.
10371070struct DepNodeColorMap {
1038- values : IndexVec < SerializedDepNodeIndex , u32 > ,
1071+ values : IndexVec < SerializedDepNodeIndex , AtomicU32 > ,
10391072}
10401073
10411074const COMPRESSED_NONE : u32 = 0 ;
@@ -1045,12 +1078,12 @@ const COMPRESSED_FIRST_GREEN: u32 = 2;
10451078impl DepNodeColorMap {
10461079 fn new ( size : usize ) -> DepNodeColorMap {
10471080 DepNodeColorMap {
1048- values : IndexVec :: from_elem_n ( COMPRESSED_NONE , size )
1081+ values : ( 0 ..size ) . map ( |_| AtomicU32 :: new ( COMPRESSED_NONE ) ) . collect ( ) ,
10491082 }
10501083 }
10511084
10521085 fn get ( & self , index : SerializedDepNodeIndex ) -> Option < DepNodeColor > {
1053- match self . values [ index] {
1086+ match self . values [ index] . load ( Ordering :: Acquire ) {
10541087 COMPRESSED_NONE => None ,
10551088 COMPRESSED_RED => Some ( DepNodeColor :: Red ) ,
10561089 value => Some ( DepNodeColor :: Green ( DepNodeIndex :: from_u32 (
@@ -1059,10 +1092,10 @@ impl DepNodeColorMap {
10591092 }
10601093 }
10611094
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 {
10641097 DepNodeColor :: Red => COMPRESSED_RED ,
10651098 DepNodeColor :: Green ( index) => index. as_u32 ( ) + COMPRESSED_FIRST_GREEN ,
1066- }
1099+ } , Ordering :: Release )
10671100 }
10681101}
0 commit comments