From df06a7e532a56916ec357506df1eed3a6d6435ea Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 28 Sep 2017 16:19:10 +0200 Subject: [PATCH] incr.comp.: Remove legacy dep-graph runtime. --- src/librustc/dep_graph/edges.rs | 255 --------------------------- src/librustc/dep_graph/graph.rs | 195 ++++++++------------ src/librustc/dep_graph/mod.rs | 1 - src/librustc/dep_graph/raii.rs | 17 +- src/librustc/dep_graph/serialized.rs | 5 +- 5 files changed, 87 insertions(+), 386 deletions(-) delete mode 100644 src/librustc/dep_graph/edges.rs diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs deleted file mode 100644 index 241bec39256..00000000000 --- a/src/librustc/dep_graph/edges.rs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use ich::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::StableHasher; -use std::env; -use std::hash::Hash; -use std::mem; -use super::{DepKind, DepNode}; -use super::debug::EdgeFilter; - -pub(super) struct DepGraphEdges { - nodes: Vec, - indices: FxHashMap, - edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>, - task_stack: Vec, - forbidden_edge: Option, - - // A set to help assert that no two tasks use the same DepNode. This is a - // temporary measure. Once we load the previous dep-graph as readonly, this - // check will fall out of the graph implementation naturally. - opened_once: FxHashSet, -} - -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub(super) struct DepNodeIndex { - index: u32, -} - -impl DepNodeIndex { - - pub const INVALID: DepNodeIndex = DepNodeIndex { index: ::std::u32::MAX }; - - fn new(v: usize) -> DepNodeIndex { - assert!((v & 0xFFFF_FFFF) == v); - DepNodeIndex { index: v as u32 } - } - - fn index(self) -> usize { - self.index as usize - } -} - -#[derive(Clone, Debug, PartialEq)] -enum OpenTask { - Regular { - node: DepNode, - reads: Vec, - read_set: FxHashSet, - }, - Anon { - reads: Vec, - read_set: FxHashSet, - }, - Ignore, -} - -impl DepGraphEdges { - pub fn new() -> DepGraphEdges { - let forbidden_edge = if cfg!(debug_assertions) { - match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { - Ok(s) => { - match EdgeFilter::new(&s) { - Ok(f) => Some(f), - Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), - } - } - Err(_) => None, - } - } else { - None - }; - - DepGraphEdges { - nodes: vec![], - indices: FxHashMap(), - edges: FxHashSet(), - task_stack: Vec::new(), - forbidden_edge, - opened_once: FxHashSet(), - } - } - - pub fn push_ignore(&mut self) { - self.task_stack.push(OpenTask::Ignore); - } - - pub fn pop_ignore(&mut self) { - let popped_node = self.task_stack.pop().unwrap(); - debug_assert_eq!(popped_node, OpenTask::Ignore); - } - - pub fn push_task(&mut self, key: DepNode) { - if !self.opened_once.insert(key) { - bug!("Re-opened node {:?}", key) - } - - self.task_stack.push(OpenTask::Regular { - node: key, - reads: Vec::new(), - read_set: FxHashSet(), - }); - } - - pub fn pop_task(&mut self, key: DepNode) -> DepNodeIndex { - let popped_node = self.task_stack.pop().unwrap(); - - if let OpenTask::Regular { - node, - read_set: _, - reads - } = popped_node { - debug_assert_eq!(node, key); - debug_assert!(!node.kind.is_input() || reads.is_empty()); - - let target_id = self.get_or_create_node(node); - - for read in reads.into_iter() { - 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 push_anon_task(&mut self) { - self.task_stack.push(OpenTask::Anon { - reads: Vec::new(), - read_set: FxHashSet(), - }); - } - - pub fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex { - 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() { - mem::discriminant(&read.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.hash); - } - - fingerprint = fingerprint.combine(hasher.finish()); - - let target_dep_node = DepNode { - kind, - hash: fingerprint, - }; - - if let Some(&index) = self.indices.get(&target_dep_node) { - return index; - } - - let target_id = self.get_or_create_node(target_dep_node); - - for read in reads.into_iter() { - let source_id = self.get_or_create_node(read); - self.edges.insert((source_id, target_id)); - } - - target_id - } else { - bug!("pop_anon_task() - Expected anonymous task to be popped") - } - } - - /// Indicates that the current task `C` reads `v` by adding an - /// edge from `v` to `C`. If there is no current task, has no - /// effect. Note that *reading* from tracked state is harmless if - /// you are not in a task; what is bad is *writing* to tracked - /// state (and leaking data that you read into a tracked task). - pub fn read(&mut self, source: DepNode) { - match self.task_stack.last_mut() { - Some(&mut OpenTask::Regular { - node: target, - ref mut reads, - ref mut read_set, - }) => { - if read_set.insert(source) { - reads.push(source); - - if cfg!(debug_assertions) { - if let Some(ref forbidden_edge) = self.forbidden_edge { - if forbidden_edge.test(&source, &target) { - bug!("forbidden edge {:?} -> {:?} created", source, target) - } - } - } - } - } - 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 - } - } - } - - pub fn read_index(&mut self, source: DepNodeIndex) { - let dep_node = self.nodes[source.index()]; - self.read(dep_node); - } - - #[inline] - pub fn add_edge(&mut self, source: DepNode, target: DepNode) { - let source = self.get_or_create_node(source); - let target = self.get_or_create_node(target); - self.edges.insert((source, target)); - } - - pub fn add_node(&mut self, node: DepNode) -> DepNodeIndex { - self.get_or_create_node(node) - } - - #[inline] - fn get_or_create_node(&mut self, dep_node: DepNode) -> DepNodeIndex { - let DepGraphEdges { - ref mut indices, - ref mut nodes, - .. - } = *self; - - *indices.entry(dep_node).or_insert_with(|| { - let next_id = nodes.len(); - nodes.push(dep_node); - DepNodeIndex::new(next_id) - }) - } -} diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 56697e9fa05..e7207ca6086 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -14,6 +14,7 @@ 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::env; use std::hash::Hash; use std::rc::Rc; use ty::TyCtxt; @@ -21,15 +22,14 @@ use util::common::{ProfileQueriesMsg, profq_msg}; use ich::Fingerprint; +use super::debug::EdgeFilter; use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::query::DepGraphQuery; use super::raii; use super::safe::DepGraphSafe; -use super::edges::{self, DepGraphEdges}; use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex}; use super::prev::PreviousDepGraph; - #[derive(Clone)] pub struct DepGraph { data: Option>, @@ -44,20 +44,25 @@ pub struct DepGraph { fingerprints: Rc>> } -/// 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, + index: u32, +} + +impl Idx for DepNodeIndex { + fn new(idx: usize) -> Self { + assert!((idx & 0xFFFF_FFFF) == idx); + DepNodeIndex { index: idx as u32 } + } + fn index(self) -> usize { + self.index as usize + } } impl DepNodeIndex { - pub const INVALID: DepNodeIndex = DepNodeIndex { - legacy: edges::DepNodeIndex::INVALID, - new: DepNodeIndexNew::INVALID, + const INVALID: DepNodeIndex = DepNodeIndex { + index: ::std::u32::MAX, }; } @@ -77,10 +82,6 @@ impl DepNodeColor { } struct DepGraphData { - /// The old, initial encoding of the dependency graph. This will soon go - /// away. - edges: RefCell, - /// 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 @@ -105,7 +106,7 @@ struct DepGraphData { dep_node_debug: RefCell>, // Used for testing, only populated when -Zquery-dep-graph is specified. - loaded_from_cache: RefCell>, + loaded_from_cache: RefCell>, } impl DepGraph { @@ -115,7 +116,6 @@ impl DepGraph { data: Some(Rc::new(DepGraphData { previous_work_products: RefCell::new(FxHashMap()), work_products: RefCell::new(FxHashMap()), - edges: RefCell::new(DepGraphEdges::new()), dep_node_debug: RefCell::new(FxHashMap()), current: RefCell::new(CurrentDepGraph::new()), previous: prev_graph, @@ -155,8 +155,7 @@ impl DepGraph { } pub fn in_ignore<'graph>(&'graph self) -> Option> { - self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges, - &data.current)) + self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.current)) } pub fn with_ignore(&self, op: OP) -> R @@ -205,7 +204,6 @@ impl DepGraph { if let Some(ref data) = self.data { debug_assert!(!data.colors.borrow().contains_key(&key)); - data.edges.borrow_mut().push_task(key); data.current.borrow_mut().push_task(key); if cfg!(debug_assertions) { profq_msg(ProfileQueriesMsg::TaskBegin(key.clone())) @@ -223,8 +221,7 @@ impl DepGraph { profq_msg(ProfileQueriesMsg::TaskEnd) }; - 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 dep_node_index = data.current.borrow_mut().pop_task(key); let mut stable_hasher = StableHasher::new(); result.hash_stable(&mut hcx, &mut stable_hasher); @@ -239,20 +236,14 @@ impl DepGraph { let prev_fingerprint = data.previous.fingerprint_of(&key); let color = if Some(current_fingerprint) == prev_fingerprint { - DepNodeColor::Green(DepNodeIndex { - legacy: dep_node_index_legacy, - new: dep_node_index_new, - }) + DepNodeColor::Green(dep_node_index) } else { DepNodeColor::Red }; assert!(data.colors.borrow_mut().insert(key, color).is_none()); - (result, DepNodeIndex { - legacy: dep_node_index_legacy, - new: dep_node_index_new, - }) + (result, dep_node_index) } else { if key.kind.fingerprint_needed_for_crate_hash() { let mut hcx = cx.create_stable_hashing_context(); @@ -276,17 +267,12 @@ impl DepGraph { where OP: FnOnce() -> R { 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_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, - }) + let dep_node_index = data.current + .borrow_mut() + .pop_anon_task(dep_kind); + (result, dep_node_index) } else { (op(), DepNodeIndex::INVALID) } @@ -295,11 +281,9 @@ impl DepGraph { #[inline] pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { - data.edges.borrow_mut().read(v); - let mut current = data.current.borrow_mut(); - if let Some(&dep_node_index_new) = current.node_to_node_index.get(&v) { - current.read_index(dep_node_index_new); + if let Some(&dep_node_index) = current.node_to_node_index.get(&v) { + current.read_index(dep_node_index); } else { bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind) } @@ -307,24 +291,12 @@ impl DepGraph { } #[inline] - pub fn read_index(&self, v: DepNodeIndex) { + pub fn read_index(&self, dep_node_index: DepNodeIndex) { if let Some(ref data) = self.data { - data.edges.borrow_mut().read_index(v.legacy); - data.current.borrow_mut().read_index(v.new); + data.current.borrow_mut().read_index(dep_node_index); } } - /// Only to be used during graph loading - #[inline] - pub fn add_edge_directly(&self, source: DepNode, target: DepNode) { - self.data.as_ref().unwrap().edges.borrow_mut().add_edge(source, target); - } - - /// Only to be used during graph loading - pub fn add_node_directly(&self, node: DepNode) { - self.data.as_ref().unwrap().edges.borrow_mut().add_node(node); - } - pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint { self.fingerprints.borrow()[dep_node] } @@ -567,18 +539,9 @@ impl DepGraph { // ... allocating an entry for it in the current dependency graph and // adding all the appropriate edges imported from the previous graph ... - let node_index_new = data.current + let dep_node_index = data.current .borrow_mut() - .alloc_node(*dep_node, - current_deps.iter().map(|n| n.new).collect()); - let dep_node_index_legacy = { - let mut legacy_graph = data.edges.borrow_mut(); - legacy_graph.push_task(*dep_node); - for node_index in current_deps.into_iter().map(|n| n.legacy) { - legacy_graph.read_index(node_index); - } - legacy_graph.pop_task(*dep_node) - }; + .alloc_node(*dep_node, current_deps); // ... copying the fingerprint from the previous graph too, so we don't // have to recompute it ... @@ -588,24 +551,19 @@ impl DepGraph { .insert(*dep_node, fingerprint) .is_none()); - let node_index = DepNodeIndex { - legacy: dep_node_index_legacy, - new: node_index_new, - }; - // ... and finally storing a "Green" entry in the color map. assert!(data.colors .borrow_mut() - .insert(*dep_node, DepNodeColor::Green(node_index)) + .insert(*dep_node, DepNodeColor::Green(dep_node_index)) .is_none()); debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node.kind); - Some(node_index) + Some(dep_node_index) } // Used in various assertions pub fn is_green(&self, dep_node_index: DepNodeIndex) -> bool { - let dep_node = self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index.new]; + let dep_node = self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index]; self.data.as_ref().unwrap().colors.borrow().get(&dep_node).map(|&color| { match color { DepNodeColor::Red => false, @@ -614,9 +572,9 @@ impl DepGraph { }).unwrap_or(false) } - pub fn mark_loaded_from_cache(&self, dep_node: DepNodeIndex, state: bool) { + pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) { debug!("mark_loaded_from_cache({:?}, {})", - self.data.as_ref().unwrap().current.borrow().nodes[dep_node.new], + self.data.as_ref().unwrap().current.borrow().nodes[dep_node_index], state); self.data @@ -624,7 +582,7 @@ impl DepGraph { .unwrap() .loaded_from_cache .borrow_mut() - .insert(dep_node.new, state); + .insert(dep_node_index, state); } pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option { @@ -673,13 +631,12 @@ pub struct WorkProduct { } pub(super) struct CurrentDepGraph { - nodes: IndexVec, - edges: IndexVec>, - node_to_node_index: FxHashMap, - + nodes: IndexVec, + edges: IndexVec>, + node_to_node_index: FxHashMap, anon_id_seed: Fingerprint, - task_stack: Vec, + forbidden_edge: Option, } impl CurrentDepGraph { @@ -692,12 +649,27 @@ impl CurrentDepGraph { let mut stable_hasher = StableHasher::new(); nanos.hash(&mut stable_hasher); + let forbidden_edge = if cfg!(debug_assertions) { + match env::var("RUST_FORBID_DEP_GRAPH_EDGE") { + Ok(s) => { + match EdgeFilter::new(&s) { + Ok(f) => Some(f), + Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err), + } + } + Err(_) => None, + } + } else { + None + }; + CurrentDepGraph { nodes: IndexVec::new(), edges: IndexVec::new(), node_to_node_index: FxHashMap(), anon_id_seed: stable_hasher.finish(), task_stack: Vec::new(), + forbidden_edge, } } @@ -718,7 +690,7 @@ impl CurrentDepGraph { }); } - pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndexNew { + pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndex { let popped_node = self.task_stack.pop().unwrap(); if let OpenTask::Regular { @@ -740,7 +712,7 @@ impl CurrentDepGraph { }); } - fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew { + fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndex { let popped_node = self.task_stack.pop().unwrap(); if let OpenTask::Anon { @@ -778,15 +750,26 @@ impl CurrentDepGraph { } } - fn read_index(&mut self, source: DepNodeIndexNew) { + fn read_index(&mut self, source: DepNodeIndex) { match self.task_stack.last_mut() { Some(&mut OpenTask::Regular { ref mut reads, ref mut read_set, - node: _, + node: ref target, }) => { if read_set.insert(source) { reads.push(source); + + if cfg!(debug_assertions) { + if let Some(ref forbidden_edge) = self.forbidden_edge { + let source = self.nodes[source]; + if forbidden_edge.test(&source, &target) { + bug!("forbidden edge {:?} -> {:?} created", + source, + target) + } + } + } } } Some(&mut OpenTask::Anon { @@ -805,12 +788,12 @@ impl CurrentDepGraph { fn alloc_node(&mut self, dep_node: DepNode, - edges: Vec) - -> DepNodeIndexNew { + edges: Vec) + -> DepNodeIndex { 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()); + let dep_node_index = DepNodeIndex::new(self.nodes.len()); self.nodes.push(dep_node); self.node_to_node_index.insert(dep_node, dep_node_index); self.edges.push(edges); @@ -818,38 +801,16 @@ impl CurrentDepGraph { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub(super) struct DepNodeIndexNew { - index: u32, -} - -impl Idx for DepNodeIndexNew { - fn new(v: usize) -> DepNodeIndexNew { - assert!((v & 0xFFFF_FFFF) == v); - DepNodeIndexNew { index: v as u32 } - } - - fn index(self) -> usize { - self.index as usize - } -} - -impl DepNodeIndexNew { - const INVALID: DepNodeIndexNew = DepNodeIndexNew { - index: ::std::u32::MAX, - }; -} - #[derive(Clone, Debug, PartialEq)] enum OpenTask { Regular { node: DepNode, - reads: Vec, - read_set: FxHashSet, + reads: Vec, + read_set: FxHashSet, }, Anon { - reads: Vec, - read_set: FxHashSet, + reads: Vec, + read_set: FxHashSet, }, Ignore, } diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index a8f78336b37..8d2cf676849 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -11,7 +11,6 @@ pub mod debug; mod dep_node; mod dep_tracking_map; -mod edges; mod graph; mod prev; mod query; diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs index 6e9e4f4a18b..5728bcc7d27 100644 --- a/src/librustc/dep_graph/raii.rs +++ b/src/librustc/dep_graph/raii.rs @@ -8,33 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::edges::DepGraphEdges; use super::graph::CurrentDepGraph; use std::cell::RefCell; pub struct IgnoreTask<'graph> { - legacy_graph: &'graph RefCell, - new_graph: &'graph RefCell, + graph: &'graph RefCell, } impl<'graph> IgnoreTask<'graph> { - pub(super) fn new(legacy_graph: &'graph RefCell, - new_graph: &'graph RefCell) - -> IgnoreTask<'graph> { - legacy_graph.borrow_mut().push_ignore(); - new_graph.borrow_mut().push_ignore(); + pub(super) fn new(graph: &'graph RefCell) -> IgnoreTask<'graph> { + graph.borrow_mut().push_ignore(); IgnoreTask { - legacy_graph, - new_graph, + graph, } } } impl<'graph> Drop for IgnoreTask<'graph> { fn drop(&mut self) { - self.legacy_graph.borrow_mut().pop_ignore(); - self.new_graph.borrow_mut().pop_ignore(); + self.graph.borrow_mut().pop_ignore(); } } diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs index 6110c270086..7275a740e76 100644 --- a/src/librustc/dep_graph/serialized.rs +++ b/src/librustc/dep_graph/serialized.rs @@ -56,7 +56,10 @@ impl SerializedDepGraph { } } - pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] { + #[inline] + pub fn edge_targets_from(&self, + source: SerializedDepNodeIndex) + -> &[SerializedDepNodeIndex] { let targets = self.edge_list_indices[source]; &self.edge_list_data[targets.0 as usize..targets.1 as usize] }