1
Fork 0

incr.comp.: Move result fingerprinting to DepGraph::with_task().

This makes sure that we don't introduce strange cases where we have
nodes outside the query system that could break red/green tracking
and it will allow to keep red/green neatly encapsulated within the
DepGraph implementation.
This commit is contained in:
Michael Woerister 2017-09-07 16:11:58 +02:00
parent e6c9a53d1a
commit 3cc3ae22bd
9 changed files with 130 additions and 37 deletions

View file

@ -9,11 +9,15 @@
// except according to those terms. // except according to those terms.
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHashingContextProvider};
use session::config::OutputType; use session::config::OutputType;
use std::cell::{Ref, RefCell}; use std::cell::{Ref, RefCell};
use std::rc::Rc; use std::rc::Rc;
use util::common::{ProfileQueriesMsg, profq_msg}; use util::common::{ProfileQueriesMsg, profq_msg};
use ich::Fingerprint;
use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::dep_node::{DepNode, DepKind, WorkProductId};
use super::query::DepGraphQuery; use super::query::DepGraphQuery;
use super::raii; use super::raii;
@ -71,10 +75,6 @@ impl DepGraph {
self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges)) self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges))
} }
pub fn in_task<'graph>(&'graph self, key: DepNode) -> Option<raii::DepTask<'graph>> {
self.data.as_ref().map(|data| raii::DepTask::new(&data.edges, key))
}
pub fn with_ignore<OP,R>(&self, op: OP) -> R pub fn with_ignore<OP,R>(&self, op: OP) -> R
where OP: FnOnce() -> R where OP: FnOnce() -> R
{ {
@ -109,24 +109,38 @@ impl DepGraph {
/// `arg` parameter. /// `arg` parameter.
/// ///
/// [README]: README.md /// [README]: README.md
pub fn with_task<C, A, R>(&self, pub fn with_task<C, A, R, HCX>(&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) -> (R, DepNodeIndex)
where C: DepGraphSafe where C: DepGraphSafe + StableHashingContextProvider<ContextType=HCX>,
R: HashStable<HCX>,
{ {
if let Some(ref data) = self.data { if let Some(ref data) = self.data {
data.edges.borrow_mut().push_task(key); data.edges.borrow_mut().push_task(key);
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
profq_msg(ProfileQueriesMsg::TaskBegin(key.clone())) profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
}; };
// In incremental mode, hash the result of the task. We don't
// do anything with the hash yet, but we are computing it
// anyway so that
// - we make sure that the infrastructure works and
// - we can get an idea of the runtime cost.
let mut hcx = cx.create_stable_hashing_context();
let result = task(cx, arg); let result = task(cx, arg);
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
profq_msg(ProfileQueriesMsg::TaskEnd) profq_msg(ProfileQueriesMsg::TaskEnd)
}; };
let dep_node_index = data.edges.borrow_mut().pop_task(key); let dep_node_index = data.edges.borrow_mut().pop_task(key);
let mut stable_hasher = StableHasher::new();
result.hash_stable(&mut hcx, &mut stable_hasher);
let _: Fingerprint = stable_hasher.finish();
(result, dep_node_index) (result, dep_node_index)
} else { } else {
(task(cx, arg), DepNodeIndex::INVALID) (task(cx, arg), DepNodeIndex::INVALID)

View file

@ -58,6 +58,13 @@ impl<'a, A> DepGraphSafe for &'a A
{ {
} }
/// Mut ref to dep-graph-safe stuff should still be dep-graph-safe.
impl<'a, A> DepGraphSafe for &'a mut A
where A: DepGraphSafe,
{
}
/// No data here! :) /// No data here! :)
impl DepGraphSafe for () { impl DepGraphSafe for () {
} }

View file

@ -26,8 +26,8 @@ use syntax::ext::hygiene::SyntaxContext;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax_pos::Span; use syntax_pos::Span;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, use rustc_data_structures::stable_hasher::{HashStable, StableHashingContextProvider,
StableHasherResult}; StableHasher, StableHasherResult};
use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::accumulate_vec::AccumulateVec;
/// This is the context state available during incr. comp. hashing. It contains /// This is the context state available during incr. comp. hashing. It contains
@ -196,6 +196,12 @@ impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
} }
} }
impl<'a, 'gcx, 'lcx> StableHashingContextProvider for ty::TyCtxt<'a, 'gcx, 'lcx> {
type ContextType = StableHashingContext<'a, 'gcx, 'lcx>;
fn create_stable_hashing_context(&self) -> Self::ContextType {
StableHashingContext::new(*self)
}
}
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId { impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ast::NodeId {
fn hash_stable<W: StableHasherResult>(&self, fn hash_stable<W: StableHasherResult>(&self,

View file

@ -14,7 +14,6 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
use hir::def::{Def, Export}; use hir::def::{Def, Export};
use hir::{self, TraitCandidate, ItemLocalId}; use hir::{self, TraitCandidate, ItemLocalId};
use hir::svh::Svh; use hir::svh::Svh;
use ich::{Fingerprint, StableHashingContext};
use lint; use lint;
use middle::const_val; use middle::const_val;
use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary}; use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
@ -46,7 +45,7 @@ use rustc_back::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use std::cell::{RefCell, RefMut, Cell}; use std::cell::{RefCell, RefMut, Cell};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt::Debug; use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -953,20 +952,6 @@ macro_rules! define_maps {
tcx.dep_graph.read_index(dep_node_index); tcx.dep_graph.read_index(dep_node_index);
// In incremental mode, hash the result of the query. We don't
// do anything with the hash yet, but we are computing it
// anyway so that
// - we make sure that the infrastructure works and
// - we can get an idea of the runtime cost.
if !dep_node.kind.is_anon() && tcx.sess.opts.incremental.is_some() {
let mut hcx = StableHashingContext::new(tcx);
let mut hasher = StableHasher::new();
result.hash_stable(&mut hcx, &mut hasher);
let _: Fingerprint = hasher.finish();
}
let value = QueryValue { let value = QueryValue {
value: result, value: result,
index: dep_node_index, index: dep_node_index,

View file

@ -2575,6 +2575,10 @@ pub struct SymbolName {
pub name: InternedString pub name: InternedString
} }
impl_stable_hash_for!(struct self::SymbolName {
name
});
impl Deref for SymbolName { impl Deref for SymbolName {
type Target = str; type Target = str;

View file

@ -192,6 +192,28 @@ impl<W> Hasher for StableHasher<W> {
} }
/// Something that can provide a stable hashing context.
pub trait StableHashingContextProvider {
type ContextType;
fn create_stable_hashing_context(&self) -> Self::ContextType;
}
impl<'a, T: StableHashingContextProvider> StableHashingContextProvider for &'a T {
type ContextType = T::ContextType;
fn create_stable_hashing_context(&self) -> Self::ContextType {
(**self).create_stable_hashing_context()
}
}
impl<'a, T: StableHashingContextProvider> StableHashingContextProvider for &'a mut T {
type ContextType = T::ContextType;
fn create_stable_hashing_context(&self) -> Self::ContextType {
(**self).create_stable_hashing_context()
}
}
/// Something that implements `HashStable<CTX>` can be hashed in a way that is /// Something that implements `HashStable<CTX>` can be hashed in a way that is
/// stable across multiple compilation sessions. /// stable across multiple compilation sessions.
pub trait HashStable<CTX> { pub trait HashStable<CTX> {
@ -292,7 +314,7 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Vec<T> {
} }
} }
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Box<T> { impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
#[inline] #[inline]
fn hash_stable<W: StableHasherResult>(&self, fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX, ctx: &mut CTX,
@ -301,7 +323,7 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for Box<T> {
} }
} }
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> { impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
#[inline] #[inline]
fn hash_stable<W: StableHasherResult>(&self, fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX, ctx: &mut CTX,
@ -310,7 +332,7 @@ impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ::std::rc::Rc<T> {
} }
} }
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ::std::sync::Arc<T> { impl<T: ?Sized + HashStable<CTX>, CTX> HashStable<CTX> for ::std::sync::Arc<T> {
#[inline] #[inline]
fn hash_stable<W: StableHasherResult>(&self, fn hash_stable<W: StableHasherResult>(&self,
ctx: &mut CTX, ctx: &mut CTX,

View file

@ -1070,7 +1070,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let start_time = Instant::now(); let start_time = Instant::now();
all_stats.extend(tcx.compile_codegen_unit(*cgu.name())); all_stats.extend(tcx.compile_codegen_unit(*cgu.name()));
total_trans_time += start_time.elapsed(); total_trans_time += start_time.elapsed();
ongoing_translation.check_for_errors(tcx.sess); ongoing_translation.check_for_errors(tcx.sess);
} }
@ -1566,4 +1565,34 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
Visibility::Hidden => llvm::Visibility::Hidden, Visibility::Hidden => llvm::Visibility::Hidden,
Visibility::Protected => llvm::Visibility::Protected, Visibility::Protected => llvm::Visibility::Protected,
} }
// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
// the HashStable trait. Normally DepGraph::with_task() calls are
// hidden behind queries, but CGU creation is a special case in two
// ways: (1) it's not a query and (2) CGU are output nodes, so their
// Fingerprints are not actually needed. It remains to be clarified
// how exactly this case will be handled in the red/green system but
// for now we content ourselves with providing a no-op HashStable
// implementation for CGUs.
mod temp_stable_hash_impls {
use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
HashStable};
use context::Stats;
use ModuleTranslation;
impl<HCX> HashStable<HCX> for Stats {
fn hash_stable<W: StableHasherResult>(&self,
_: &mut HCX,
_: &mut StableHasher<W>) {
// do nothing
}
}
impl<HCX> HashStable<HCX> for ModuleTranslation {
fn hash_stable<W: StableHasherResult>(&self,
_: &mut HCX,
_: &mut StableHasher<W>) {
// do nothing
}
}
} }

View file

@ -14,6 +14,7 @@ use llvm::{ContextRef, ModuleRef, ValueRef};
use rustc::dep_graph::{DepGraph, DepGraphSafe}; use rustc::dep_graph::{DepGraph, DepGraphSafe};
use rustc::hir; use rustc::hir;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::ich::StableHashingContext;
use rustc::traits; use rustc::traits;
use debuginfo; use debuginfo;
use callee; use callee;
@ -25,6 +26,8 @@ use partitioning::CodegenUnit;
use type_::Type; use type_::Type;
use rustc_data_structures::base_n; use rustc_data_structures::base_n;
use rustc::middle::trans::Stats; use rustc::middle::trans::Stats;
use rustc_data_structures::stable_hasher::StableHashingContextProvider;
use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
use rustc::session::Session; use rustc::session::Session;
use rustc::session::config::{self, NoDebugInfo}; use rustc::session::config::{self, NoDebugInfo};
use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout}; use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
@ -134,6 +137,17 @@ impl<'a, 'tcx> CrateContext<'a, 'tcx> {
impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> { impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
} }
impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
}
impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
type ContextType = StableHashingContext<'a, 'tcx, 'tcx>;
fn create_stable_hashing_context(&self) -> Self::ContextType {
StableHashingContext::new(self.tcx)
}
}
pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
let reloc_model_arg = match sess.opts.cg.relocation_model { let reloc_model_arg = match sess.opts.cg.relocation_model {
Some(ref s) => &s[..], Some(ref s) => &s[..],

View file

@ -14,7 +14,8 @@
//! We walk the set of items and, for each member, generate new constraints. //! We walk the set of items and, for each member, generate new constraints.
use hir::def_id::DefId; use hir::def_id::DefId;
use rustc::dep_graph::{AssertDepGraphSafe, DepKind}; use rustc::dep_graph::{DepGraphSafe, DepKind};
use rustc::ich::StableHashingContext;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use syntax::ast; use syntax::ast;
@ -22,6 +23,7 @@ use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc_data_structures::transitive_relation::TransitiveRelation; use rustc_data_structures::transitive_relation::TransitiveRelation;
use rustc_data_structures::stable_hasher::StableHashingContextProvider;
use super::terms::*; use super::terms::*;
use super::terms::VarianceTerm::*; use super::terms::VarianceTerm::*;
@ -138,6 +140,16 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
} }
} }
impl<'a, 'tcx> StableHashingContextProvider for ConstraintContext<'a, 'tcx> {
type ContextType = StableHashingContext<'a, 'tcx, 'tcx>;
fn create_stable_hashing_context(&self) -> Self::ContextType {
StableHashingContext::new(self.terms_cx.tcx)
}
}
impl<'a, 'tcx> DepGraphSafe for ConstraintContext<'a, 'tcx> {}
impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
fn visit_node_helper(&mut self, id: ast::NodeId) { fn visit_node_helper(&mut self, id: ast::NodeId) {
let tcx = self.terms_cx.tcx; let tcx = self.terms_cx.tcx;
@ -151,14 +163,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// on dep-graph management. // on dep-graph management.
let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints); let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
tcx.dep_graph.with_task(dep_node, tcx.dep_graph.with_task(dep_node,
AssertDepGraphSafe(self), self,
def_id, def_id,
visit_item_task); visit_item_task);
fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>, fn visit_item_task<'a, 'tcx>(ccx: &mut ConstraintContext<'a, 'tcx>,
def_id: DefId) def_id: DefId)
{ {
ccx.0.build_constraints_for_item(def_id); ccx.build_constraints_for_item(def_id);
} }
} }