pub struct DepGraphEdges {
nodes: Vec<DepNode>,
- indices: FxHashMap<DepNode, IdIndex>,
- edges: FxHashSet<(IdIndex, IdIndex)>,
+ indices: FxHashMap<DepNode, DepNodeIndex>,
+ edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>,
task_stack: Vec<OpenTask>,
forbidden_edge: Option<EdgeFilter>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-struct IdIndex {
+pub struct DepNodeIndex {
index: u32
}
-impl IdIndex {
- fn new(v: usize) -> IdIndex {
+impl DepNodeIndex {
+
+ pub const INVALID: DepNodeIndex = DepNodeIndex { index: ::std::u32::MAX };
+
+ fn new(v: usize) -> DepNodeIndex {
assert!((v & 0xFFFF_FFFF) == v);
- IdIndex { index: v as u32 }
+ DepNodeIndex { index: v as u32 }
}
fn index(self) -> usize {
}
}
- fn id(&self, index: IdIndex) -> DepNode {
+ fn id(&self, index: DepNodeIndex) -> DepNode {
self.nodes[index.index()]
}
});
}
- pub fn pop_task(&mut self, key: DepNode) {
+ pub fn pop_task(&mut self, key: DepNode) -> DepNodeIndex {
let popped_node = self.task_stack.pop().unwrap();
if let OpenTask::Regular {
let source_id = self.get_or_create_node(read);
self.edges.insert((source_id, target_id));
}
+
+ target_id
} else {
bug!("pop_task() - Expected regular task to be popped")
}
});
}
- pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNode {
+ pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex {
let popped_node = self.task_stack.pop().unwrap();
if let OpenTask::Anon {
hash: fingerprint,
};
- if self.indices.contains_key(&target_dep_node) {
- return target_dep_node;
+ if let Some(&index) = self.indices.get(&target_dep_node) {
+ return index;
}
let target_id = self.get_or_create_node(target_dep_node);
self.edges.insert((source_id, target_id));
}
- target_dep_node
+ target_id
} else {
bug!("pop_anon_task() - Expected anonymous task to be popped")
}
}
}
+ pub fn read_index(&mut self, source: DepNodeIndex) {
+ let dep_node = self.nodes[source.index()];
+ self.read(dep_node);
+ }
+
pub fn query(&self) -> DepGraphQuery {
let edges: Vec<_> = self.edges.iter()
.map(|&(i, j)| (self.id(i), self.id(j)))
}
#[inline]
- fn get_or_create_node(&mut self, dep_node: DepNode) -> IdIndex {
+ fn get_or_create_node(&mut self, dep_node: DepNode) -> DepNodeIndex {
let DepGraphEdges {
ref mut indices,
ref mut nodes,
*indices.entry(dep_node).or_insert_with(|| {
let next_id = nodes.len();
nodes.push(dep_node);
- IdIndex::new(next_id)
+ DepNodeIndex::new(next_id)
})
}
}
use super::query::DepGraphQuery;
use super::raii;
use super::safe::DepGraphSafe;
-use super::edges::DepGraphEdges;
+use super::edges::{DepGraphEdges, DepNodeIndex};
#[derive(Clone)]
pub struct DepGraph {
/// `arg` parameter.
///
/// [README]: README.md
- pub fn with_task<C, A, R>(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> R
- where C: DepGraphSafe, A: DepGraphSafe
+ pub fn with_task<C, A, R>(&self,
+ key: DepNode,
+ cx: C,
+ arg: A,
+ task: fn(C, A) -> R)
+ -> (R, DepNodeIndex)
+ where C: DepGraphSafe
{
- let _task = self.in_task(key);
- task(cx, arg)
+ if let Some(ref data) = self.data {
+ data.edges.borrow_mut().push_task(key);
+ let result = task(cx, arg);
+ let dep_node_index = data.edges.borrow_mut().pop_task(key);
+ (result, dep_node_index)
+ } else {
+ (task(cx, arg), DepNodeIndex::INVALID)
+ }
}
/// 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)
+ pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex)
where OP: FnOnce() -> R
{
if let Some(ref data) = self.data {
let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind);
(result, dep_node)
} else {
- (op(), DepNode::new_no_params(DepKind::Krate))
+ (op(), DepNodeIndex::INVALID)
}
}
}
}
+ #[inline]
+ pub fn read_index(&self, v: DepNodeIndex) {
+ if let Some(ref data) = self.data {
+ data.edges.borrow_mut().read_index(v);
+ }
+ }
+
/// Only to be used during graph loading
#[inline]
pub fn add_edge_directly(&self, source: DepNode, target: DepNode) {
pub use self::dep_node::WorkProductId;
pub use self::graph::DepGraph;
pub use self::graph::WorkProduct;
+pub use self::edges::DepNodeIndex;
pub use self::query::DepGraphQuery;
pub use self::safe::AssertDepGraphSafe;
pub use self::safe::DepGraphSafe;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use dep_graph::{DepConstructor, DepNode};
+use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use hir::def::Def;
use hir;
struct QueryMap<D: QueryDescription> {
phantom: PhantomData<D>,
- map: FxHashMap<D::Key, D::Value>,
+ map: FxHashMap<D::Key, (D::Value, DepNodeIndex)>,
}
impl<M: QueryDescription> QueryMap<M> {
key,
span);
- if let Some(result) = tcx.maps.$name.borrow().map.get(&key) {
+ if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) {
+ tcx.dep_graph.read_index(dep_node_index);
return Ok(f(result));
}
span = key.default_span(tcx)
}
- let _task = tcx.dep_graph.in_task(Self::to_dep_node(tcx, &key));
-
- let result = tcx.cycle_check(span, Query::$name(key), || {
- let provider = tcx.maps.providers[key.map_crate()].$name;
- provider(tcx.global_tcx(), key)
+ let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || {
+ let dep_node = Self::to_dep_node(tcx, &key);
+
+ if dep_node.kind.is_anon() {
+ tcx.dep_graph.with_anon_task(dep_node.kind, || {
+ let provider = tcx.maps.providers[key.map_crate()].$name;
+ provider(tcx.global_tcx(), key)
+ })
+ } else {
+ fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
+ key: $K)
+ -> $V {
+ let provider = tcx.maps.providers[key.map_crate()].$name;
+ provider(tcx.global_tcx(), key)
+ }
+
+ tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
+ }
})?;
- Ok(f(tcx.maps.$name.borrow_mut().map.entry(key).or_insert(result)))
+ tcx.dep_graph.read_index(dep_node_index);
+
+ Ok(f(&tcx.maps
+ .$name
+ .borrow_mut()
+ .map
+ .entry(key)
+ .or_insert((result, dep_node_index))
+ .0))
}
pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-> Result<$V, CycleError<'a, $tcx>> {
- // We register the `read` here, but not in `force`, since
- // `force` does not give access to the value produced (and thus
- // we actually don't read it).
- tcx.dep_graph.read(Self::to_dep_node(tcx, &key));
Self::try_get_with(tcx, span, key, Clone::clone)
}
pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
+ // Ignore dependencies, since we not reading the computed value
+ let _task = tcx.dep_graph.in_ignore();
+
match Self::try_get_with(tcx, span, key, |_| ()) {
Ok(()) => {}
Err(e) => tcx.report_cycle(e)
.into_iter()
.map(|cgu| {
let dep_node = cgu.work_product_dep_node();
- let (stats, module) =
+ let ((stats, module), _) =
tcx.dep_graph.with_task(dep_node,
AssertDepGraphSafe(&shared_ccx),
AssertDepGraphSafe(cgu),