Skip to content

Commit df57e28

Browse files
Aaron1011petrochenkov
authored andcommitted
Lazy decoding of DefPathTable from crate metadata (non-incremental case)
1 parent 527a685 commit df57e28

File tree

10 files changed

+104
-70
lines changed

10 files changed

+104
-70
lines changed

Diff for: src/librustc_hir/definitions.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use tracing::debug;
2323
/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
2424
/// stores the `DefIndex` of its parent.
2525
/// There is one `DefPathTable` for each crate.
26-
#[derive(Clone, Default, Decodable, Encodable)]
26+
#[derive(Clone, Default)]
2727
pub struct DefPathTable {
2828
index_to_key: IndexVec<DefIndex, DefKey>,
2929
def_path_hashes: IndexVec<DefIndex, DefPathHash>,
@@ -42,10 +42,6 @@ impl DefPathTable {
4242
index
4343
}
4444

45-
pub fn next_id(&self) -> DefIndex {
46-
DefIndex::from(self.index_to_key.len())
47-
}
48-
4945
#[inline(always)]
5046
pub fn def_key(&self, index: DefIndex) -> DefKey {
5147
self.index_to_key[index]
@@ -58,15 +54,25 @@ impl DefPathTable {
5854
hash
5955
}
6056

61-
pub fn add_def_path_hashes_to(&self, cnum: CrateNum, out: &mut FxHashMap<DefPathHash, DefId>) {
62-
out.extend(self.def_path_hashes.iter().enumerate().map(|(index, &hash)| {
63-
let def_id = DefId { krate: cnum, index: DefIndex::from(index) };
64-
(hash, def_id)
65-
}));
57+
pub fn num_def_ids(&self) -> usize {
58+
self.index_to_key.len()
6659
}
6760

68-
pub fn size(&self) -> usize {
69-
self.index_to_key.len()
61+
pub fn enumerated_keys_and_path_hashes(
62+
&self,
63+
) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + '_ {
64+
self.index_to_key
65+
.iter_enumerated()
66+
.map(move |(index, key)| (index, key, &self.def_path_hashes[index]))
67+
}
68+
69+
pub fn all_def_path_hashes_and_def_ids(
70+
&self,
71+
krate: CrateNum,
72+
) -> impl Iterator<Item = (DefPathHash, DefId)> + '_ {
73+
self.def_path_hashes
74+
.iter_enumerated()
75+
.map(move |(index, hash)| (*hash, DefId { krate, index }))
7076
}
7177
}
7278

Diff for: src/librustc_metadata/rmeta/decoder.rs

+45-21
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
1616
use rustc_hir as hir;
1717
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
1818
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
19-
use rustc_hir::definitions::DefPathTable;
2019
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
2120
use rustc_hir::lang_items;
2221
use rustc_index::vec::{Idx, IndexVec};
@@ -29,7 +28,6 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
2928
use rustc_middle::mir::{self, Body, Promoted};
3029
use rustc_middle::ty::codec::TyDecoder;
3130
use rustc_middle::ty::{self, Ty, TyCtxt};
32-
use rustc_middle::util::common::record_time;
3331
use rustc_serialize::{opaque, Decodable, Decoder};
3432
use rustc_session::Session;
3533
use rustc_span::hygiene::ExpnDataDecodeMode;
@@ -69,12 +67,6 @@ crate struct CrateMetadata {
6967
/// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
7068
/// is being used to decode those values.
7169
root: CrateRoot<'static>,
72-
/// For each definition in this crate, we encode a key. When the
73-
/// crate is loaded, we read all the keys and put them in this
74-
/// hashmap, which gives the reverse mapping. This allows us to
75-
/// quickly retrace a `DefPath`, which is needed for incremental
76-
/// compilation support.
77-
def_path_table: DefPathTable,
7870
/// Trait impl data.
7971
/// FIXME: Used only from queries and can use query cache,
8072
/// so pre-decoding can probably be avoided.
@@ -91,6 +83,10 @@ crate struct CrateMetadata {
9183
/// Do not access the value directly, as it might not have been initialized yet.
9284
/// The field must always be initialized to `DepNodeIndex::INVALID`.
9385
dep_node_index: AtomicCell<DepNodeIndex>,
86+
/// Caches decoded `DefKey`s.
87+
def_key_cache: Lock<FxHashMap<DefIndex, DefKey>>,
88+
/// Caches decoded `DefPathHash`es.
89+
def_path_hash_cache: Lock<FxHashMap<DefIndex, DefPathHash>>,
9490

9591
// --- Other significant crate properties ---
9692
/// ID of this crate, from the current compilation session's point of view.
@@ -807,7 +803,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
807803
data.has_auto_impl,
808804
data.is_marker,
809805
data.specialization_kind,
810-
self.def_path_table.def_path_hash(item_id),
806+
self.def_path_hash(item_id),
811807
)
812808
}
813809
EntryKind::TraitAlias => ty::TraitDef::new(
@@ -817,7 +813,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
817813
false,
818814
false,
819815
ty::trait_def::TraitSpecializationKind::None,
820-
self.def_path_table.def_path_hash(item_id),
816+
self.def_path_hash(item_id),
821817
),
822818
_ => bug!("def-index does not refer to trait or trait alias"),
823819
}
@@ -1509,12 +1505,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15091505

