Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only keep one dep-graph in memory #82345

Closed
wants to merge 14 commits into from
11 changes: 10 additions & 1 deletion compiler/rustc_data_structures/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ cfg_if! {
}
}

use std::ops::Add;
use std::ops::{Add, BitOr};
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};

/// This is a single threaded variant of AtomicCell provided by crossbeam.
Expand Down Expand Up @@ -147,6 +147,15 @@ cfg_if! {
}
}

impl<T: BitOr<Output=T> + Copy> Atomic<T> {
#[inline]
pub fn fetch_or(&self, val: T, _: Ordering) -> T {
let old = self.0.get();
self.0.set(old | val);
old
}
}

pub type AtomicUsize = Atomic<usize>;
pub type AtomicBool = Atomic<bool>;
pub type AtomicU32 = Atomic<u32>;
Expand Down
28 changes: 3 additions & 25 deletions compiler/rustc_incremental/src/persist/dirty_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
//! the required condition is not met.

use rustc_ast::{self as ast, Attribute, NestedMetaItem};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::Node as HirNode;
use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeColor, DepNodeExt};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{sym, Symbol};
Expand Down Expand Up @@ -391,39 +390,18 @@ impl DirtyCleanVisitor<'tcx> {
fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
debug!("assert_dirty({:?})", dep_node);

let current_fingerprint = self.get_fingerprint(&dep_node);
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);

if current_fingerprint == prev_fingerprint {
if self.tcx.dep_graph.node_color(&dep_node) == Some(DepNodeColor::Green) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx
.sess
.span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str));
}
}

fn get_fingerprint(&self, dep_node: &DepNode) -> Option<Fingerprint> {
if self.tcx.dep_graph.dep_node_exists(dep_node) {
let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node);
Some(self.tcx.dep_graph.fingerprint_of(dep_node_index))
} else {
None
}
}

fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
debug!("assert_clean({:?})", dep_node);

let current_fingerprint = self.get_fingerprint(&dep_node);
let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);

// if the node wasn't previously evaluated and now is (or vice versa),
// then the node isn't actually clean or dirty.
if (current_fingerprint == None) ^ (prev_fingerprint == None) {
return;
}

if current_fingerprint != prev_fingerprint {
if self.tcx.dep_graph.node_color(&dep_node) == Some(DepNodeColor::Red) {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx
.sess
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_incremental/src/persist/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use rustc_data_structures::fx::FxHashMap;
use rustc_hir::definitions::Definitions;
use rustc_middle::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::query::OnDiskCache;
use rustc_serialize::opaque::Decoder;
use rustc_serialize::Decodable as RustcDecodable;
Expand All @@ -22,8 +22,8 @@ pub enum LoadResult<T> {
Error { message: String },
}

impl LoadResult<(PreviousDepGraph, WorkProductMap)> {
pub fn open(self, sess: &Session) -> (PreviousDepGraph, WorkProductMap) {
impl LoadResult<(SerializedDepGraph, WorkProductMap)> {
pub fn open(self, sess: &Session) -> (SerializedDepGraph, WorkProductMap) {
match self {
LoadResult::Error { message } => {
sess.warn(&message);
Expand Down Expand Up @@ -84,7 +84,7 @@ impl<T> MaybeAsync<T> {
}
}

pub type DepGraphFuture = MaybeAsync<LoadResult<(PreviousDepGraph, WorkProductMap)>>;
pub type DepGraphFuture = MaybeAsync<LoadResult<(SerializedDepGraph, WorkProductMap)>>;

/// Launch a thread and load the dependency graph in the background.
pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
Expand Down Expand Up @@ -185,7 +185,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
let dep_graph = SerializedDepGraph::decode(&mut decoder)
.expect("Error reading cached dep-graph");

LoadResult::Ok { data: (PreviousDepGraph::new(dep_graph), prev_work_products) }
LoadResult::Ok { data: (dep_graph, prev_work_products) }
}
}
}))
Expand Down
139 changes: 139 additions & 0 deletions compiler/rustc_index/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,5 +842,144 @@ impl<I: Idx> FnMut<(usize,)> for IntoIdx<I> {
}
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct IndexArray<I: Idx, T> {
pub raw: Box<[T]>,
_marker: PhantomData<fn(&I)>,
}

// Whether `IndexArray` is `Send` depends only on the data,
// not the phantom data.
unsafe impl<I: Idx, T> Send for IndexArray<I, T> where T: Send {}

impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexArray<I, T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&self.raw, s)
}
}

impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for &IndexArray<I, T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&self.raw, s)
}
}

impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexArray<I, T> {
fn decode(d: &mut D) -> Result<Self, D::Error> {
Decodable::decode(d).map(|v| IndexArray { raw: v, _marker: PhantomData })
}
}

impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexArray<I, T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.raw, fmt)
}
}

impl<I: Idx, T> IndexArray<I, T> {
#[inline]
pub fn new() -> Self {
IndexArray { raw: Box::default(), _marker: PhantomData }
}

#[inline]
pub fn from_raw(raw: Box<[T]>) -> Self {
IndexArray { raw, _marker: PhantomData }
}

#[inline]
pub fn from_vec(raw: Vec<T>) -> Self {
IndexArray { raw: raw.into(), _marker: PhantomData }
}

#[inline]
pub fn len(&self) -> usize {
self.raw.len()
}

#[inline]
pub fn is_empty(&self) -> bool {
self.raw.is_empty()
}

#[inline]
pub fn iter(&self) -> slice::Iter<'_, T> {
self.raw.iter()
}

