@@ -7,6 +7,7 @@ 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 ;
10
+ use std:: mem;
10
11
use crate :: ty:: { self , TyCtxt } ;
11
12
use crate :: util:: common:: { ProfileQueriesMsg , profq_msg} ;
12
13
use parking_lot:: { Mutex , Condvar } ;
@@ -61,11 +62,11 @@ struct DepGraphData {
61
62
62
63
colors : DepNodeColorMap ,
63
64
64
- /// A set of loaded diagnostics that have been emitted.
65
- emitted_diagnostics : Mutex < FxHashSet < DepNodeIndex > > ,
65
+ /// A set of loaded diagnostics that is in the progress of being emitted.
66
+ emitting_diagnostics : Mutex < FxHashSet < DepNodeIndex > > ,
66
67
67
68
/// Used to wait for diagnostics to be emitted.
68
- emitted_diagnostics_cond_var : Condvar ,
69
+ emitting_diagnostics_cond_var : Condvar ,
69
70
70
71
/// When we load, there may be `.o` files, cached MIR, or other such
71
72
/// things available to us. If we find that they are not dirty, we
@@ -99,8 +100,8 @@ impl DepGraph {
99
100
previous_work_products : prev_work_products,
100
101
dep_node_debug : Default :: default ( ) ,
101
102
current : Lock :: new ( CurrentDepGraph :: new ( prev_graph_node_count) ) ,
102
- emitted_diagnostics : Default :: default ( ) ,
103
- emitted_diagnostics_cond_var : Condvar :: new ( ) ,
103
+ emitting_diagnostics : Default :: default ( ) ,
104
+ emitting_diagnostics_cond_var : Condvar :: new ( ) ,
104
105
previous : prev_graph,
105
106
colors : DepNodeColorMap :: new ( prev_graph_node_count) ,
106
107
loaded_from_cache : Default :: default ( ) ,
@@ -744,7 +745,7 @@ impl DepGraph {
744
745
745
746
// There may be multiple threads trying to mark the same dep node green concurrently
746
747
747
- let ( dep_node_index, did_allocation ) = {
748
+ let dep_node_index = {
748
749
let mut current = data. current . borrow_mut ( ) ;
749
750
750
751
// Copy the fingerprint from the previous graph,
@@ -758,71 +759,86 @@ impl DepGraph {
758
759
759
760
// ... emitting any stored diagnostic ...
760
761
762
+ // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere
763
+ // Maybe store a list on disk and encode this fact in the DepNodeState
761
764
let diagnostics = tcx. queries . on_disk_cache
762
- . load_diagnostics ( tcx, prev_dep_node_index) ;
765
+ . load_diagnostics ( tcx, prev_dep_node_index) ;
766
+
767
+ #[ cfg( not( parallel_compiler) ) ]
768
+ debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ,
769
+ "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
770
+ insertion for {:?}", dep_node) ;
763
771
764
772
if unlikely ! ( diagnostics. len( ) > 0 ) {
765
773
self . emit_diagnostics (
766
774
tcx,
767
775
data,
768
776
dep_node_index,
769
- did_allocation ,
777
+ prev_dep_node_index ,
770
778
diagnostics
771
779
) ;
772
780
}
773
781
774
782
// ... and finally storing a "Green" entry in the color map.
775
783
// Multiple threads can all write the same color here
776
- #[ cfg( not( parallel_compiler) ) ]
777
- debug_assert ! ( data. colors. get( prev_dep_node_index) . is_none( ) ,
778
- "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
779
- insertion for {:?}", dep_node) ;
780
-
781
784
data. colors . insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
782
785
783
786
debug ! ( "try_mark_previous_green({:?}) - END - successfully marked as green" , dep_node) ;
784
787
Some ( dep_node_index)
785
788
}
786
789
787
- /// Atomically emits some loaded diagnotics, assuming that this only gets called with
788
- /// `did_allocation` set to `true` on a single thread .
790
+ /// Atomically emits some loaded diagnostics.
791
+ /// This may be called concurrently on multiple threads for the same dep node .
789
792
#[ cold]
790
793
#[ inline( never) ]
791
794
fn emit_diagnostics < ' tcx > (
792
795
& self ,
793
796
tcx : TyCtxt < ' tcx > ,
794
797
data : & DepGraphData ,
795
798
dep_node_index : DepNodeIndex ,
796
- did_allocation : bool ,
799
+ prev_dep_node_index : SerializedDepNodeIndex ,
797
800
diagnostics : Vec < Diagnostic > ,
798
801
) {
799
- if did_allocation || !cfg ! ( parallel_compiler) {
800
- // Only the thread which did the allocation emits the error messages
801
- let handle = tcx. sess . diagnostic ( ) ;
802
+ let mut emitting = data. emitting_diagnostics . lock ( ) ;
803
+
804
+ if data. colors . get ( prev_dep_node_index) == Some ( DepNodeColor :: Green ( dep_node_index) ) {
805
+ // The node is already green so diagnostics must have been emitted already
806
+ return ;
807
+ }
808
+
809
+ if emitting. insert ( dep_node_index) {
810
+ // We were the first to insert the node in the set so this thread
811
+ // must emit the diagnostics and signal other potentially waiting
812
+ // threads after.
813
+ mem:: drop ( emitting) ;
802
814
803
815
// Promote the previous diagnostics to the current session.
804
816
tcx. queries . on_disk_cache
805
- . store_diagnostics ( dep_node_index, diagnostics. clone ( ) . into ( ) ) ;
817
+ . store_diagnostics ( dep_node_index, diagnostics. clone ( ) . into ( ) ) ;
818
+
819
+ let handle = tcx. sess . diagnostic ( ) ;
806
820
807
821
for diagnostic in diagnostics {
808
822
DiagnosticBuilder :: new_diagnostic ( handle, diagnostic) . emit ( ) ;
809
823
}
810
824
811
- #[ cfg( parallel_compiler) ]
812
- {
813
- // Mark the diagnostics and emitted and wake up waiters
814
- data. emitted_diagnostics . lock ( ) . insert ( dep_node_index) ;
815
- data. emitted_diagnostics_cond_var . notify_all ( ) ;
816
- }
825
+ // Mark the node as green now that diagnostics are emitted
826
+ data. colors . insert ( prev_dep_node_index, DepNodeColor :: Green ( dep_node_index) ) ;
827
+
828
+ // Remove the node from the set
829
+ data. emitting_diagnostics . lock ( ) . remove ( & dep_node_index) ;
830
+
831
+ // Wake up waiters
832
+ data. emitting_diagnostics_cond_var . notify_all ( ) ;
817
833
} else {
818
- // The other threads will wait for the diagnostics to be emitted
834
+ // We must wait for the other thread to finish emitting the diagnostic
819
835
820
- let mut emitted_diagnostics = data. emitted_diagnostics . lock ( ) ;
821
836
loop {
822
- if emitted_diagnostics. contains ( & dep_node_index) {
837
+ data. emitting_diagnostics_cond_var . wait ( & mut emitting) ;
838
+ if data. colors
839
+ . get ( prev_dep_node_index) == Some ( DepNodeColor :: Green ( dep_node_index) ) {
823
840
break ;
824
841
}
825
- data. emitted_diagnostics_cond_var . wait ( & mut emitted_diagnostics) ;
826
842
}
827
843
}
828
844
}
@@ -1027,7 +1043,7 @@ impl CurrentDepGraph {
1027
1043
hash : self . anon_id_seed . combine ( hasher. finish ( ) ) ,
1028
1044
} ;
1029
1045
1030
- self . intern_node ( target_dep_node, task_deps. reads , Fingerprint :: ZERO ) . 0
1046
+ self . intern_node ( target_dep_node, task_deps. reads , Fingerprint :: ZERO )
1031
1047
}
1032
1048
1033
1049
fn alloc_node (
@@ -1037,19 +1053,19 @@ impl CurrentDepGraph {
1037
1053
fingerprint : Fingerprint
1038
1054
) -> DepNodeIndex {
1039
1055
debug_assert ! ( !self . node_to_node_index. contains_key( & dep_node) ) ;
1040
- self . intern_node ( dep_node, edges, fingerprint) . 0
1056
+ self . intern_node ( dep_node, edges, fingerprint)
1041
1057
}
1042
1058
1043
1059
fn intern_node (
1044
1060
& mut self ,
1045
1061
dep_node : DepNode ,
1046
1062
edges : SmallVec < [ DepNodeIndex ; 8 ] > ,
1047
1063
fingerprint : Fingerprint
1048
- ) -> ( DepNodeIndex , bool ) {
1064
+ ) -> DepNodeIndex {
1049
1065
debug_assert_eq ! ( self . node_to_node_index. len( ) , self . data. len( ) ) ;
1050
1066
1051
1067
match self . node_to_node_index . entry ( dep_node) {
1052
- Entry :: Occupied ( entry) => ( * entry. get ( ) , false ) ,
1068
+ Entry :: Occupied ( entry) => * entry. get ( ) ,
1053
1069
Entry :: Vacant ( entry) => {
1054
1070
let dep_node_index = DepNodeIndex :: new ( self . data . len ( ) ) ;
1055
1071
self . data . push ( DepNodeData {
@@ -1058,7 +1074,7 @@ impl CurrentDepGraph {
1058
1074
fingerprint
1059
1075
} ) ;
1060
1076
entry. insert ( dep_node_index) ;
1061
- ( dep_node_index, true )
1077
+ dep_node_index
1062
1078
}
1063
1079
}
1064
1080
}
0 commit comments