15101506
#[inline]
15111507
fn def_key(&self, index: DefIndex) -> DefKey {
1512-
let mut key = self.def_path_table.def_key(index);
1513-
if self.is_proc_macro(index) {
1514-
let name = self.raw_proc_macro(index).name();
1515-
key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
1516-
}
1517-
key
1508+
*self.def_key_cache.lock().entry(index).or_insert_with(|| {
1509+
let mut key = self.root.tables.def_keys.get(self, index).unwrap().decode(self);
1510+
if self.is_proc_macro(index) {
1511+
let name = self.raw_proc_macro(index).name();
1512+
key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name));
1513+
}
1514+
key
1515+
})
15181516
}
15191517

15201518
// Returns the path leading to the thing with this `id`.
@@ -1723,9 +1721,6 @@ impl CrateMetadata {
17231721
private_dep: bool,
17241722
host_hash: Option<Svh>,
17251723
) -> CrateMetadata {
1726-
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
1727-
root.def_path_table.decode((&blob, sess))
1728-
});
17291724
let trait_impls = root
17301725
.impls
17311726
.decode((&blob, sess))
@@ -1737,7 +1732,6 @@ impl CrateMetadata {
17371732
CrateMetadata {
17381733
blob,
17391734
root,
1740-
def_path_table,
17411735
trait_impls,
17421736
raw_proc_macros,
17431737
source_map_import_info: OnceCell::new(),
@@ -1752,6 +1746,8 @@ impl CrateMetadata {
17521746
host_hash,
17531747
extern_crate: Lock::new(None),
17541748
hygiene_context: Default::default(),
1749+
def_key_cache: Default::default(),
1750+
def_path_hash_cache: Default::default(),
17551751
}
17561752
}
17571753

@@ -1828,6 +1824,10 @@ impl CrateMetadata {
18281824
self.root.hash
18291825
}
18301826

1827+
fn num_def_ids(&self) -> usize {
1828+
self.root.tables.def_keys.size()
1829+
}
1830+
18311831
fn local_def_id(&self, index: DefIndex) -> DefId {
18321832
DefId { krate: self.cnum, index }
18331833
}
@@ -1843,10 +1843,34 @@ impl CrateMetadata {
18431843

18441844
None
18451845
}
1846+
}
1847+
1848+
impl<'a, 'tcx> CrateMetadataRef<'a> {
1849+
fn def_path_hash_unlocked(
1850+
&self,
1851+
index: DefIndex,
1852+
def_path_hashes: &mut FxHashMap<DefIndex, DefPathHash>,
1853+
) -> DefPathHash {
1854+
*def_path_hashes.entry(index).or_insert_with(|| {
1855+
self.root.tables.def_path_hashes.get(self, index).unwrap().decode(self)
1856+
})
1857+
}
18461858

18471859
#[inline]
18481860
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
1849-
self.def_path_table.def_path_hash(index)
1861+
let mut def_path_hashes = self.def_path_hash_cache.lock();
1862+
self.def_path_hash_unlocked(index, &mut def_path_hashes)
1863+
}
1864+
1865+
fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
1866+
let mut result = Vec::new();
1867+
let mut def_path_hashes = self.def_path_hash_cache.lock();
1868+
for index in 0..self.num_def_ids() {
1869+
let index = DefIndex::from_usize(index);
1870+
let def_path_hash = self.def_path_hash_unlocked(index, &mut def_path_hashes);
1871+
result.push((def_path_hash, self.local_def_id(index)));
1872+
}
1873+
result
18501874
}
18511875

