Skip to content

Commit

Permalink
Make dep node indices persistent between sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Jun 22, 2019
1 parent fcd003f commit 290912a
Show file tree
Hide file tree
Showing 12 changed files with 492 additions and 324 deletions.
618 changes: 373 additions & 245 deletions src/librustc/dep_graph/graph.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/librustc/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ pub mod cgu_reuse_tracker;
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, RecoverKey, label_strs};
pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps, hash_result};
pub use self::graph::WorkProductFileKind;
pub use self::graph::{DepGraphArgs, WorkProductFileKind, CurrentDepGraph};
pub use self::prev::PreviousDepGraph;
pub use self::query::DepGraphQuery;
pub use self::safe::AssertDepGraphSafe;
pub use self::safe::DepGraphSafe;
pub use self::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
pub use self::serialized::SerializedDepGraph;
55 changes: 41 additions & 14 deletions src/librustc/dep_graph/prev.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,70 @@
use crate::ich::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use super::dep_node::DepNode;
use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::sync::AtomicCell;
use super::dep_node::{DepNode, DepKind};
use super::graph::{DepNodeIndex, DepNodeState};
use super::serialized::SerializedDepGraph;

#[derive(Debug, RustcEncodable, RustcDecodable, Default)]
#[derive(Debug, Default)]
pub struct PreviousDepGraph {
data: SerializedDepGraph,
index: FxHashMap<DepNode, SerializedDepNodeIndex>,
pub(super) index: FxHashMap<DepNode, DepNodeIndex>,
pub(super) unused: Vec<DepNodeIndex>,
}

