提交 fecd92a7 编写于 作者: M Michael Woerister

incr.comp.: Initial implemenation of append-only dep-graph.

上级 a83c3e77
......@@ -17,7 +17,7 @@
use super::{DepGraphQuery, DepKind, DepNode};
use super::debug::EdgeFilter;
pub struct DepGraphEdges {
pub(super) struct DepGraphEdges {
nodes: Vec<DepNode>,
indices: FxHashMap<DepNode, DepNodeIndex>,
edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>,
......@@ -31,8 +31,8 @@ pub struct DepGraphEdges {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct DepNodeIndex {
index: u32
pub(super) struct DepNodeIndex {
index: u32,
}
impl DepNodeIndex {
......
......@@ -8,11 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHashingContextProvider};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use session::config::OutputType;
use std::cell::{Ref, RefCell};
use std::hash::Hash;
use std::rc::Rc;
use util::common::{ProfileQueriesMsg, profq_msg};
......@@ -22,7 +24,7 @@
use super::query::DepGraphQuery;
use super::raii;
use super::safe::DepGraphSafe;
use super::edges::{DepGraphEdges, DepNodeIndex};
use super::edges::{self, DepGraphEdges};
#[derive(Clone)]
pub struct DepGraph {
......@@ -38,10 +40,34 @@ pub struct DepGraph {
fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>>
}
/// As a temporary measure, while transitioning to the new DepGraph
/// implementation, we maintain the old and the new dep-graph encoding in
/// parallel, so a DepNodeIndex actually contains two indices, one for each
/// version.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct DepNodeIndex {
legacy: edges::DepNodeIndex,
new: DepNodeIndexNew,
}
impl DepNodeIndex {
pub const INVALID: DepNodeIndex = DepNodeIndex {
legacy: edges::DepNodeIndex::INVALID,
new: DepNodeIndexNew::INVALID,
};
}
struct DepGraphData {
/// The actual graph data.
/// The old, initial encoding of the dependency graph. This will soon go
/// away.
edges: RefCell<DepGraphEdges>,
/// The new encoding of the dependency graph, optimized for red/green
/// tracking. The `current` field is the dependency graph of only the
/// current compilation session: We don't merge the previous dep-graph into
/// current one anymore.
current: RefCell<CurrentDepGraph>,
/// When we load, there may be `.o` files, cached mir, or other such
/// things available to us. If we find that they are not dirty, we
/// load the path to the file storing those work-products here into
......@@ -63,6 +89,7 @@ pub fn new(enabled: bool) -> DepGraph {
work_products: RefCell::new(FxHashMap()),
edges: RefCell::new(DepGraphEdges::new()),
dep_node_debug: RefCell::new(FxHashMap()),
current: RefCell::new(CurrentDepGraph::new()),
}))
} else {
None
......@@ -82,7 +109,8 @@ pub fn query(&self) -> DepGraphQuery {
}
pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> {
self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges))
self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges,
&data.current))
}
pub fn with_ignore<OP,R>(&self, op: OP) -> R
......@@ -130,6 +158,7 @@ pub fn with_task<C, A, R, HCX>(&self,
{
if let Some(ref data) = self.data {
data.edges.borrow_mut().push_task(key);
data.current.borrow_mut().push_task(key);
if cfg!(debug_assertions) {
profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
};
......@@ -145,7 +174,9 @@ pub fn with_task<C, A, R, HCX>(&self,
if cfg!(debug_assertions) {
profq_msg(ProfileQueriesMsg::TaskEnd)
};
let dep_node_index = data.edges.borrow_mut().pop_task(key);
let dep_node_index_legacy = data.edges.borrow_mut().pop_task(key);
let dep_node_index_new = data.current.borrow_mut().pop_task(key);
let mut stable_hasher = StableHasher::new();
result.hash_stable(&mut hcx, &mut stable_hasher);
......@@ -155,7 +186,10 @@ pub fn with_task<C, A, R, HCX>(&self,
.insert(key, stable_hasher.finish())
.is_none());
(result, dep_node_index)
(result, DepNodeIndex {
legacy: dep_node_index_legacy,
new: dep_node_index_new,
})
} else {
if key.kind.fingerprint_needed_for_crate_hash() {
let mut hcx = cx.create_stable_hashing_context();
......@@ -180,9 +214,14 @@ pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeInde
{
if let Some(ref data) = self.data {
data.edges.borrow_mut().push_anon_task();
data.current.borrow_mut().push_anon_task();
let result = op();
let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind);
(result, dep_node)
let dep_node_index_legacy = data.edges.borrow_mut().pop_anon_task(dep_kind);
let dep_node_index_new = data.current.borrow_mut().pop_anon_task(dep_kind);
(result, DepNodeIndex {
legacy: dep_node_index_legacy,
new: dep_node_index_new,
})
} else {
(op(), DepNodeIndex::INVALID)
}
......@@ -192,13 +231,15 @@ pub fn with_anon_task<OP,R>(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeInde
pub fn read(&self, v: DepNode) {
if let Some(ref data) = self.data {
data.edges.borrow_mut().read(v);
data.current.borrow_mut().read(v);
}
}
#[inline]
pub fn read_index(&self, v: DepNodeIndex) {
if let Some(ref data) = self.data {
data.edges.borrow_mut().read_index(v);
data.edges.borrow_mut().read_index(v.legacy);
data.current.borrow_mut().read_index(v.new);
}
}
......@@ -215,7 +256,13 @@ pub fn add_node_directly(&self, node: DepNode) {
pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
if let Some(ref data) = self.data {
data.edges.borrow_mut().add_node(node)
let dep_node_index_legacy = data.edges.borrow_mut().add_node(node);
let dep_node_index_new = data.current.borrow_mut()
.alloc_node(node, Vec::new());
DepNodeIndex {
legacy: dep_node_index_legacy,
new: dep_node_index_new,
}
} else {
DepNodeIndex::INVALID
}
......@@ -335,3 +382,208 @@ pub struct WorkProduct {
/// Saved files associated with this CGU
pub saved_files: Vec<(OutputType, String)>,
}
pub(super) struct CurrentDepGraph {
nodes: IndexVec<DepNodeIndexNew, DepNode>,
edges: IndexVec<DepNodeIndexNew, Vec<DepNodeIndexNew>>,
node_to_node_index: FxHashMap<DepNode, DepNodeIndexNew>,
task_stack: Vec<OpenTask>,
}
impl CurrentDepGraph {
fn new() -> CurrentDepGraph {
CurrentDepGraph {
nodes: IndexVec::new(),
edges: IndexVec::new(),
node_to_node_index: FxHashMap(),
task_stack: Vec::new(),
}
}
pub(super) fn push_ignore(&mut self) {
self.task_stack.push(OpenTask::Ignore);
}
pub(super) fn pop_ignore(&mut self) {
let popped_node = self.task_stack.pop().unwrap();
debug_assert_eq!(popped_node, OpenTask::Ignore);
}
pub(super) fn push_task(&mut self, key: DepNode) {
self.task_stack.push(OpenTask::Regular {
node: key,
reads: Vec::new(),
read_set: FxHashSet(),
});
}
pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndexNew {
let popped_node = self.task_stack.pop().unwrap();
if let OpenTask::Regular {
node,
read_set: _,
reads
} = popped_node {
debug_assert_eq!(node, key);
self.alloc_node(node, reads)
} else {
bug!("pop_task() - Expected regular task to be popped")
}
}
fn push_anon_task(&mut self) {
self.task_stack.push(OpenTask::Anon {
reads: Vec::new(),
read_set: FxHashSet(),
});
}
fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew {
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() {
let read_dep_node = self.nodes[read];
::std::mem::discriminant(&read_dep_node.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_dep_node.hash);
}
fingerprint = fingerprint.combine(hasher.finish());
let target_dep_node = DepNode {
kind,
hash: fingerprint,
};
if let Some(&index) = self.node_to_node_index.get(&target_dep_node) {
return index;
}
self.alloc_node(target_dep_node, reads)
} else {
bug!("pop_anon_task() - Expected anonymous task to be popped")
}
}
fn read(&mut self, source: DepNode) {
let dep_node_index = self.maybe_alloc_node(source);
self.read_index(dep_node_index);
}
fn read_index(&mut self, source: DepNodeIndexNew) {
match self.task_stack.last_mut() {
Some(&mut OpenTask::Regular {
ref mut reads,
ref mut read_set,
node: _,
}) => {
if read_set.insert(source) {
reads.push(source);
}
}
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
}
}
}
fn alloc_node(&mut self,
dep_node: DepNode,
edges: Vec<DepNodeIndexNew>)
-> DepNodeIndexNew {
debug_assert_eq!(self.edges.len(), self.nodes.len());
debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
let dep_node_index = DepNodeIndexNew::new(self.nodes.len());
self.nodes.push(dep_node);
self.node_to_node_index.insert(dep_node, dep_node_index);
self.edges.push(edges);
dep_node_index
}
fn maybe_alloc_node(&mut self,
dep_node: DepNode)
-> DepNodeIndexNew {
debug_assert_eq!(self.edges.len(), self.nodes.len());
debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
let CurrentDepGraph {
ref mut node_to_node_index,
ref mut nodes,
ref mut edges,
..
} = *self;
*node_to_node_index.entry(dep_node).or_insert_with(|| {
let next_id = nodes.len();
nodes.push(dep_node);
edges.push(Vec::new());
DepNodeIndexNew::new(next_id)
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub(super) struct DepNodeIndexNew {
index: u32,
}
impl Idx for DepNodeIndexNew {
fn new(idx: usize) -> Self {
DepNodeIndexNew::new(idx)
}
fn index(self) -> usize {
self.index()
}
}
impl DepNodeIndexNew {
const INVALID: DepNodeIndexNew = DepNodeIndexNew {
index: ::std::u32::MAX,
};
fn new(v: usize) -> DepNodeIndexNew {
assert!((v & 0xFFFF_FFFF) == v);
DepNodeIndexNew { index: v as u32 }
}
fn index(self) -> usize {
self.index as usize
}
}
#[derive(Clone, Debug, PartialEq)]
enum OpenTask {
Regular {
node: DepNode,
reads: Vec<DepNodeIndexNew>,
read_set: FxHashSet<DepNodeIndexNew>,
},
Anon {
reads: Vec<DepNodeIndexNew>,
read_set: FxHashSet<DepNodeIndexNew>,
},
Ignore,
}
......@@ -22,10 +22,9 @@
pub use self::dep_node::WorkProductId;
pub use self::graph::DepGraph;
pub use self::graph::WorkProduct;
pub use self::edges::DepNodeIndex;
pub use self::graph::DepNodeIndex;
pub use self::query::DepGraphQuery;
pub use self::safe::AssertDepGraphSafe;
pub use self::safe::DepGraphSafe;
pub use self::raii::DepTask;
pub use self::dep_node::{DepKind, DepConstructor};
......@@ -8,50 +8,33 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::DepNode;
use super::edges::DepGraphEdges;
use super::graph::CurrentDepGraph;
use std::cell::RefCell;
pub struct DepTask<'graph> {
graph: &'graph RefCell<DepGraphEdges>,
key: DepNode,
}
impl<'graph> DepTask<'graph> {
pub fn new(graph: &'graph RefCell<DepGraphEdges>,
key: DepNode)
-> DepTask<'graph> {
graph.borrow_mut().push_task(key);
DepTask {
graph,
key,
}
}
}
impl<'graph> Drop for DepTask<'graph> {
fn drop(&mut self) {
self.graph.borrow_mut().pop_task(self.key);
}
}
pub struct IgnoreTask<'graph> {
graph: &'graph RefCell<DepGraphEdges>,
legacy_graph: &'graph RefCell<DepGraphEdges>,
new_graph: &'graph RefCell<CurrentDepGraph>,
}
impl<'graph> IgnoreTask<'graph> {
pub fn new(graph: &'graph RefCell<DepGraphEdges>) -> IgnoreTask<'graph> {
graph.borrow_mut().push_ignore();
pub(super) fn new(legacy_graph: &'graph RefCell<DepGraphEdges>,
new_graph: &'graph RefCell<CurrentDepGraph>)
-> IgnoreTask<'graph> {
legacy_graph.borrow_mut().push_ignore();
new_graph.borrow_mut().push_ignore();
IgnoreTask {
graph
legacy_graph,
new_graph,
}
}
}
impl<'graph> Drop for IgnoreTask<'graph> {
fn drop(&mut self) {
self.graph.borrow_mut().pop_ignore();
self.legacy_graph.borrow_mut().pop_ignore();
self.new_graph.borrow_mut().pop_ignore();
}
}
......@@ -88,6 +88,15 @@ pub(super) fn root(krate: &'hir Crate,
).1;
}
{
dep_graph.with_task(
DepNode::new_no_params(DepKind::AllLocalTraitImpls),
&hcx,
&krate.trait_impls,
identity_fn
);
}
let hir_body_nodes = vec![root_mod_def_path_hash];
let mut collector = NodeCollector {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册