18521876
/// Get the `DepNodeIndex` corresponding this crate. The result of this

Diff for: src/librustc_metadata/rmeta/decoder/cstore_impl.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_ast::expand::allocator::AllocatorKind;
99
use rustc_data_structures::svh::Svh;
1010
use rustc_hir as hir;
1111
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
12-
use rustc_hir::definitions::DefPathTable;
1312
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
1413
use rustc_middle::hir::exports::Export;
1514
use rustc_middle::middle::cstore::{CrateSource, CrateStore, EncodedMetadata};
@@ -486,8 +485,12 @@ impl CrateStore for CStore {
486485
self.get_crate_data(def.krate).def_path_hash(def.index)
487486
}
488487

489-
fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
490-
&self.get_crate_data(cnum).cdata.def_path_table
488+
fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)> {
489+
self.get_crate_data(cnum).all_def_path_hashes_and_def_ids()
490+
}
491+
492+
fn num_def_ids(&self, cnum: CrateNum) -> usize {
493+
self.get_crate_data(cnum).num_def_ids()
491494
}
492495

493496
fn crates_untracked(&self) -> Vec<CrateNum> {

Diff for: src/librustc_metadata/rmeta/encoder.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_data_structures::sync::{join, Lrc};
99
use rustc_hir as hir;
1010
use rustc_hir::def::CtorKind;
1111
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
12-
use rustc_hir::definitions::DefPathTable;
1312
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
1413
use rustc_hir::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
1514
use rustc_hir::lang_items;
@@ -418,9 +417,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
418417
}
419418
}
420419

421-
fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
422-
let definitions = self.tcx.hir().definitions();
423-
self.lazy(definitions.def_path_table())
420+
fn encode_def_path_table(&mut self) {
421+
let table = self.tcx.hir().definitions().def_path_table();
422+
for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
423+
let def_key = self.lazy(def_key);
424+
let def_path_hash = self.lazy(def_path_hash);
425+
self.tables.def_keys.set(def_index, def_key);
426+
self.tables.def_path_hashes.set(def_index, def_path_hash);
427+
}
424428
}
425429

426430
fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
@@ -525,7 +529,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
525529

526530
// Encode DefPathTable
527531
i = self.position();
528-
let def_path_table = self.encode_def_path_table();
532+
self.encode_def_path_table();
529533
let def_path_table_bytes = self.position() - i;
530534

531535
// Encode the def IDs of impls, for coherence checking.
@@ -642,7 +646,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
642646
native_libraries,
643647
foreign_modules,
644648
source_map,
645-
def_path_table,
646649
impls,
647650
exported_symbols,
648651
interpret_alloc_index,

Diff for: src/librustc_metadata/rmeta/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use rustc_data_structures::svh::Svh;
77
use rustc_data_structures::sync::MetadataRef;
88
use rustc_hir as hir;
99
use rustc_hir::def::CtorKind;
10-
use rustc_hir::def_id::{DefId, DefIndex};
10+
use rustc_hir::def_id::{DefId, DefIndex, DefPathHash};
11+
use rustc_hir::definitions::DefKey;
1112
use rustc_hir::lang_items;
1213
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
1314
use rustc_middle::hir::exports::Export;
@@ -195,7 +196,6 @@ crate struct CrateRoot<'tcx> {
195196
diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
196197
native_libraries: Lazy<[NativeLib]>,
197198
foreign_modules: Lazy<[ForeignModule]>,
198-
def_path_table: Lazy<rustc_hir::definitions::DefPathTable>,
199199
impls: Lazy<[TraitImpls]>,
200200
interpret_alloc_index: Lazy<[u32]>,
201201

@@ -285,6 +285,12 @@ define_tables! {
285285
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
286286
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
287287
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
288+
// `def_keys` and `def_path_hashes` represent a lazy version of a
289+
// `DefPathTable`. This allows us to avoid deserializing an entire
290+
// `DefPathTable` up front, since we may only ever use a few
291+
// definitions from any given crate.
292+
def_keys: Table<DefIndex, Lazy<DefKey>>,
293+
def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>
288294
}
289295

290296
#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]

Diff for: src/librustc_metadata/rmeta/table.rs

