1
Fork 0

Add a query type which is always marked as red if it runs

This commit is contained in:
John Kåre Alsaker 2019-01-20 05:44:02 +01:00
parent d173180116
commit 34ec9a5942
8 changed files with 106 additions and 61 deletions

View file

@ -79,6 +79,16 @@ struct DepGraphData {
loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>, loaded_from_cache: Lock<FxHashMap<DepNodeIndex, bool>>,
} }
pub fn hash_result<R>(hcx: &mut StableHashingContext<'_>, result: &R) -> Option<Fingerprint>
where
R: for<'a> HashStable<StableHashingContext<'a>>,
{
let mut stable_hasher = StableHasher::new();
result.hash_stable(hcx, &mut stable_hasher);
Some(stable_hasher.finish())
}
impl DepGraph { impl DepGraph {
pub fn new(prev_graph: PreviousDepGraph, pub fn new(prev_graph: PreviousDepGraph,
@ -178,14 +188,16 @@ impl DepGraph {
/// `arg` parameter. /// `arg` parameter.
/// ///
/// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html /// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html
pub fn with_task<'gcx, C, A, R>(&self, pub fn with_task<'a, C, A, R>(
&self,
key: DepNode, key: DepNode,
cx: C, cx: C,
arg: A, arg: A,
task: fn(C, A) -> R) task: fn(C, A) -> R,
-> (R, DepNodeIndex) hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option<Fingerprint>,
where C: DepGraphSafe + StableHashingContextProvider<'gcx>, ) -> (R, DepNodeIndex)
R: HashStable<StableHashingContext<'gcx>>, where
C: DepGraphSafe + StableHashingContextProvider<'a>,
{ {
self.with_task_impl(key, cx, arg, false, task, self.with_task_impl(key, cx, arg, false, task,
|_key| Some(TaskDeps { |_key| Some(TaskDeps {
@ -196,17 +208,18 @@ impl DepGraph {
}), }),
|data, key, fingerprint, task| { |data, key, fingerprint, task| {
data.borrow_mut().complete_task(key, task.unwrap(), fingerprint) data.borrow_mut().complete_task(key, task.unwrap(), fingerprint)
}) },
hash_result)
} }
/// Creates a new dep-graph input with value `input` /// Creates a new dep-graph input with value `input`
pub fn input_task<'gcx, C, R>(&self, pub fn input_task<'a, C, R>(&self,
key: DepNode, key: DepNode,
cx: C, cx: C,
input: R) input: R)
-> (R, DepNodeIndex) -> (R, DepNodeIndex)
where C: DepGraphSafe + StableHashingContextProvider<'gcx>, where C: DepGraphSafe + StableHashingContextProvider<'a>,
R: HashStable<StableHashingContext<'gcx>>, R: for<'b> HashStable<StableHashingContext<'b>>,
{ {
fn identity_fn<C, A>(_: C, arg: A) -> A { fn identity_fn<C, A>(_: C, arg: A) -> A {
arg arg
@ -216,10 +229,11 @@ impl DepGraph {
|_| None, |_| None,
|data, key, fingerprint, _| { |data, key, fingerprint, _| {
data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint) data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint)
}) },
hash_result::<R>)
} }
fn with_task_impl<'gcx, C, A, R>( fn with_task_impl<'a, C, A, R>(
&self, &self,
key: DepNode, key: DepNode,
cx: C, cx: C,
@ -230,11 +244,11 @@ impl DepGraph {
finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>, finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
DepNode, DepNode,
Fingerprint, Fingerprint,
Option<TaskDeps>) -> DepNodeIndex Option<TaskDeps>) -> DepNodeIndex,
hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option<Fingerprint>,
) -> (R, DepNodeIndex) ) -> (R, DepNodeIndex)
where where
C: DepGraphSafe + StableHashingContextProvider<'gcx>, C: DepGraphSafe + StableHashingContextProvider<'a>,
R: HashStable<StableHashingContext<'gcx>>,
{ {
if let Some(ref data) = self.data { if let Some(ref data) = self.data {
let task_deps = create_task(key).map(|deps| Lock::new(deps)); let task_deps = create_task(key).map(|deps| Lock::new(deps));
@ -269,15 +283,12 @@ impl DepGraph {
profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd)
}; };
let mut stable_hasher = StableHasher::new(); let current_fingerprint = hash_result(&mut hcx, &result);
result.hash_stable(&mut hcx, &mut stable_hasher);
let current_fingerprint = stable_hasher.finish();
let dep_node_index = finish_task_and_alloc_depnode( let dep_node_index = finish_task_and_alloc_depnode(
&data.current, &data.current,
key, key,
current_fingerprint, current_fingerprint.unwrap_or(Fingerprint::ZERO),
task_deps.map(|lock| lock.into_inner()), task_deps.map(|lock| lock.into_inner()),
); );
@ -285,10 +296,15 @@ impl DepGraph {
if let Some(prev_index) = data.previous.node_to_index_opt(&key) { if let Some(prev_index) = data.previous.node_to_index_opt(&key) {
let prev_fingerprint = data.previous.fingerprint_by_index(prev_index); let prev_fingerprint = data.previous.fingerprint_by_index(prev_index);
let color = if current_fingerprint == prev_fingerprint { let color = if let Some(current_fingerprint) = current_fingerprint {
if current_fingerprint == prev_fingerprint {
DepNodeColor::Green(dep_node_index) DepNodeColor::Green(dep_node_index)
} else { } else {
DepNodeColor::Red DepNodeColor::Red
}
} else {
// Mark the node as Red if we can't hash the result
DepNodeColor::Red
}; };
debug_assert!(data.colors.get(prev_index).is_none(), debug_assert!(data.colors.get(prev_index).is_none(),
@ -342,14 +358,16 @@ impl DepGraph {
/// Execute something within an "eval-always" task which is a task /// Execute something within an "eval-always" task which is a task
// that runs whenever anything changes. // that runs whenever anything changes.
pub fn with_eval_always_task<'gcx, C, A, R>(&self, pub fn with_eval_always_task<'a, C, A, R>(
&self,
key: DepNode, key: DepNode,
cx: C, cx: C,
arg: A, arg: A,
task: fn(C, A) -> R) task: fn(C, A) -> R,
-> (R, DepNodeIndex) hash_result: impl FnOnce(&mut StableHashingContext<'_>, &R) -> Option<Fingerprint>,
where C: DepGraphSafe + StableHashingContextProvider<'gcx>, ) -> (R, DepNodeIndex)
R: HashStable<StableHashingContext<'gcx>>, where
C: DepGraphSafe + StableHashingContextProvider<'a>,
{ {
self.with_task_impl(key, cx, arg, false, task, self.with_task_impl(key, cx, arg, false, task,
|_| None, |_| None,
@ -359,7 +377,8 @@ impl DepGraph {
&DepNode::new_no_params(DepKind::Krate) &DepNode::new_no_params(DepKind::Krate)
]; ];
current.alloc_node(key, smallvec![krate_idx], fingerprint) current.alloc_node(key, smallvec![krate_idx], fingerprint)
}) },
hash_result)
} }
#[inline] #[inline]

View file

@ -10,7 +10,7 @@ pub mod cgu_reuse_tracker;
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig}; pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs}; pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs};
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps}; pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result};
pub use self::graph::WorkProductFileKind; pub use self::graph::WorkProductFileKind;
pub use self::prev::PreviousDepGraph; pub use self::prev::PreviousDepGraph;
pub use self::query::DepGraphQuery; pub use self::query::DepGraphQuery;

View file

@ -48,14 +48,14 @@ pub(super) struct NodeCollector<'a, 'hir> {
hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, hir_body_nodes: Vec<(DefPathHash, Fingerprint)>,
} }
fn input_dep_node_and_hash<'a, I>( fn input_dep_node_and_hash<I>(
dep_graph: &DepGraph, dep_graph: &DepGraph,
hcx: &mut StableHashingContext<'a>, hcx: &mut StableHashingContext<'_>,
dep_node: DepNode, dep_node: DepNode,
input: I, input: I,
) -> (DepNodeIndex, Fingerprint) ) -> (DepNodeIndex, Fingerprint)
where where
I: HashStable<StableHashingContext<'a>>, I: for<'a> HashStable<StableHashingContext<'a>>,
{ {
let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1;
@ -70,15 +70,15 @@ where
(dep_node_index, hash) (dep_node_index, hash)
} }
fn alloc_hir_dep_nodes<'a, I>( fn alloc_hir_dep_nodes<I>(
dep_graph: &DepGraph, dep_graph: &DepGraph,
hcx: &mut StableHashingContext<'a>, hcx: &mut StableHashingContext<'_>,
def_path_hash: DefPathHash, def_path_hash: DefPathHash,
item_like: I, item_like: I,
hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>,
) -> (DepNodeIndex, DepNodeIndex) ) -> (DepNodeIndex, DepNodeIndex)
where where
I: HashStable<StableHashingContext<'a>>, I: for<'a> HashStable<StableHashingContext<'a>>,
{ {
let sig = dep_graph.input_task( let sig = dep_graph.input_task(
def_path_hash.to_dep_node(DepKind::Hir), def_path_hash.to_dep_node(DepKind::Hir),
@ -286,7 +286,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
self.parent_node = parent_node; self.parent_node = parent_node;
} }
fn with_dep_node_owner<T: HashStable<StableHashingContext<'a>>, fn with_dep_node_owner<T: for<'b> HashStable<StableHashingContext<'b>>,
F: FnOnce(&mut Self)>(&mut self, F: FnOnce(&mut Self)>(&mut self,
dep_node_owner: DefIndex, dep_node_owner: DefIndex,
item_like: &T, item_like: &T,

View file

@ -1,7 +1,7 @@
//! type context book-keeping //! type context book-keeping
use crate::dep_graph::DepGraph; use crate::dep_graph::DepGraph;
use crate::dep_graph::{DepNode, DepConstructor}; use crate::dep_graph::{self, DepNode, DepConstructor};
use crate::errors::DiagnosticBuilder; use crate::errors::DiagnosticBuilder;
use crate::session::Session; use crate::session::Session;
use crate::session::config::{BorrowckMode, OutputFilenames}; use crate::session::config::{BorrowckMode, OutputFilenames};
@ -1435,7 +1435,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.dep_graph.with_task(dep_node, self.dep_graph.with_task(dep_node,
self, self,
crate_hash, crate_hash,
|_, x| x // No transformation needed |_, x| x, // No transformation needed
dep_graph::hash_result,
); );
} }
} }

