diff options
Diffstat (limited to 'compiler/rustc_query_system/src/dep_graph/graph.rs')
| -rw-r--r-- | compiler/rustc_query_system/src/dep_graph/graph.rs | 105 |
1 files changed, 63 insertions, 42 deletions
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 3109d53cd2c..de681328bcb 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -5,13 +5,14 @@ use std::marker::PhantomData; use std::sync::Arc; use std::sync::atomic::{AtomicU32, Ordering}; -use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef}; use rustc_data_structures::sharded::{self, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU64, Lock}; use rustc_data_structures::unord::UnordMap; +use rustc_errors::DiagInner; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -91,8 +92,6 @@ pub(crate) struct DepGraphData<D: Deps> { colors: DepNodeColorMap, - processed_side_effects: Lock<FxHashSet<DepNodeIndex>>, - /// When we load, there may be `.o` files, cached MIR, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into @@ -174,7 +173,6 @@ impl<D: Deps> DepGraph<D> { previous_work_products: prev_work_products, dep_node_debug: Default::default(), current, - processed_side_effects: Default::default(), previous: prev_graph, colors, debug_loaded_from_disk: Default::default(), @@ -535,6 +533,24 @@ impl<D: Deps> DepGraph<D> { } } + #[inline] + pub fn record_diagnostic<Qcx: QueryContext>(&self, qcx: Qcx, diagnostic: &DiagInner) { + if let Some(ref data) = self.data { + self.read_index(data.encode_diagnostic(qcx, diagnostic)); + } + } + + #[inline] + pub fn force_diagnostic_node<Qcx: QueryContext>( + &self, + qcx: Qcx, + prev_index: SerializedDepNodeIndex, + ) { + if let Some(ref data) = self.data { + data.force_diagnostic_node(qcx, prev_index); + } + } + /// Create a node when we force-feed a value into the query cache. /// This is used to remove cycles during type-checking const generic parameters. /// @@ -656,6 +672,48 @@ impl<D: Deps> DepGraphData<D> { pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { self.debug_loaded_from_disk.lock().insert(dep_node); } + + #[inline] + fn encode_diagnostic<Qcx: QueryContext>( + &self, + qcx: Qcx, + diagnostic: &DiagInner, + ) -> DepNodeIndex { + let dep_node_index = self.current.encoder.send( + DepNode { + kind: D::DEP_KIND_SIDE_EFFECT, + hash: PackedFingerprint::from(Fingerprint::ZERO), + }, + Fingerprint::ZERO, + // We want the side effect node to always be red so it will be forced and emit the + // diagnostic. + std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), + ); + let side_effects = QuerySideEffects { diagnostic: diagnostic.clone() }; + qcx.store_side_effects(dep_node_index, side_effects); + dep_node_index + } + + #[inline] + fn force_diagnostic_node<Qcx: QueryContext>( + &self, + qcx: Qcx, + prev_index: SerializedDepNodeIndex, + ) { + D::with_deps(TaskDepsRef::Ignore, || { + let side_effects = qcx.load_side_effects(prev_index).unwrap(); + + qcx.dep_context().sess().dcx().emit_diagnostic(side_effects.diagnostic.clone()); + + // Promote the previous diagnostics to the current session. + let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index); + // FIXME: Can this race with a parallel compiler? + qcx.store_side_effects(index, side_effects); + + // Mark the node as green. + self.colors.insert(prev_index, DepNodeColor::Green(index)); + }) + } } impl<D: Deps> DepGraph<D> { @@ -794,7 +852,7 @@ impl<D: Deps> DepGraphData<D> { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) { + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -867,16 +925,6 @@ impl<D: Deps> DepGraphData<D> { // ... emitting any stored diagnostic ... - // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere - // Maybe store a list on disk and encode this fact in the DepNodeState - let side_effects = qcx.load_side_effects(prev_dep_node_index); - - if side_effects.maybe_any() { - qcx.dep_context().dep_graph().with_query_deserialization(|| { - self.emit_side_effects(qcx, dep_node_index, side_effects) - }); - } - // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index)); @@ -884,33 +932,6 @@ impl<D: Deps> DepGraphData<D> { debug!("successfully marked {dep_node:?} as green"); Some(dep_node_index) } - - /// Atomically emits some loaded diagnostics. - /// This may be called concurrently on multiple threads for the same dep node. - #[cold] - #[inline(never)] - fn emit_side_effects<Qcx: QueryContext<Deps = D>>( - &self, - qcx: Qcx, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - let mut processed = self.processed_side_effects.lock(); - - if processed.insert(dep_node_index) { - // We were the first to insert the node in the set so this thread - // must process side effects - - // Promote the previous diagnostics to the current session. - qcx.store_side_effects(dep_node_index, side_effects.clone()); - - let dcx = qcx.dep_context().sess().dcx(); - - for diagnostic in side_effects.diagnostics { - dcx.emit_diagnostic(diagnostic); - } - } - } } impl<D: Deps> DepGraph<D> { |
