Skip to content

Commit 37a13de

Browse files
committed
Encode ExpnId using ExpnHash for incr. comp.
1 parent 2fe37c5 commit 37a13de

File tree

6 files changed

+161
-121
lines changed

6 files changed

+161
-121
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+38
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ crate struct CrateMetadata {
7979
/// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
8080
/// this is used.
8181
def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
82+
/// Likewise for ExpnHash.
83+
expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>,
8284
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
8385
alloc_decoding_state: AllocDecodingState,
8486
/// Caches decoded `DefKey`s.
@@ -1619,6 +1621,41 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
16191621
self.def_path_hash_unlocked(index, &mut def_path_hashes)
16201622
}
16211623

1624+
fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
1625+
debug_assert_eq!(ExpnId::from_hash(hash), None);
1626+
let index_guess = ExpnIndex::from_u32(index_guess);
1627+
let old_hash = self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode(self));
1628+
1629+
let index = if old_hash == Some(hash) {
1630+
// Fast path: the expn and its index is unchanged from the
1631+
// previous compilation session. There is no need to decode anything
1632+
// else.
1633+
index_guess
1634+
} else {
1635+
// Slow path: We need to find out the new `DefIndex` of the provided
1636+
// `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
1637+
// stored in this crate.
1638+
let map = self.cdata.expn_hash_map.get_or_init(|| {
1639+
let end_id = self.root.expn_hashes.size() as u32;
1640+
let mut map =
1641+
UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
1642+
for i in 0..end_id {
1643+
let i = ExpnIndex::from_u32(i);
1644+
if let Some(hash) = self.root.expn_hashes.get(self, i) {
1645+
map.insert(hash.decode(self), i);
1646+
} else {
1647+
panic!("Missing expn_hash entry for {:?}", i);
1648+
}
1649+
}
1650+
map
1651+
});
1652+
map[&hash]
1653+
};
1654+
1655+
let data = self.root.expn_data.get(self, index).unwrap().decode(self);
1656+
rustc_span::hygiene::register_expn_id(data, hash)
1657+
}
1658+
16221659
/// Imports the source_map from an external crate into the source_map of the crate
16231660
/// currently being compiled (the "local crate").
16241661
///
@@ -1857,6 +1894,7 @@ impl CrateMetadata {
18571894
raw_proc_macros,
18581895
source_map_import_info: OnceCell::new(),
18591896
def_path_hash_map: Default::default(),
1897+
expn_hash_map: Default::default(),
18601898
alloc_decoding_state,
18611899
cnum,
18621900
cnum_map,

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+5-18
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::query::Providers;
1818
use rustc_middle::ty::{self, TyCtxt, Visibility};
1919
use rustc_session::utils::NativeLibKind;
2020
use rustc_session::{Session, StableCrateId};
21-
use rustc_span::hygiene::{ExpnData, ExpnHash, ExpnId};
21+
use rustc_span::hygiene::{ExpnHash, ExpnId};
2222
use rustc_span::source_map::{Span, Spanned};
2323
use rustc_span::symbol::Symbol;
2424

@@ -494,23 +494,6 @@ impl CrateStore for CStore {
494494
fn as_any(&self) -> &dyn Any {
495495
self
496496
}
497-
fn decode_expn_data(&self, sess: &Session, expn_id: ExpnId) -> (ExpnData, ExpnHash) {
498-
let crate_data = self.get_crate_data(expn_id.krate);
499-
(
500-
crate_data
501-
.root
502-
.expn_data
503-
.get(&crate_data, expn_id.local_id)
504-
.unwrap()
505-
.decode((&crate_data, sess)),
506-
crate_data
507-
.root
508-
.expn_hashes
509-
.get(&crate_data, expn_id.local_id)
510-
.unwrap()
511-
.decode((&crate_data, sess)),
512-
)
513-
}
514497

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

531+
fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
532+
self.get_crate_data(cnum).expn_hash_to_expn_id(index_guess, hash)
533+
}
534+
548535
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
549536
encoder::encode_metadata(tcx)
550537
}

