mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
incr.comp.: Cache DepNodes with corresponding query results.
This commit is contained in:
parent
0363a23c35
commit
6d049fb5bb
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user