From: Michael Woerister Date: Tue, 4 Jul 2017 15:33:43 +0000 (+0200) Subject: incr.comp.: Cache DepNodes with corresponding query results. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=6d049fb5bb3661771f7f30c8cda058a1778d1fa2;p=rust.git incr.comp.: Cache DepNodes with corresponding query results. --- diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index e67d65841d5..277b69262c9 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -19,21 +19,24 @@ pub struct DepGraphEdges { nodes: Vec, - indices: FxHashMap, - edges: FxHashSet<(IdIndex, IdIndex)>, + indices: FxHashMap, + edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>, task_stack: Vec, forbidden_edge: Option, } #[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 @@ pub fn new() -> DepGraphEdges { } } - fn id(&self, index: IdIndex) -> DepNode { + fn id(&self, index: DepNodeIndex) -> DepNode { self.nodes[index.index()] } @@ -101,7 +104,7 @@ pub fn push_task(&mut self, key: DepNode) { }); } - 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 @@ pub fn pop_task(&mut self, key: DepNode) { 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 @@ pub fn push_anon_task(&mut self) { }); } - 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 @@ pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNode { 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 @@ pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNode { 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 @@ pub fn read(&mut self, source: DepNode) { } } + 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 @@ pub fn add_node(&mut self, node: DepNode) { } #[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 @@ fn get_or_create_node(&mut self, dep_node: DepNode) -> IdIndex { *indices.entry(dep_node).or_insert_with(|| { let next_id = nodes.len(); nodes.push(dep_node); - IdIndex::new(next_id) + DepNodeIndex::new(next_id) }) } } diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 295b402c533..de8b7ddb6ca 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -17,7 +17,7 @@ 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 @@ pub fn with_ignore(&self, op: OP) -> R /// `arg` parameter. /// /// [README]: README.md - pub fn with_task(&self, key: DepNode, cx: C, arg: A, task: fn(C, A) -> R) -> R - where C: DepGraphSafe, A: DepGraphSafe + pub fn with_task(&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(&self, dep_kind: DepKind, op: OP) -> (R, DepNode) + pub fn with_anon_task(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeIndex) where OP: FnOnce() -> R { if let Some(ref data) = self.data { @@ -126,7 +137,7 @@ pub fn with_anon_task(&self, dep_kind: DepKind, op: OP) -> (R, DepNode) 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 @@ pub fn read(&self, v: DepNode) { } } + #[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) { diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index df8c3ba4ac8..ac0c88ced93 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -22,6 +22,7 @@ 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; diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 5280901b8c5..e94308f3510 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -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 @@ fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self { struct QueryMap { phantom: PhantomData, - map: FxHashMap, + map: FxHashMap, } impl QueryMap { @@ -580,7 +580,8 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, 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 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, 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) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 8298324e996..9feccc13372 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -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),