mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
incr.comp.: Introduce the concept of anonymous DepNodes.
This commit is contained in:
parent
089860b603
commit
0363a23c35
@ -79,9 +79,14 @@ macro_rules! erase {
|
||||
($x:tt) => ({})
|
||||
}
|
||||
|
||||
macro_rules! anon_attr_to_bool {
|
||||
(anon) => (true)
|
||||
}
|
||||
|
||||
macro_rules! define_dep_nodes {
|
||||
(<$tcx:tt>
|
||||
$(
|
||||
[$($anon:ident)*]
|
||||
$variant:ident $(( $($tuple_arg:tt),* ))*
|
||||
$({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })*
|
||||
,)*
|
||||
@ -117,6 +122,19 @@ macro_rules! define_dep_nodes {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
#[inline]
|
||||
pub fn is_anon<$tcx>(&self) -> bool {
|
||||
match *self {
|
||||
$(
|
||||
DepKind :: $variant => {
|
||||
$(return anon_attr_to_bool!($anon);)*
|
||||
false
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
#[inline]
|
||||
pub fn has_params(&self) -> bool {
|
||||
@ -356,100 +374,101 @@ define_dep_nodes!( <'tcx>
|
||||
// suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
|
||||
// access to the krate, but you must remember to add suitable
|
||||
// edges yourself for the individual items that you read.
|
||||
Krate,
|
||||
[] Krate,
|
||||
|
||||
// Represents the HIR node with the given node-id
|
||||
Hir(DefId),
|
||||
[] Hir(DefId),
|
||||
|
||||
// Represents the body of a function or method. The def-id is that of the
|
||||
// function/method.
|
||||
HirBody(DefId),
|
||||
[] HirBody(DefId),
|
||||
|
||||
// Represents the metadata for a given HIR node, typically found
|
||||
// in an extern crate.
|
||||
MetaData(DefId),
|
||||
[] MetaData(DefId),
|
||||
|
||||
// Represents some artifact that we save to disk. Note that these
|
||||
// do not have a def-id as part of their identifier.
|
||||
WorkProduct(WorkProductId),
|
||||
[] WorkProduct(WorkProductId),
|
||||
|
||||
// Represents different phases in the compiler.
|
||||
RegionMaps(DefId),
|
||||
Coherence,
|
||||
Resolve,
|
||||
CoherenceCheckTrait(DefId),
|
||||
PrivacyAccessLevels(CrateNum),
|
||||
[] RegionMaps(DefId),
|
||||
[] Coherence,
|
||||
[] Resolve,
|
||||
[] CoherenceCheckTrait(DefId),
|
||||
[] PrivacyAccessLevels(CrateNum),
|
||||
|
||||
// Represents the MIR for a fn; also used as the task node for
|
||||
// things read/modify that MIR.
|
||||
MirConstQualif(DefId),
|
||||
MirConst(DefId),
|
||||
MirValidated(DefId),
|
||||
MirOptimized(DefId),
|
||||
MirShim { instance_def: InstanceDef<'tcx> },
|
||||
[] MirConstQualif(DefId),
|
||||
[] MirConst(DefId),
|
||||
[] MirValidated(DefId),
|
||||
[] MirOptimized(DefId),
|
||||
[] MirShim { instance_def: InstanceDef<'tcx> },
|
||||
|
||||
BorrowCheckKrate,
|
||||
BorrowCheck(DefId),
|
||||
RvalueCheck(DefId),
|
||||
Reachability,
|
||||
MirKeys,
|
||||
TransWriteMetadata,
|
||||
CrateVariances,
|
||||
[] BorrowCheckKrate,
|
||||
[] BorrowCheck(DefId),
|
||||
[] RvalueCheck(DefId),
|
||||
[] Reachability,
|
||||
[] MirKeys,
|
||||
[] TransWriteMetadata,
|
||||
[] CrateVariances,
|
||||
|
||||
// Nodes representing bits of computed IR in the tcx. Each shared
|
||||
// table in the tcx (or elsewhere) maps to one of these
|
||||
// nodes.
|
||||
AssociatedItems(DefId),
|
||||
TypeOfItem(DefId),
|
||||
GenericsOfItem(DefId),
|
||||
PredicatesOfItem(DefId),
|
||||
SuperPredicatesOfItem(DefId),
|
||||
TraitDefOfItem(DefId),
|
||||
AdtDefOfItem(DefId),
|
||||
IsDefaultImpl(DefId),
|
||||
ImplTraitRef(DefId),
|
||||
ImplPolarity(DefId),
|
||||
ClosureKind(DefId),
|
||||
FnSignature(DefId),
|
||||
CoerceUnsizedInfo(DefId),
|
||||
[] AssociatedItems(DefId),
|
||||
[] TypeOfItem(DefId),
|
||||
[] GenericsOfItem(DefId),
|
||||
[] PredicatesOfItem(DefId),
|
||||
[] SuperPredicatesOfItem(DefId),
|
||||
[] TraitDefOfItem(DefId),
|
||||
[] AdtDefOfItem(DefId),
|
||||
[] IsDefaultImpl(DefId),
|
||||
[] ImplTraitRef(DefId),
|
||||
[] ImplPolarity(DefId),
|
||||
[] ClosureKind(DefId),
|
||||
[] FnSignature(DefId),
|
||||
[] CoerceUnsizedInfo(DefId),
|
||||
|
||||
ItemVarianceConstraints(DefId),
|
||||
ItemVariances(DefId),
|
||||
IsConstFn(DefId),
|
||||
IsForeignItem(DefId),
|
||||
TypeParamPredicates { item_id: DefId, param_id: DefId },
|
||||
SizedConstraint(DefId),
|
||||
DtorckConstraint(DefId),
|
||||
AdtDestructor(DefId),
|
||||
AssociatedItemDefIds(DefId),
|
||||
InherentImpls(DefId),
|
||||
TypeckBodiesKrate,
|
||||
TypeckTables(DefId),
|
||||
HasTypeckTables(DefId),
|
||||
ConstEval { def_id: DefId, substs: &'tcx Substs<'tcx> },
|
||||
SymbolName(DefId),
|
||||
InstanceSymbolName { instance: Instance<'tcx> },
|
||||
SpecializationGraph(DefId),
|
||||
ObjectSafety(DefId),
|
||||
IsCopy(DefId),
|
||||
IsSized(DefId),
|
||||
IsFreeze(DefId),
|
||||
NeedsDrop(DefId),
|
||||
Layout(DefId),
|
||||
[] ItemVarianceConstraints(DefId),
|
||||
[] ItemVariances(DefId),
|
||||
[] IsConstFn(DefId),
|
||||
[] IsForeignItem(DefId),
|
||||
[] TypeParamPredicates { item_id: DefId, param_id: DefId },
|
||||
[] SizedConstraint(DefId),
|
||||
[] DtorckConstraint(DefId),
|
||||
[] AdtDestructor(DefId),
|
||||
[] AssociatedItemDefIds(DefId),
|
||||
[] InherentImpls(DefId),
|
||||
[] TypeckBodiesKrate,
|
||||
[] TypeckTables(DefId),
|
||||
[] HasTypeckTables(DefId),
|
||||
[] ConstEval { def_id: DefId, substs: &'tcx Substs<'tcx> },
|
||||
[] SymbolName(DefId),
|
||||
[] InstanceSymbolName { instance: Instance<'tcx> },
|
||||
[] SpecializationGraph(DefId),
|
||||
[] ObjectSafety(DefId),
|
||||
|
||||
[anon] IsCopy(DefId),
|
||||
[anon] IsSized(DefId),
|
||||
[anon] IsFreeze(DefId),
|
||||
[anon] NeedsDrop(DefId),
|
||||
[anon] Layout(DefId),
|
||||
|
||||
// The set of impls for a given trait.
|
||||
TraitImpls(DefId),
|
||||
RelevantTraitImpls(DefId, SimplifiedType),
|
||||
[] TraitImpls(DefId),
|
||||
[] RelevantTraitImpls(DefId, SimplifiedType),
|
||||
|
||||
AllLocalTraitImpls,
|
||||
[] AllLocalTraitImpls,
|
||||
|
||||
// Nodes representing caches. To properly handle a true cache, we
|
||||
// don't use a DepTrackingMap, but rather we push a task node.
|
||||
// Otherwise the write into the map would be incorrectly
|
||||
// attributed to the first task that happened to fill the cache,
|
||||
// which would yield an overly conservative dep-graph.
|
||||
TraitItems(DefId),
|
||||
ReprHints(DefId),
|
||||
[] TraitItems(DefId),
|
||||
[] ReprHints(DefId),
|
||||
|
||||
// Trait selection cache is a little funny. Given a trait
|
||||
// reference like `Foo: SomeTrait<Bar>`, there could be
|
||||
@ -476,35 +495,45 @@ define_dep_nodes!( <'tcx>
|
||||
// imprecision in our dep-graph tracking. The important thing is
|
||||
// that for any given trait-ref, we always map to the **same**
|
||||
// trait-select node.
|
||||
TraitSelect { trait_def_id: DefId, input_def_id: DefId },
|
||||
[] TraitSelect { trait_def_id: DefId, input_def_id: DefId },
|
||||
|
||||
// For proj. cache, we just keep a list of all def-ids, since it is
|
||||
// not a hotspot.
|
||||
ProjectionCache { def_ids: DefIdList },
|
||||
[] ProjectionCache { def_ids: DefIdList },
|
||||
|
||||
ParamEnv(DefId),
|
||||
DescribeDef(DefId),
|
||||
DefSpan(DefId),
|
||||
Stability(DefId),
|
||||
Deprecation(DefId),
|
||||
ItemBodyNestedBodies(DefId),
|
||||
ConstIsRvaluePromotableToStatic(DefId),
|
||||
ImplParent(DefId),
|
||||
TraitOfItem(DefId),
|
||||
IsExportedSymbol(DefId),
|
||||
IsMirAvailable(DefId),
|
||||
ItemAttrs(DefId),
|
||||
FnArgNames(DefId),
|
||||
DylibDepFormats(DefId),
|
||||
IsAllocator(DefId),
|
||||
IsPanicRuntime(DefId),
|
||||
ExternCrate(DefId),
|
||||
[] ParamEnv(DefId),
|
||||
[] DescribeDef(DefId),
|
||||
[] DefSpan(DefId),
|
||||
[] Stability(DefId),
|
||||
[] Deprecation(DefId),
|
||||
[] ItemBodyNestedBodies(DefId),
|
||||
[] ConstIsRvaluePromotableToStatic(DefId),
|
||||
[] ImplParent(DefId),
|
||||
[] TraitOfItem(DefId),
|
||||
[] IsExportedSymbol(DefId),
|
||||
[] IsMirAvailable(DefId),
|
||||
[] ItemAttrs(DefId),
|
||||
[] FnArgNames(DefId),
|
||||
[] DylibDepFormats(DefId),
|
||||
[] IsAllocator(DefId),
|
||||
[] IsPanicRuntime(DefId),
|
||||
[] ExternCrate(DefId),
|
||||
);
|
||||
|
||||
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
|
||||
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
|
||||
const CAN_RECONSTRUCT_QUERY_KEY: bool;
|
||||
fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint;
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String;
|
||||
|
||||
/// This method turns the parameters of a DepNodeConstructor into an opaque
|
||||
/// Fingerprint to be used in DepNode.
|
||||
/// Not all DepNodeParams support being turned into a Fingerprint (they
|
||||
/// don't need to if the corresponding DepNode is anonymous).
|
||||
fn to_fingerprint(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint {
|
||||
panic!("Not implemented. Accidentally called on anonymous node?")
|
||||
}
|
||||
|
||||
fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
|
||||
|
@ -8,9 +8,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ich::Fingerprint;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use std::env;
|
||||
use super::{DepGraphQuery, DepNode};
|
||||
use std::hash::Hash;
|
||||
use std::mem;
|
||||
use super::{DepGraphQuery, DepKind, DepNode};
|
||||
use super::debug::EdgeFilter;
|
||||
|
||||
pub struct DepGraphEdges {
|
||||
@ -44,6 +48,10 @@ enum OpenTask {
|
||||
reads: Vec<DepNode>,
|
||||
read_set: FxHashSet<DepNode>,
|
||||
},
|
||||
Anon {
|
||||
reads: Vec<DepNode>,
|
||||
read_set: FxHashSet<DepNode>,
|
||||
},
|
||||
Ignore,
|
||||
}
|
||||
|
||||
@ -114,6 +122,56 @@ impl DepGraphEdges {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_anon_task(&mut self) {
|
||||
self.task_stack.push(OpenTask::Anon {
|
||||
reads: Vec::new(),
|
||||
read_set: FxHashSet(),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNode {
|
||||
let popped_node = self.task_stack.pop().unwrap();
|
||||
|
||||
if let OpenTask::Anon {
|
||||
read_set: _,
|
||||
reads
|
||||
} = popped_node {
|
||||
let mut fingerprint = Fingerprint::zero();
|
||||
let mut hasher = StableHasher::new();
|
||||
|
||||
for read in reads.iter() {
|
||||
mem::discriminant(&read.kind).hash(&mut hasher);
|
||||
|
||||
// Fingerprint::combine() is faster than sending Fingerprint
|
||||
// through the StableHasher (at least as long as StableHasher
|
||||
// is so slow).
|
||||
fingerprint = fingerprint.combine(read.hash);
|
||||
}
|
||||
|
||||
fingerprint = fingerprint.combine(hasher.finish());
|
||||
|
||||
let target_dep_node = DepNode {
|
||||
kind,
|
||||
hash: fingerprint,
|
||||
};
|
||||
|
||||
if self.indices.contains_key(&target_dep_node) {
|
||||
return target_dep_node;
|
||||
}
|
||||
|
||||
let target_id = self.get_or_create_node(target_dep_node);
|
||||
|
||||
for read in reads.into_iter() {
|
||||
let source_id = self.get_or_create_node(read);
|
||||
self.edges.insert((source_id, target_id));
|
||||
}
|
||||
|
||||
target_dep_node
|
||||
} else {
|
||||
bug!("pop_anon_task() - Expected anonymous task to be popped")
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that the current task `C` reads `v` by adding an
|
||||
/// edge from `v` to `C`. If there is no current task, has no
|
||||
/// effect. Note that *reading* from tracked state is harmless if
|
||||
@ -138,6 +196,14 @@ impl DepGraphEdges {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(&mut OpenTask::Anon {
|
||||
ref mut reads,
|
||||
ref mut read_set,
|
||||
}) => {
|
||||
if read_set.insert(source) {
|
||||
reads.push(source);
|
||||
}
|
||||
}
|
||||
Some(&mut OpenTask::Ignore) | None => {
|
||||
// ignore
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use session::config::OutputType;
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::dep_node::{DepNode, WorkProductId};
|
||||
use super::dep_node::{DepNode, DepKind, WorkProductId};
|
||||
use super::query::DepGraphQuery;
|
||||
use super::raii;
|
||||
use super::safe::DepGraphSafe;
|
||||
@ -115,6 +115,21 @@ impl DepGraph {
|
||||
task(cx, arg)
|
||||
}
|
||||
|
||||
/// Execute something within an "anonymous" task, that is, a task the
|
||||
/// DepNode of which is determined by the list of inputs it read from.
|
||||
pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNode)
|
||||
where OP: FnOnce() -> R
|
||||
{
|
||||
if let Some(ref data) = self.data {
|
||||
data.edges.borrow_mut().push_anon_task();
|
||||
let result = op();
|
||||
let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind);
|
||||
(result, dep_node)
|
||||
} else {
|
||||
(op(), DepNode::new_no_params(DepKind::Krate))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read(&self, v: DepNode) {
|
||||
if let Some(ref data) = self.data {
|
||||
|
Loading…
Reference in New Issue
Block a user