compiler/rustc_middle/src/middle/cstore.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
1111
use rustc_macros::HashStable;
1212
use rustc_session::search_paths::PathKind;
1313
use rustc_session::utils::NativeLibKind;
14-
use rustc_session::Session;
15-
use rustc_span::hygiene::{ExpnData, ExpnHash, ExpnId};
14+
use rustc_span::hygiene::{ExpnHash, ExpnId};
1615
use rustc_span::symbol::Symbol;
1716
use rustc_span::Span;
1817
use rustc_target::spec::Target;
@@ -188,7 +187,6 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
188187
/// during resolve)
189188
pub trait CrateStore: std::fmt::Debug {
190189
fn as_any(&self) -> &dyn Any;
191-
fn decode_expn_data(&self, sess: &Session, expn_id: ExpnId) -> (ExpnData, ExpnHash);
192190

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

213212
// utility functions
214213
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;

compiler/rustc_middle/src/ty/query/on_disk_cache.rs

+59-34
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,16 @@ pub struct OnDiskCache<'sess> {
8383
// `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
8484
// we could look up the `ExpnData` from the metadata of foreign crates,
8585
// but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
86-
expn_data: FxHashMap<u32, AbsoluteBytePos>,
86+
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
8787
// Additional information used when decoding hygiene data.
8888
hygiene_context: HygieneDecodeContext,
8989
// Maps `DefPathHash`es to their `RawDefId`s from the *previous*
9090
// compilation session. This is used as an initial 'guess' when
9191
// we try to map a `DefPathHash` to its `DefId` in the current compilation
9292
// session.
9393
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
94+
// Likewise for ExpnId.
95+
foreign_expn_data: UnhashMap<ExpnHash, u32>,
9496

9597
// The *next* compilation sessison's `foreign_def_path_hashes` - at
9698
// the end of our current compilation session, this will get written
@@ -118,8 +120,9 @@ struct Footer {
118120
// See `OnDiskCache.syntax_contexts`
119121
syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
120122
// See `OnDiskCache.expn_data`
121-
expn_data: FxHashMap<u32, AbsoluteBytePos>,
123+
expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
122124
foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
125+
foreign_expn_data: UnhashMap<ExpnHash, u32>,
123126
}
124127

125128
pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
@@ -217,6 +220,7 @@ impl<'sess> OnDiskCache<'sess> {
217220
alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
218221
syntax_contexts: footer.syntax_contexts,
219222
expn_data: footer.expn_data,
223+
foreign_expn_data: footer.foreign_expn_data,
220224
hygiene_context: Default::default(),
221225
foreign_def_path_hashes: footer.foreign_def_path_hashes,
222226
latest_foreign_def_path_hashes: Default::default(),
@@ -236,7 +240,8 @@ impl<'sess> OnDiskCache<'sess> {
236240
prev_diagnostics_index: Default::default(),
237241
alloc_decoding_state: AllocDecodingState::new(Vec::new()),
238242
syntax_contexts: FxHashMap::default(),
239-
expn_data: FxHashMap::default(),
243+
expn_data: UnhashMap::default(),
244+
foreign_expn_data: UnhashMap::default(),
240245
hygiene_context: Default::default(),
241246
foreign_def_path_hashes: Default::default(),
242247
latest_foreign_def_path_hashes: Default::default(),
@@ -350,7 +355,8 @@ impl<'sess> OnDiskCache<'sess> {
350355
};
351356

352357
let mut syntax_contexts = FxHashMap::default();
353-
let mut expn_ids = FxHashMap::default();
358+
let mut expn_data = UnhashMap::default();
359+
let mut foreign_expn_data = UnhashMap::default();
354360

355361
// Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
356362
// session.
@@ -363,13 +369,14 @@ impl<'sess> OnDiskCache<'sess> {
363369
syntax_contexts.insert(index, pos);
364370
Ok(())
365371
},
366-
|encoder, index, expn_data, hash| -> FileEncodeResult {
367-
if index.krate == LOCAL_CRATE {
372+
|encoder, expn_id, data, hash| -> FileEncodeResult {
373+
if expn_id.krate == LOCAL_CRATE {
368374
let pos = AbsoluteBytePos::new(encoder.position());
369-
encoder.encode_tagged(TAG_EXPN_DATA, &(expn_data, hash))?;
370-
expn_ids.insert(index.local_id.as_u32(), pos);
375+
encoder.encode_tagged(TAG_EXPN_DATA, &data)?;
376+
expn_data.insert(hash, pos);
377+
} else {
378+
foreign_expn_data.insert(hash, expn_id.local_id.as_u32());
371379
}
372-
// TODO Handle foreign expansions.
373380
Ok(())
374381
},
375382
)?;
@@ -387,7 +394,8 @@ impl<'sess> OnDiskCache<'sess> {
387394
diagnostics_index,
388395
interpret_alloc_index,
389396
syntax_contexts,
390-
expn_data: expn_ids,
397+
expn_data,
398+
foreign_expn_data,
391399
foreign_def_path_hashes,
392400
},
393401
)?;
@@ -549,6 +557,7 @@ impl<'sess> OnDiskCache<'sess> {
549557
alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
550558
syntax_contexts: &self.syntax_contexts,
551559
expn_data: &self.expn_data,
560+
foreign_expn_data: &self.foreign_expn_data,
552561
hygiene_context: &self.hygiene_context,
553562
};
554563
f(&mut decoder)
@@ -643,7 +652,8 @@ pub struct CacheDecoder<'a, 'tcx> {
643652
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
644653
alloc_decoding_session: AllocDecodingSession<'a>,
645654
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
646-
expn_data: &'a FxHashMap<u32, AbsoluteBytePos>,
655+
expn_data: &'a UnhashMap<ExpnHash, AbsoluteBytePos>,
656+
foreign_expn_data: &'a UnhashMap<ExpnHash, u32>,
647657
hygiene_context: &'a HygieneDecodeContext,
648658
}
649659

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

795805
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
796806
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
797-
let krate = CrateNum::decode(decoder)?;
798-
let index = u32::decode(decoder)?;
799-
800-
let expn_data = decoder.expn_data;
801-
let tcx = decoder.tcx;
802-
rustc_span::hygiene::decode_expn_id_incrcomp(
803-
krate,
804-
index,
805-
decoder.hygiene_context,
806-
|index| -> Result<(ExpnData, ExpnHash), _> {
807-
// This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
808-
// We look up the position of the associated `ExpnData` and decode it.
809-
let pos = expn_data
810-
.get(&index)
811-
.unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data));
812-
813-
decoder
814-
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))
815-
},
816-
|expn_id| tcx.untracked_resolutions.cstore.decode_expn_data(tcx.sess, expn_id),
817-
)
807+
let hash = ExpnHash::decode(decoder)?;
808+
if hash.is_root() {
809+
return Ok(ExpnId::root());
810+
}
811+
812+
if let Some(expn_id) = ExpnId::from_hash(hash) {
813+
return Ok(expn_id);
814+
}
815+
816+
let krate = decoder.cnum_map[&hash.stable_crate_id()];
817+
818+
let expn_id = if krate == LOCAL_CRATE {
819+
// We look up the position of the associated `ExpnData` and decode it.
820+
let pos = decoder
821+
.expn_data
822+
.get(&hash)
823+
.unwrap_or_else(|| panic!("Bad hash {:?} (map {:?})", hash, decoder.expn_data));
824+
825+
let data: ExpnData = decoder
826+
.with_position(pos.to_usize(), |decoder| decode_tagged(decoder, TAG_EXPN_DATA))?;
827+
rustc_span::hygiene::register_local_expn_id(data, hash)
828+
} else {
829+
let index_guess = decoder.foreign_expn_data[&hash];
830+
decoder.tcx.untracked_resolutions.cstore.expn_hash_to_expn_id(krate, index_guess, hash)
831+
};
832+
833+
#[cfg(debug_assertions)]
834+
{
835+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
836+
let mut hcx = decoder.tcx.create_stable_hashing_context();
837+
let mut hasher = StableHasher::new();
838+
expn_id.expn_data().hash_stable(&mut hcx, &mut hasher);
839+
let local_hash: u64 = hasher.finish();
840+
debug_assert_eq!(hash.local_hash(), local_hash);
841+
}
842+
843+
Ok(expn_id)
818844
}
819845
}
820846

@@ -990,8 +1016,7 @@ where
9901016
{
9911017
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
9921018
s.hygiene_context.schedule_expn_data_for_encoding(*self);
993-
self.krate.encode(s)?;
994-
self.local_id.as_u32().encode(s)
1019+
self.expn_hash().encode(s)
9951020
}
9961021
}
9971022

compiler/rustc_span/src/def_id.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl Borrow<Fingerprint> for DefPathHash {
136136
/// further trouble.
137137
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
138138
#[derive(HashStable_Generic, Encodable, Decodable)]
139-
pub struct StableCrateId(u64);
139+
pub struct StableCrateId(pub(crate) u64);
140140

141141
impl StableCrateId {
142142
pub fn to_u64(self) -> u64 {

0 commit comments

Comments
 (0)