Skip to content

Commit

Permalink
Encode ExpnId using ExpnHash for incr. comp.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgillot committed Jul 17, 2021
1 parent 2fe37c5 commit 37a13de
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 121 deletions.
38 changes: 38 additions & 0 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Expand Up @@ -79,6 +79,8 @@ crate struct CrateMetadata {
/// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
/// this is used.
def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
/// Likewise for ExpnHash.
expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>,
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
alloc_decoding_state: AllocDecodingState,
/// Caches decoded `DefKey`s.
Expand Down Expand Up @@ -1619,6 +1621,41 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
self.def_path_hash_unlocked(index, &mut def_path_hashes)
}

fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
debug_assert_eq!(ExpnId::from_hash(hash), None);
let index_guess = ExpnIndex::from_u32(index_guess);
let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));

let index = if old_hash == Some(hash) {
// Fast path: the expn and its index is unchanged from the
// previous compilation session. There is no need to decode anything
// else.
index_guess
} else {
// Slow path: We need to find out the new `DefIndex` of the provided
// `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
// stored in this crate.
let map = self.cdata.expn_hash_map.get_or_init(|| {
let end_id = self.root.expn_hashes.size() as u32;
let mut map =
UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
for i in 0..end_id {
let i = ExpnIndex::from_u32(i);
if let Some(hash) = self.root.expn_hashes.get(self, i) {
map.insert(hash.decode(self), i);
} else {
panic!("Missing expn_hash entry for {:?}", i);
}
}
map
});
map[&hash]
};

let data = self.root.expn_data.get(self, index).unwrap().decode(self);
rustc_span::hygiene::register_expn_id(data, hash)
}

/// Imports the source_map from an external crate into the source_map of the crate
/// currently being compiled (the "local crate").
///
Expand Down Expand Up @@ -1857,6 +1894,7 @@ impl CrateMetadata {
raw_proc_macros,
source_map_import_info: OnceCell::new(),
def_path_hash_map: Default::default(),
expn_hash_map: Default::default(),
alloc_decoding_state,
cnum,
cnum_map,
Expand Down
23 changes: 5 additions & 18 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Expand Up @@ -18,7 +18,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, Visibility};
use rustc_session::utils::NativeLibKind;
use rustc_session::{Session, StableCrateId};
use rustc_span::hygiene::{ExpnData, ExpnHash, ExpnId};
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::Symbol;

Expand Down Expand Up @@ -494,23 +494,6 @@ impl CrateStore for CStore {
fn as_any(&self) -> &dyn Any {
self
}
fn decode_expn_data(&self, sess: &Session, expn_id: ExpnId) -> (ExpnData, ExpnHash) {
let crate_data = self.get_crate_data(expn_id.krate);
(
crate_data
.root
.expn_data
.get(&crate_data, expn_id.local_id)
.unwrap()
.decode((&crate_data, sess)),
crate_data
.root
.expn_hashes
.get(&crate_data, expn_id.local_id)
.unwrap()
.decode((&crate_data, sess)),
)
}

fn crate_name(&self, cnum: CrateNum) -> Symbol {
self.get_crate_data(cnum).root.name
Expand Down Expand Up @@ -545,6 +528,10 @@ impl CrateStore for CStore {
self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash)
}

fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash)
}

fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
encoder::encode_metadata(tcx)
}
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_middle/src/middle/cstore.rs
Expand Up @@ -11,8 +11,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_macros::HashStable;
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use rustc_span::hygiene::{ExpnData, ExpnHash, ExpnId};
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::Target;
Expand Down Expand Up @@ -188,7 +187,6 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
/// during resolve)
pub trait CrateStore: std::fmt::Debug {
fn as_any(&self) -> &dyn Any;
fn decode_expn_data(&self, sess: &Session, expn_id: ExpnId) -> (ExpnData, ExpnHash);

// Foreign definitions.
// This information is safe to access, since it's hashed as part of the DefPathHash, which incr.
Expand All @@ -209,6 +207,7 @@ pub trait CrateStore: std::fmt::Debug {
index_guess: u32,
hash: DefPathHash,
) -> Option<DefId>;
fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId;

// utility functions
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
Expand Down
93 changes: 59 additions & 34 deletions compiler/rustc_middle/src/ty/query/on_disk_cache.rs
Expand Up @@ -83,14 +83,16 @@ pub struct OnDiskCache<'sess> {
// `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
// we could look up the `ExpnData` from the metadata of foreign crates,
// but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
expn_data: FxHashMap<u32, AbsoluteBytePos>,
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
// Additional information used when decoding hygiene data.
hygiene_context: HygieneDecodeContext,
// Maps `DefPathHash`es to their `RawDefId`s from the *previous*
// compilation session. This is used as an initial 'guess' when
// we try to map a `DefPathHash` to its `DefId` in the current compilation
// session.
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
// Likewise for ExpnId.
foreign_expn_data: UnhashMap<ExpnHash, u32>,

// The *next* compilation sessison's `foreign_def_path_hashes` - at
// the end of our current compilation session, this will get written
Expand Down Expand Up @@ -118,8 +120,9 @@ struct Footer {
// See `OnDiskCache.syntax_contexts`
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
// See `OnDiskCache.expn_data`
expn_data: FxHashMap<u32, AbsoluteBytePos>,
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
foreign_expn_data: UnhashMap<ExpnHash, u32>,
}

pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
Expand Down Expand Up @@ -217,6 +220,7 @@ impl<'sess> OnDiskCache<'sess> {
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
syntax_contexts: footer.syntax_contexts,
expn_data: footer.expn_data,
foreign_expn_data: footer.foreign_expn_data,
hygiene_context: Default::default(),
foreign_def_path_hashes: footer.foreign_def_path_hashes,
latest_foreign_def_path_hashes: Default::default(),
Expand All @@ -236,7 +240,8 @@ impl<'sess> OnDiskCache<'sess> {
prev_diagnostics_index: Default::default(),
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
syntax_contexts: FxHashMap::default(),
expn_data: FxHashMap::default(),
expn_data: UnhashMap::default(),
foreign_expn_data: UnhashMap::default(),
hygiene_context: Default::default(),
foreign_def_path_hashes: Default::default(),
latest_foreign_def_path_hashes: Default::default(),
Expand Down Expand Up @@ -350,7 +355,8 @@ impl<'sess> OnDiskCache<'sess> {
};

let mut syntax_contexts = FxHashMap::default();
let mut expn_ids = FxHashMap::default();
let mut expn_data = UnhashMap::default();
let mut foreign_expn_data = UnhashMap::default();

// Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
// session.
Expand All @@ -363,13 +369,14 @@ impl<'sess> OnDiskCache<'sess> {
syntax_contexts.insert(index, pos);
Ok(())
},
|encoder, index, expn_data, hash| -> FileEncodeResult {
if index.krate == LOCAL_CRATE {
|encoder, expn_id, data, hash| -> FileEncodeResult {
if expn_id.krate == LOCAL_CRATE {
let pos = AbsoluteBytePos::new(encoder.position());
encoder.encode_tagged(TAG_EXPN_DATA, &(expn_data, hash))?;
expn_ids.insert(index.local_id.as_u32(), pos);
encoder.encode_tagged(TAG_EXPN_DATA, &data)?;
expn_data.insert(hash, pos);
} else {
foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
}
// TODO Handle foreign expansions.
Ok(())
},
)?;
Expand All @@ -387,7 +394,8 @@ impl<'sess> OnDiskCache<'sess> {
diagnostics_index,
interpret_alloc_index,
syntax_contexts,
expn_data: expn_ids,
expn_data,
foreign_expn_data,
foreign_def_path_hashes,
},
)?;
Expand Down Expand Up @@ -549,6 +557,7 @@ impl<'sess> OnDiskCache<'sess> {
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
syntax_contexts: &self.syntax_contexts,
expn_data: &self.expn_data,
foreign_expn_data: &self.foreign_expn_data,
hygiene_context: &self.hygiene_context,
};
f(&mut decoder)
Expand Down Expand Up @@ -643,7 +652,8 @@ pub struct CacheDecoder<'a, 'tcx> {
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
alloc_decoding_session: AllocDecodingSession<'a>,
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
expn_data: &'a FxHashMap<u32, AbsoluteBytePos>,
expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
hygiene_context: &'a HygieneDecodeContext,
}

Expand Down Expand Up @@ -794,27 +804,43 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {

impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
let krate = CrateNum::decode(decoder)?;
let index = u32::decode(decoder)?;

let expn_data = decoder.expn_data;
let tcx = decoder.tcx;
rustc_span::hygiene::decode_expn_id_incrcomp(
krate,
index,
decoder.hygiene_context,
|index| -> Result<(ExpnData, ExpnHash), _> {
// This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
// We look up the position of the associated `ExpnData` and decode it.
let pos = expn_data
.get(&index)
.unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data));

decoder
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))
},
|expn_id| tcx.untracked_resolutions.cstore.decode_expn_data(tcx.sess, expn_id),
)
let hash = ExpnHash::decode(decoder)?;
if hash.is_root() {
return Ok(ExpnId::root());
}

if let Some(expn_id) = ExpnId::from_hash(hash) {
return Ok(expn_id);
}

let krate = decoder.cnum_map[&hash.stable_crate_id()];

let expn_id = if krate == LOCAL_CRATE {
// We look up the position of the associated `ExpnData` and decode it.
let pos = decoder
.expn_data
.get(&hash)
.unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data));

let data: ExpnData = decoder
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?;
rustc_span::hygiene::register_local_expn_id(data, hash)
} else {
let index_guess = decoder.foreign_expn_data[&hash];
decoder.tcx.untracked_resolutions.cstore.expn_hash_to_expn_id(krate, index_guess, hash)
};

#[cfg(debug_assertions)]
{
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
let mut hcx = decoder.tcx.create_stable_hashing_context();
let mut hasher = StableHasher::new();
expn_id.expn_data().hash_stable(&mut hcx, &mut hasher);
let local_hash: u64 = hasher.finish();
debug_assert_eq!(hash.local_hash(), local_hash);
}

Ok(expn_id)
}
}

Expand Down Expand Up @@ -990,8 +1016,7 @@ where
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
s.hygiene_context.schedule_expn_data_for_encoding(*self);
self.krate.encode(s)?;
self.local_id.as_u32().encode(s)
self.expn_hash().encode(s)
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_span/src/def_id.rs
Expand Up @@ -136,7 +136,7 @@ impl Borrow<Fingerprint> for DefPathHash {
/// further trouble.
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub struct StableCrateId(u64);
pub struct StableCrateId(pub(crate) u64);

impl StableCrateId {
pub fn to_u64(self) -> u64 {
Expand Down

0 comments on commit 37a13de

Please sign in to comment.