Skip to content

Commit

Permalink
Encode trait impls using nested Tables
Browse files Browse the repository at this point in the history
We now decode trait impls DefIds only as needed.
  • Loading branch information
Aaron1011 committed Jul 27, 2020
1 parent fa36f96 commit 119c788
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 60 deletions.
20 changes: 5 additions & 15 deletions src/librustc_metadata/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ crate struct CrateMetadata {
/// quickly retrace a `DefPath`, which is needed for incremental
/// compilation support.
def_path_table: DefPathTable,
/// Trait impl data.
/// FIXME: Used only from queries and can use query cache,
/// so pre-decoding can probably be avoided.
trait_impls: FxHashMap<(u32, DefIndex), Lazy<[DefIndex]>>,
/// Proc macro descriptions for this crate, if it's a proc macro crate.
raw_proc_macros: Option<&'static [ProcMacro]>,
/// Source maps for code from the crate.
Expand Down Expand Up @@ -1304,17 +1300,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
None => None,
};

if let Some(filter) = filter {
if let Some(impls) = self.trait_impls.get(&filter) {
if let Some((cnum, index)) = filter {
if let Some(impls) =
self.root.tables.trait_impls.get(self, cnum).and_then(|t| t.get(self, index))
{
tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
} else {
&[]
}
} else {
tcx.arena.alloc_from_iter(
self.trait_impls
.values()
.flat_map(|impls| impls.decode(self).map(|idx| self.local_def_id(idx))),
self.root.all_trait_impls.decode(self).map(|idx| self.local_def_id(idx)),
)
}
}
Expand Down Expand Up @@ -1646,19 +1642,13 @@ impl CrateMetadata {
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
root.def_path_table.decode((&blob, sess))
});
let trait_impls = root
.impls
.decode((&blob, sess))
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
.collect();
let alloc_decoding_state =
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
CrateMetadata {
blob,
root,
def_path_table,
trait_impls,
raw_proc_macros,
source_map_import_info: OnceCell::new(),
alloc_decoding_state,
Expand Down
45 changes: 24 additions & 21 deletions src/librustc_metadata/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

// Encode the def IDs of impls, for coherence checking.
i = self.position();
let impls = self.encode_impls();
let all_trait_impls = self.encode_trait_impls();
let impl_bytes = self.position() - i;

let tcx = self.tcx;
Expand Down Expand Up @@ -677,12 +677,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
foreign_modules,
source_map,
def_path_table,
impls,
exported_symbols,
interpret_alloc_index,
tables,
syntax_contexts,
expn_data,
all_trait_impls,
});

let total_bytes = self.position();
Expand Down Expand Up @@ -1586,34 +1586,37 @@ impl EncodeContext<'a, 'tcx> {
self.lazy(&tcx.lang_items().missing)
}

/// Encodes an index, mapping each trait to its (local) implementations.
fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
fn encode_trait_impls(&mut self) -> Lazy<[DefIndex]> {
debug!("EncodeContext::encode_impls()");
let tcx = self.tcx;
let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() };
tcx.hir().krate().visit_all_item_likes(&mut visitor);

let mut all_impls: Vec<_> = visitor.impls.into_iter().collect();
let all_impls: Vec<_> = visitor.impls.into_iter().collect();
let mut all_trait_impls = Vec::new();

// Bring everything into deterministic order for hashing
all_impls.sort_by_cached_key(|&(trait_def_id, _)| tcx.def_path_hash(trait_def_id));
let mut table_map: FxHashMap<u32, TableBuilder<DefIndex, Lazy<[DefIndex]>>> =
Default::default();

let all_impls: Vec<_> = all_impls
.into_iter()
.map(|(trait_def_id, mut impls)| {
// Bring everything into deterministic order for hashing
impls.sort_by_cached_key(|&index| {
tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
});
for (trait_def_id, mut impls) in all_impls {
// Bring everything into deterministic order for hashing
impls.sort_by_cached_key(|&index| {
tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index })
});

TraitImpls {
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
impls: self.lazy(&impls),
}
})
.collect();
all_trait_impls.extend(&impls);

