incr.comp.: Cache DepNodes with corresponding query results.

This commit is contained in:
Michael Woerister 2017-07-04 17:33:43 +02:00
parent 0363a23c35
commit 6d049fb5bb
5 changed files with 84 additions and 34 deletions

View File

@ -19,21 +19,24 @@ use super::debug::EdgeFilter;
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 {
@ -80,7 +83,7 @@ impl DepGraphEdges {
}
}
fn id(&self, index: IdIndex) -> DepNode {
fn id(&self, index: DepNodeIndex) -> DepNode {
self.nodes[index.index()]
}
@ -101,7 +104,7 @@ impl DepGraphEdges {
});
}
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 {
@ -117,6 +120,8 @@ impl DepGraphEdges {
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")
}
@ -129,7 +134,7 @@ impl DepGraphEdges {
});
}
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 {
@ -155,8 +160,8 @@ impl DepGraphEdges {
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);
@ -166,7 +171,7 @@ impl DepGraphEdges {
self.edges.insert((source_id, target_id));
}
target_dep_node
target_id
} else {
bug!("pop_anon_task() - Expected anonymous task to be popped")
}
@ -210,6 +215,11 @@ impl DepGraphEdges {
}
}
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)))
@ -229,7 +239,7 @@ impl DepGraphEdges {
}
#[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,
@ -239,7 +249,7 @@ impl DepGraphEdges {
*indices.entry(dep_node).or_insert_with(|| {
let next_id = nodes.len();
nodes.push(dep_node);
IdIndex::new(next_id)
DepNodeIndex::new(next_id)
})
}
}

View File

@ -17,7 +17,7 @@ use super::dep_node::{DepNode, DepKind, WorkProductId};
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 {
@ -108,16 +108,27 @@ impl 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 {
@ -126,7 +137,7 @@ impl DepGraph {
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)
}
}
@ -137,6 +148,13 @@ impl DepGraph {
}
}
#[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) {

View File

@ -22,6 +22,7 @@ pub use self::dep_node::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;

View File

@ -8,7 +8,7 @@
// 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;
@ -186,7 +186,7 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
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> {
@ -580,7 +580,8 @@ macro_rules! define_maps {
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));
}
@ -591,26 +592,46 @@ macro_rules! define_maps {
span = key.default_span(tcx)
}
let _task = tcx.dep_graph.in_task(Self::to_dep_node(tcx, &key));
let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || {
let dep_node = 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)
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)

View File

@ -1120,7 +1120,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.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),