#[inline]
pub fn iter_enumerated(&self) -> Enumerated<I, slice::Iter<'_, T>> {
self.raw.iter().enumerate().map(IntoIdx { _marker: PhantomData })
}

#[inline]
pub fn indices(&self) -> iter::Map<Range<usize>, IntoIdx<I>> {
(0..self.len()).map(IntoIdx { _marker: PhantomData })
}

#[inline]
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
self.raw.iter_mut()
}

#[inline]
pub fn iter_enumerated_mut(&mut self) -> Enumerated<I, slice::IterMut<'_, T>> {
self.raw.iter_mut().enumerate().map(IntoIdx { _marker: PhantomData })
}
}

impl<I: Idx, T> Index<I> for IndexArray<I, T> {
type Output = T;

#[inline]
fn index(&self, index: I) -> &T {
&self.raw[index.index()]
}
}

impl<I: Idx, T> IndexMut<I> for IndexArray<I, T> {
#[inline]
fn index_mut(&mut self, index: I) -> &mut T {
&mut self.raw[index.index()]
}
}

impl<I: Idx, T> Default for IndexArray<I, T> {
#[inline]
fn default() -> Self {
Self::new()
}
}

impl<I: Idx, T> FromIterator<T> for IndexArray<I, T> {
#[inline]
fn from_iter<J>(iter: J) -> Self
where
J: IntoIterator<Item = T>,
{
IndexArray { raw: FromIterator::from_iter(iter), _marker: PhantomData }
}
}

impl<'a, I: Idx, T> IntoIterator for &'a IndexArray<I, T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;

#[inline]
fn into_iter(self) -> slice::Iter<'a, T> {
self.raw.iter()
}
}

impl<'a, I: Idx, T> IntoIterator for &'a mut IndexArray<I, T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;

#[inline]
fn into_iter(self) -> slice::IterMut<'a, T> {
self.raw.iter_mut()
}
}

#[cfg(test)]
mod tests;
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use rustc_hir::HirId;
use rustc_span::symbol::Symbol;
use std::hash::Hash;

pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
pub use rustc_query_system::dep_graph::{DepContext, DepNodeColor, DepNodeParams};

/// This struct stores metadata about each DepKind.
///
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt};
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph<DepKind>;
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;

impl rustc_query_system::dep_graph::DepKind for DepKind {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use rustc_serialize::opaque;
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind;
Expand Down Expand Up @@ -237,6 +238,7 @@ macro_rules! define_callbacks {
tcx: TyCtxt<'tcx>,
encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>,
query_result_index: &mut on_disk_cache::EncodedQueryResultIndex,
remap: &IndexVec<DepNodeIndex, Option<SerializedDepNodeIndex>>,
) -> opaque::FileEncodeResult;

fn exec_cache_promotions(&'tcx self, tcx: TyCtxt<'tcx>);
Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_middle/src/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_errors::Diagnostic;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_hir::definitions::Definitions;
use rustc_index::vec::{Idx, IndexVec};
use rustc_index::vec::IndexVec;
use rustc_query_system::dep_graph::DepContext;
use rustc_query_system::query::QueryContext;
use rustc_serialize::{
Expand Down Expand Up @@ -303,13 +303,15 @@ impl<'sess> OnDiskCache<'sess> {
latest_foreign_def_path_hashes,
};

let remap = tcx.dep_graph.compression_map();

// Encode query results.
let mut query_result_index = EncodedQueryResultIndex::new();

tcx.sess.time("encode_query_results", || -> FileEncodeResult {
let enc = &mut encoder;
let qri = &mut query_result_index;
tcx.queries.encode_query_results(tcx, enc, qri)
tcx.queries.encode_query_results(tcx, enc, qri, &remap)
})?;

// Encode diagnostics.
Expand All @@ -318,11 +320,11 @@ impl<'sess> OnDiskCache<'sess> {
.borrow()
.iter()
.map(
|(dep_node_index, diagnostics)| -> Result<_, <FileEncoder as Encoder>::Error> {
|(&dep_node_index, diagnostics)| -> Result<_, <FileEncoder as Encoder>::Error> {
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 = remap[dep_node_index].unwrap();
encoder.encode_tagged(dep_node_index, diagnostics)?;

Ok((dep_node_index, pos))
Expand Down Expand Up @@ -1220,6 +1222,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
tcx: CTX,
encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,
query_result_index: &mut EncodedQueryResultIndex,
remap: &IndexVec<DepNodeIndex, Option<SerializedDepNodeIndex>>,
) -> FileEncodeResult
where
CTX: QueryContext + 'tcx,
Expand All @@ -1236,7 +1239,7 @@ where
cache.iter_results(|results| {
for (key, value, dep_node) in results {
if Q::cache_on_disk(tcx, &key, Some(value)) {
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
let dep_node = remap[dep_node].unwrap();

// Record position of the cache entry.
query_result_index
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_query_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use rustc_middle::ich::StableHashingContext;
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
use rustc_middle::ty::query::{Providers, QueryEngine};
use rustc_middle::ty::{self, TyCtxt};
use rustc_query_system::dep_graph::{DepNodeColor, DepNodeIndex, SerializedDepNodeIndex};
use rustc_serialize::opaque;
use rustc_span::{Span, DUMMY_SP};

Expand Down
Loading