self.lazy(&all_impls)
table_map
.entry(trait_def_id.krate.as_u32())
.or_default()
.set(trait_def_id.index, self.lazy(&impls));
}

for (cnum, builder) in table_map {
let table = builder.encode(&mut self.opaque);
self.tables.trait_impls.set(cnum, table);
}
self.lazy(&all_trait_impls)
}

// Encodes all symbols exported from this crate into the metadata.
Expand Down
15 changes: 5 additions & 10 deletions src/librustc_metadata/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ crate struct CrateRoot<'tcx> {
native_libraries: Lazy<[NativeLib]>,
foreign_modules: Lazy<[ForeignModule]>,
def_path_table: Lazy<rustc_hir::definitions::DefPathTable>,
impls: Lazy<[TraitImpls]>,
all_trait_impls: Lazy<[DefIndex]>,
interpret_alloc_index: Lazy<[u32]>,

tables: LazyTables<'tcx>,
Expand Down Expand Up @@ -230,23 +230,17 @@ crate struct CrateDep {
pub extra_filename: String,
}

#[derive(RustcEncodable, RustcDecodable)]
crate struct TraitImpls {
trait_id: (u32, DefIndex),
impls: Lazy<[DefIndex]>,
}

/// Define `LazyTables` and `TableBuilders` at the same time.
macro_rules! define_tables {
($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
($($name:ident: Table<$I:ty, $T:ty>),+ $(,)?) => {
#[derive(RustcEncodable, RustcDecodable)]
crate struct LazyTables<'tcx> {
$($name: Lazy!(Table<DefIndex, $T>)),+
$($name: Lazy!(Table<$I, $T>)),+
}

#[derive(Default)]
struct TableBuilders<'tcx> {
$($name: TableBuilder<DefIndex, $T>),+
$($name: TableBuilder<$I, $T>),+
}

impl TableBuilders<'tcx> {
Expand Down Expand Up @@ -286,6 +280,7 @@ define_tables! {
mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u64>>>,
trait_impls: Table<u32, Lazy!(Table<DefIndex, Lazy!([DefIndex])>)>,
}

#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
Expand Down
38 changes: 24 additions & 14 deletions src/librustc_metadata/rmeta/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,34 @@ impl<T: Encodable> FixedSizeEncoding for Option<Lazy<T>> {
}
}

impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2);
macro_rules! meta_body {
($T:ident) => {
fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2);

fn from_bytes(b: &[u8]) -> Self {
Some(Lazy::from_position_and_meta(
<Option<Lazy<$T>>>::from_bytes(b)?.position,
u32::from_bytes(&b[u32::BYTE_LEN..]) as usize,
))
}

fn from_bytes(b: &[u8]) -> Self {
Some(Lazy::from_position_and_meta(
<Option<Lazy<T>>>::from_bytes(b)?.position,
u32::from_bytes(&b[u32::BYTE_LEN..]) as usize,
))
}
fn write_to_bytes(self, b: &mut [u8]) {
self.map(|lazy| Lazy::<$T>::from_position(lazy.position)).write_to_bytes(b);

fn write_to_bytes(self, b: &mut [u8]) {
self.map(|lazy| Lazy::<T>::from_position(lazy.position)).write_to_bytes(b);
let len = self.map_or(0, |lazy| lazy.meta);
let len: u32 = len.try_into().unwrap();

len.write_to_bytes(&mut b[u32::BYTE_LEN..]);
}
};
}

let len = self.map_or(0, |lazy| lazy.meta);
let len: u32 = len.try_into().unwrap();
impl<I: Idx, T: Encodable> FixedSizeEncoding for Option<Lazy<Table<I, Lazy<[T], usize>>, usize>> {
meta_body!(T);
}

len.write_to_bytes(&mut b[u32::BYTE_LEN..]);
}
impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
meta_body!(T);
}

/// Random-access table (i.e. offering constant-time `get`/`set`), similar to
Expand Down

0 comments on commit 119c788

Please sign in to comment.