impl PreviousDepGraph {
pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
pub fn new_and_state(
data: SerializedDepGraph
) -> (PreviousDepGraph, IndexVec<DepNodeIndex, AtomicCell<DepNodeState>>) {
let mut unused = Vec::new();

let state: IndexVec<_, _> = data.nodes.iter_enumerated().map(|(index, node)| {
if node.kind == DepKind::Null {
// There might be `DepKind::Null` nodes due to thread-local dep node indices
// that didn't get assigned anything.
// We also changed outdated nodes to `DepKind::Null`.
unused.push(index);
AtomicCell::new(DepNodeState::Invalid)
} else {
AtomicCell::new(DepNodeState::Unknown)
}
}).collect();

let index: FxHashMap<_, _> = data.nodes
.iter_enumerated()
.map(|(idx, &dep_node)| (dep_node, idx))
.filter_map(|(idx, &dep_node)| {
if dep_node.kind == DepKind::Null {
None
} else {
Some((dep_node, idx))
}
})
.collect();
PreviousDepGraph { data, index }

(PreviousDepGraph { data, index, unused }, state)
}

#[inline]
pub fn edge_targets_from(
&self,
dep_node_index: SerializedDepNodeIndex
) -> &[SerializedDepNodeIndex] {
dep_node_index: DepNodeIndex
) -> &[DepNodeIndex] {
self.data.edge_targets_from(dep_node_index)
}

#[inline]
pub fn index_to_node(&self, dep_node_index: SerializedDepNodeIndex) -> DepNode {
pub fn index_to_node(&self, dep_node_index: DepNodeIndex) -> DepNode {
self.data.nodes[dep_node_index]
}

#[inline]
pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
pub fn node_to_index(&self, dep_node: &DepNode) -> DepNodeIndex {
self.index[dep_node]
}

#[inline]
pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option<SerializedDepNodeIndex> {
pub fn node_to_index_opt(&self, dep_node: &DepNode) -> Option<DepNodeIndex> {
self.index.get(dep_node).cloned()
}

Expand All @@ -50,12 +77,12 @@ impl PreviousDepGraph {

#[inline]
pub fn fingerprint_by_index(&self,
dep_node_index: SerializedDepNodeIndex)
dep_node_index: DepNodeIndex)
-> Fingerprint {
self.data.fingerprints[dep_node_index]
}

pub fn node_count(&self) -> usize {
self.index.len()
self.data.nodes.len()
}
}
19 changes: 8 additions & 11 deletions src/librustc/dep_graph/serialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,31 @@

use crate::dep_graph::DepNode;
use crate::ich::Fingerprint;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};

newtype_index! {
pub struct SerializedDepNodeIndex { .. }
}
use rustc_data_structures::indexed_vec::IndexVec;
use super::graph::DepNodeIndex;

/// Data for use when recompiling the **current crate**.
#[derive(Debug, RustcEncodable, RustcDecodable, Default)]
pub struct SerializedDepGraph {
/// The set of all DepNodes in the graph
pub nodes: IndexVec<SerializedDepNodeIndex, DepNode>,
pub nodes: IndexVec<DepNodeIndex, DepNode>,
/// The set of all Fingerprints in the graph. Each Fingerprint corresponds to
/// the DepNode at the same index in the nodes vector.
pub fingerprints: IndexVec<SerializedDepNodeIndex, Fingerprint>,
pub fingerprints: IndexVec<DepNodeIndex, Fingerprint>,
/// For each DepNode, stores the list of edges originating from that
/// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
/// which holds the actual DepNodeIndices of the target nodes.
pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
pub edge_list_indices: IndexVec<DepNodeIndex, (u32, u32)>,
/// A flattened list of all edge targets in the graph. Edge sources are
/// implicit in edge_list_indices.
pub edge_list_data: Vec<SerializedDepNodeIndex>,
pub edge_list_data: Vec<DepNodeIndex>,
}

impl SerializedDepGraph {
#[inline]
pub fn edge_targets_from(&self,
source: SerializedDepNodeIndex)
-> &[SerializedDepNodeIndex] {
source: DepNodeIndex)
-> &[DepNodeIndex] {
let targets = self.edge_list_indices[source];
&self.edge_list_data[targets.0 as usize..targets.1 as usize]
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::ty::query::QueryDescription;
use crate::ty::query::queries;
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
use crate::ty::subst::SubstsRef;
use crate::dep_graph::SerializedDepNodeIndex;
use crate::hir::def_id::{CrateNum, DefId, DefIndex};
use crate::mir;
use crate::mir::interpret::GlobalId;
use crate::dep_graph::DepNodeIndex;
use crate::traits;
use crate::traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal,
Expand Down
7 changes: 3 additions & 4 deletions src/librustc/ty/query/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::dep_graph::SerializedDepNodeIndex;
use crate::dep_graph::DepNode;
use crate::dep_graph::{DepNode, DepNodeIndex};
use crate::hir::def_id::{CrateNum, DefId};
use crate::ty::TyCtxt;
use crate::ty::query::queries;
Expand Down Expand Up @@ -54,7 +53,7 @@ pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
false
}

fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option<Self::Value> {
fn try_load_from_disk(_: TyCtxt<'tcx>, _: DepNodeIndex) -> Option<Self::Value> {
bug!("QueryDescription::load_from_disk() called for an unsupported query.")
}
}
Expand Down Expand Up @@ -86,7 +85,7 @@ macro_rules! impl_disk_cacheable_query(

#[inline]
fn try_load_from_disk(tcx: TyCtxt<'tcx>,
id: SerializedDepNodeIndex)
id: DepNodeIndex)
-> Option<Self::Value> {
tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
}
Expand Down
30 changes: 15 additions & 15 deletions src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use crate::dep_graph::DepNodeIndex;
use crate::hir;
use crate::hir::def_id::{CrateNum, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
use crate::hir::map::definitions::DefPathHash;
Expand Down Expand Up @@ -62,11 +62,11 @@ pub struct OnDiskCache<'sess> {

// A map from dep-node to the position of the cached query result in
// `serialized_data`.
query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
query_result_index: FxHashMap<DepNodeIndex, AbsoluteBytePos>,

// A map from dep-node to the position of any associated diagnostics in
// `serialized_data`.
prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
prev_diagnostics_index: FxHashMap<DepNodeIndex, AbsoluteBytePos>,

alloc_decoding_state: AllocDecodingState,
}
Expand All @@ -82,8 +82,8 @@ struct Footer {
interpret_alloc_index: Vec<u32>,
}

type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
type EncodedQueryResultIndex = Vec<(DepNodeIndex, AbsoluteBytePos)>;
type EncodedDiagnosticsIndex = Vec<(DepNodeIndex, AbsoluteBytePos)>;
type EncodedDiagnostics = Vec<Diagnostic>;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
Expand Down Expand Up @@ -230,12 +230,12 @@ impl<'sess> OnDiskCache<'sess> {
use crate::ty::query::config::QueryDescription;
if const_eval::cache_on_disk(tcx, key.clone()) {
if let Ok(ref value) = entry.value {
let dep_node = SerializedDepNodeIndex::new(entry.index.index());
let dep_node = DepNodeIndex::new(entry.index.index());

// Record position of the cache entry
qri.push((dep_node, AbsoluteBytePos::new(enc.position())));

// Encode the type check tables with the SerializedDepNodeIndex
// Encode the type check tables with the DepNodeIndex
// as tag.
enc.encode_tagged(dep_node, value)?;
}
Expand All @@ -253,7 +253,7 @@ impl<'sess> OnDiskCache<'sess> {
let pos = AbsoluteBytePos::new(encoder.position());
// Let's make sure we get the expected type here:
let diagnostics: &EncodedDiagnostics = diagnostics;
let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
let dep_node_index = DepNodeIndex::new(dep_node_index.index());
encoder.encode_tagged(dep_node_index, diagnostics)?;

Ok((dep_node_index, pos))
Expand Down Expand Up @@ -327,7 +327,7 @@ impl<'sess> OnDiskCache<'sess> {
pub fn load_diagnostics<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
dep_node_index: DepNodeIndex,
) -> Vec<Diagnostic> {
let diagnostics: Option<EncodedDiagnostics> = self.load_indexed(
tcx,
Expand All @@ -352,11 +352,11 @@ impl<'sess> OnDiskCache<'sess> {
}

/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
/// the given `DepNodeIndex`; otherwise returns `None`.
pub fn try_load_query_result<'tcx, T>(
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
dep_node_index: DepNodeIndex,
) -> Option<T>
where
T: Decodable,
Expand Down Expand Up @@ -386,8 +386,8 @@ impl<'sess> OnDiskCache<'sess> {
fn load_indexed<'tcx, T>(
&self,
tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
index: &FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
dep_node_index: DepNodeIndex,
index: &FxHashMap<DepNodeIndex, AbsoluteBytePos>,
debug_tag: &'static str,
) -> Option<T>
where
Expand Down Expand Up @@ -1091,12 +1091,12 @@ where
assert!(shards.iter().all(|shard| shard.active.is_empty()));
for (key, entry) in shards.iter().flat_map(|shard| shard.results.iter()) {
if Q::cache_on_disk(tcx, key.clone()) {
let dep_node = SerializedDepNodeIndex::new(entry.index.index());
let dep_node = DepNodeIndex::new(entry.index.index());

// Record position of the cache entry
query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));

// Encode the type check tables with the SerializedDepNodeIndex
// Encode the type check tables with the DepNodeIndex
// as tag.
encoder.encode_tagged(dep_node, &entry.value)?;
}
Expand Down
20 changes: 6 additions & 14 deletions src/librustc/ty/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.

use crate::dep_graph::{DepNodeIndex, DepNode, DepKind, SerializedDepNodeIndex};
use crate::dep_graph::{DepNodeIndex, DepNode, DepKind};
use crate::ty::tls;
use crate::ty::{self, TyCtxt};
use crate::ty::query::Query;
Expand Down Expand Up @@ -413,10 +413,9 @@ impl<'tcx> TyCtxt<'tcx> {
// try_mark_green(), so we can ignore them here.
let loaded = self.start_query(job.job.clone(), None, |tcx| {
let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node);
marked.map(|(prev_dep_node_index, dep_node_index)| {
marked.map(|dep_node_index| {
(tcx.load_from_disk_and_cache_in_memory::<Q>(
key.clone(),
prev_dep_node_index,
dep_node_index,
&dep_node
), dep_node_index)
Expand All @@ -436,7 +435,6 @@ impl<'tcx> TyCtxt<'tcx> {
fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'tcx>>(
self,
key: Q::Key,
prev_dep_node_index: SerializedDepNodeIndex,
dep_node_index: DepNodeIndex,
dep_node: &DepNode,
) -> Q::Value {
Expand All @@ -449,7 +447,7 @@ impl<'tcx> TyCtxt<'tcx> {
let result = if Q::cache_on_disk(self.global_tcx(), key.clone()) &&
self.sess.opts.debugging_opts.incremental_queries {
self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME));
let result = Q::try_load_from_disk(self.global_tcx(), prev_dep_node_index);
let result = Q::try_load_from_disk(self.global_tcx(), dep_node_index);
self.sess.profiler(|p| p.incremental_load_result_end(Q::NAME));

// We always expect to find a cached result for things that
Expand Down Expand Up @@ -488,7 +486,7 @@ impl<'tcx> TyCtxt<'tcx> {
// If -Zincremental-verify-ich is specified, re-hash results from
// the cache and make sure that they have the expected fingerprint.
if unlikely!(self.sess.opts.debugging_opts.incremental_verify_ich) {
self.incremental_verify_ich::<Q>(&result, dep_node, dep_node_index);
self.incremental_verify_ich::<Q>(&result, dep_node);
}

if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) {
Expand All @@ -504,24 +502,18 @@ impl<'tcx> TyCtxt<'tcx> {
self,
result: &Q::Value,
dep_node: &DepNode,
dep_node_index: DepNodeIndex,
) {
use crate::ich::Fingerprint;

assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
self.dep_graph.prev_fingerprint_of(dep_node),
"Fingerprint for green query instance not loaded \
from cache: {:?}", dep_node);

debug!("BEGIN verify_ich({:?})", dep_node);
let mut hcx = self.create_stable_hashing_context();

let new_hash = Q::hash_result(&mut hcx, result).unwrap_or(Fingerprint::ZERO);
debug!("END verify_ich({:?})", dep_node);

let old_hash = self.dep_graph.fingerprint_of(dep_node_index);
let old_hash = self.dep_graph.prev_fingerprint_of(dep_node);

assert!(new_hash == old_hash, "Found unstable fingerprints \
assert!(Some(new_hash) == old_hash, "Found unstable fingerprints \
for {:?}", dep_node);
}

Expand Down
Loading

0 comments on commit 290912a

Please sign in to comment.