View file

@ -20,7 +20,7 @@ use std::hash::Hash;
use std::fmt::Debug; use std::fmt::Debug;
use syntax_pos::symbol::InternedString; use syntax_pos::symbol::InternedString;
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_data_structures::stable_hasher::HashStable; use rustc_data_structures::fingerprint::Fingerprint;
use crate::ich::StableHashingContext; use crate::ich::StableHashingContext;
// Query configuration and description traits. // Query configuration and description traits.
@ -30,7 +30,7 @@ pub trait QueryConfig<'tcx> {
const CATEGORY: ProfileCategory; const CATEGORY: ProfileCategory;
type Key: Eq + Hash + Clone + Debug; type Key: Eq + Hash + Clone + Debug;
type Value: Clone + for<'a> HashStable<StableHashingContext<'a>>; type Value: Clone;
} }
pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
@ -44,6 +44,11 @@ pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
// Don't use this method to compute query results, instead use the methods on TyCtxt // Don't use this method to compute query results, instead use the methods on TyCtxt
fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value; fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value;
fn hash_result(
hcx: &mut StableHashingContext<'_>,
result: &Self::Value
) -> Option<Fingerprint>;
fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value; fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value;
} }

View file

@ -1,4 +1,4 @@
use crate::dep_graph::{DepConstructor, DepNode}; use crate::dep_graph::{self, DepConstructor, DepNode};
use crate::errors::DiagnosticBuilder; use crate::errors::DiagnosticBuilder;
use crate::hir::def_id::{CrateNum, DefId, DefIndex}; use crate::hir::def_id::{CrateNum, DefId, DefIndex};
use crate::hir::def::{Def, Export}; use crate::hir::def::{Def, Export};
@ -49,6 +49,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::StableVec; use rustc_data_structures::stable_hasher::StableVec;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_target::spec::PanicStrategy; use rustc_target::spec::PanicStrategy;
use std::borrow::Cow; use std::borrow::Cow;
@ -227,19 +228,19 @@ define_queries! { <'tcx>
/// Fetch the MIR for a given def-id right after it's built - this includes /// Fetch the MIR for a given def-id right after it's built - this includes
/// unreachable code. /// unreachable code.
[] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>, [no_hash] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
/// Fetch the MIR for a given def-id up till the point where it is /// Fetch the MIR for a given def-id up till the point where it is
/// ready for const evaluation. /// ready for const evaluation.
/// ///
/// See the README for the `mir` module for details. /// See the README for the `mir` module for details.
[] fn mir_const: MirConst(DefId) -> &'tcx Steal<mir::Mir<'tcx>>, [no_hash] fn mir_const: MirConst(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
[] fn mir_validated: MirValidated(DefId) -> &'tcx Steal<mir::Mir<'tcx>>, [no_hash] fn mir_validated: MirValidated(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
/// MIR after our optimization passes have run. This is MIR that is ready /// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present. /// for codegen. This is also the only query that can fetch non-local MIR, at present.
[] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>, [no_hash] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>,
}, },
TypeChecking { TypeChecking {
@ -282,7 +283,7 @@ define_queries! { <'tcx>
TypeChecking { TypeChecking {
[] fn typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult, [] fn typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
[] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, [no_hash] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
}, },
Other { Other {

View file

@ -499,7 +499,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
dep_node: &DepNode, dep_node: &DepNode,
dep_node_index: DepNodeIndex, dep_node_index: DepNodeIndex,
) { ) {
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
use crate::ich::Fingerprint; use crate::ich::Fingerprint;
assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
@ -509,11 +508,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
debug!("BEGIN verify_ich({:?})", dep_node); debug!("BEGIN verify_ich({:?})", dep_node);
let mut hcx = self.create_stable_hashing_context(); let mut hcx = self.create_stable_hashing_context();
let mut hasher = StableHasher::new();
result.hash_stable(&mut hcx, &mut hasher); let new_hash = Q::hash_result(&mut hcx, result).unwrap_or(Fingerprint::ZERO);
let new_hash: Fingerprint = hasher.finish();
debug!("END verify_ich({:?})", dep_node); debug!("END verify_ich({:?})", dep_node);
let old_hash = self.dep_graph.fingerprint_of(dep_node_index); let old_hash = self.dep_graph.fingerprint_of(dep_node_index);
@ -549,12 +545,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
tcx.dep_graph.with_eval_always_task(dep_node, tcx.dep_graph.with_eval_always_task(dep_node,
tcx, tcx,
key, key,
Q::compute) Q::compute,
Q::hash_result)
} else { } else {
tcx.dep_graph.with_task(dep_node, tcx.dep_graph.with_task(dep_node,
tcx, tcx,
key, key,
Q::compute) Q::compute,
Q::hash_result)
} }
}) })
}); });
@ -679,6 +677,18 @@ macro_rules! handle_cycle_error {
}; };
} }
macro_rules! hash_result {
([][$hcx:expr, $result:expr]) => {{
dep_graph::hash_result($hcx, &$result)
}};
([no_hash$(, $modifiers:ident)*][$hcx:expr, $result:expr]) => {{
None
}};
([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => {
hash_result!([$($modifiers),*][$($args)*])
};
}
macro_rules! define_queries { macro_rules! define_queries {
(<$tcx:tt> $($category:tt { (<$tcx:tt> $($category:tt {
$($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)* $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*
@ -966,6 +976,13 @@ macro_rules! define_queries_inner {
}) })
} }
fn hash_result(
_hcx: &mut StableHashingContext<'_>,
_result: &Self::Value
) -> Option<Fingerprint> {
hash_result!([$($modifiers)*][_hcx, _result])
}
fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value { fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value {
handle_cycle_error!([$($modifiers)*][tcx]) handle_cycle_error!([$($modifiers)*][tcx])
} }

View file

@ -20,6 +20,7 @@ use super::LlvmCodegenBackend;
use llvm; use llvm;
use metadata; use metadata;
use rustc::dep_graph;
use rustc::mir::mono::{Linkage, Visibility, Stats}; use rustc::mir::mono::{Linkage, Visibility, Stats};
use rustc::middle::cstore::{EncodedMetadata}; use rustc::middle::cstore::{EncodedMetadata};
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
@ -145,7 +146,8 @@ pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, let ((stats, module), _) = tcx.dep_graph.with_task(dep_node,
tcx, tcx,
cgu_name, cgu_name,
module_codegen); module_codegen,
dep_graph::hash_result);
let time_to_codegen = start_time.elapsed(); let time_to_codegen = start_time.elapsed();
// We assume that the cost to run LLVM on a CGU is proportional to // We assume that the cost to run LLVM on a CGU is proportional to