+5
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,9 @@ where
201201
let bytes = &metadata.raw_bytes()[start..start + self.meta];
202202
<Option<T>>::maybe_read_from_bytes_at(bytes, i.index())?
203203
}
204+
205+
/// Size of the table in entries, including possible gaps.
206+
pub(super) fn size(&self) -> usize {
207+
self.meta / <Option<T>>::BYTE_LEN
208+
}
204209
}

Diff for: src/librustc_middle/middle/cstore.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
99
use rustc_data_structures::svh::Svh;
1010
use rustc_data_structures::sync::{self, MetadataRef};
1111
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
12-
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, DefPathTable};
12+
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
1313
use rustc_macros::HashStable;
1414
use rustc_session::search_paths::PathKind;
1515
use rustc_session::utils::NativeLibKind;
@@ -187,7 +187,8 @@ pub trait CrateStore {
187187
fn def_key(&self, def: DefId) -> DefKey;
188188
fn def_path(&self, def: DefId) -> DefPath;
189189
fn def_path_hash(&self, def: DefId) -> DefPathHash;
190-
fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable;
190+
fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
191+
fn num_def_ids(&self, cnum: CrateNum) -> usize;
191192

192193
// "queries" used in resolve that aren't tracked for incremental compilation
193194
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;

Diff for: src/librustc_middle/ty/context.rs

+6-13
Original file line numberDiff line numberDiff line change
@@ -1102,20 +1102,13 @@ impl<'tcx> TyCtxt<'tcx> {
11021102
providers[LOCAL_CRATE] = local_providers;
11031103

11041104
let def_path_hash_to_def_id = if s.opts.build_dep_graph() {
1105-
let def_path_tables = crates
1106-
.iter()
1107-
.map(|&cnum| (cnum, cstore.def_path_table(cnum)))
1108-
.chain(iter::once((LOCAL_CRATE, definitions.def_path_table())));
1105+
let capacity = definitions.def_path_table().num_def_ids()
1106+
+ crates.iter().map(|cnum| cstore.num_def_ids(*cnum)).sum::<usize>();
1107+
let mut map = FxHashMap::with_capacity_and_hasher(capacity, Default::default());
11091108

1110-
// Precompute the capacity of the hashmap so we don't have to
1111-
// re-allocate when populating it.
1112-
let capacity = def_path_tables.clone().map(|(_, t)| t.size()).sum::<usize>();
1113-
1114-
let mut map: FxHashMap<_, _> =
1115-
FxHashMap::with_capacity_and_hasher(capacity, ::std::default::Default::default());
1116-
1117-
for (cnum, def_path_table) in def_path_tables {
1118-
def_path_table.add_def_path_hashes_to(cnum, &mut map);
1109+
map.extend(definitions.def_path_table().all_def_path_hashes_and_def_ids(LOCAL_CRATE));
1110+
for cnum in &crates {
1111+
map.extend(cstore.all_def_path_hashes_and_def_ids(*cnum).into_iter());
11191112
}
11201113

11211114
Some(map)

Diff for: src/librustc_session/session.rs

-7
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,6 @@ pub struct Session {
218218
pub struct PerfStats {
219219
/// The accumulated time spent on computing symbol hashes.
220220
pub symbol_hash_time: Lock<Duration>,
221-
/// The accumulated time spent decoding def path tables from metadata.
222-
pub decode_def_path_tables_time: Lock<Duration>,
223221
/// Total number of values canonicalized queries constructed.
224222
pub queries_canonicalized: AtomicUsize,
225223
/// Number of times this query is invoked.
@@ -862,10 +860,6 @@ impl Session {
862860
"Total time spent computing symbol hashes: {}",
863861
duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock())
864862
);
865-
println!(
866-
"Total time spent decoding DefPath tables: {}",
867-
duration_to_secs_str(*self.perf_stats.decode_def_path_tables_time.lock())
868-
);
869863
println!(
870864
"Total queries canonicalized: {}",
871865
self.perf_stats.queries_canonicalized.load(Ordering::Relaxed)
@@ -1339,7 +1333,6 @@ pub fn build_session(
13391333
prof,
13401334
perf_stats: PerfStats {
13411335
symbol_hash_time: Lock::new(Duration::from_secs(0)),
1342-
decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
13431336
queries_canonicalized: AtomicUsize::new(0),
13441337
normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0),
13451338
normalize_projection_ty: AtomicUsize::new(0),

0 commit comments

Comments
 (0)