From b9287a83c5691568827f056bea0241a0bdb72f18 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 10 Apr 2022 00:16:55 +0200 Subject: [PATCH] Directly encode DefId in metadata. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 22 ++++++++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 7 ++--- compiler/rustc_metadata/src/rmeta/mod.rs | 30 ++++++++++++++++++-- compiler/rustc_metadata/src/rmeta/table.rs | 28 ++++++++++++++++++ 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 7b500f1565d..3933a0d19a4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -388,6 +388,17 @@ impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option> } } +impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option> for Option { + fn decode_query( + self, + cdata: CrateMetadataRef<'a>, + _: TyCtxt<'tcx>, + _: impl FnOnce() -> !, + ) -> Option { + self.map(|raw_def_id| raw_def_id.decode(cdata)) + } +} + impl<'a, 'tcx> DecodeContext<'a, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -406,8 +417,9 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.cdata.unwrap() } + #[inline] fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { - if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] } + self.cdata().map_encoded_cnum_to_current(cnum) } fn read_lazy_with_meta(&mut self, meta: T::Meta) -> Lazy { @@ -718,8 +730,7 @@ impl<'a, 'tcx, T: Decodable>> Decodable>> Decodable> - for Lazy> +impl<'a, 'tcx, I: Idx, T> Decodable> for Lazy> where Option: FixedSizeEncoding, { @@ -856,6 +867,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.kind.get(self, item_id).map(|k| k.decode(self)) } + #[inline] + pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum { + if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] } + } + fn kind(self, item_id: DefIndex) -> EntryKind { self.maybe_kind(item_id).unwrap_or_else(|| { bug!( diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index be10ad490e1..e967750aebb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -147,8 +147,7 @@ impl<'a, 'tcx, T: Encodable>> Encodable>> Encodable> - for Lazy> +impl<'a, 'tcx, I: Idx, T> Encodable> for Lazy> where Option: FixedSizeEncoding, { @@ -1285,7 +1284,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_ident_span(def_id, impl_item.ident(self.tcx)); self.encode_item_type(def_id); if let Some(trait_item_def_id) = impl_item.trait_item_def_id { - record!(self.tables.trait_item_def_id[def_id] <- trait_item_def_id); + self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into()); } if impl_item.kind == ty::AssocKind::Fn { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); @@ -1457,7 +1456,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let trait_def = self.tcx.trait_def(trait_ref.def_id); if let Some(mut an) = trait_def.ancestors(self.tcx, def_id).ok() { if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { - record!(self.tables.impl_parent[def_id] <- parent); + self.tables.impl_parent.set(def_id.index, parent.into()); } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 37340ee3268..43ccfc64e05 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,3 +1,4 @@ +use crate::creader::CrateMetadataRef; use decoder::Metadata; use def_path_hash_map::DefPathHashMapRef; use table::{Table, TableBuilder}; @@ -8,7 +9,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::def_id::{DefId, DefIndex, DefPathHash, StableCrateId}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::lang_items; use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; @@ -237,6 +238,29 @@ crate struct CrateRoot<'tcx> { symbol_mangling_version: SymbolManglingVersion, } +/// On-disk representation of `DefId`. +/// This creates a type-safe way to enforce that we remap the CrateNum between the on-disk +/// representation and the compilation session. +#[derive(Copy, Clone)] +crate struct RawDefId { + krate: u32, + index: u32, +} + +impl Into for DefId { + fn into(self) -> RawDefId { + RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() } + } +} + +impl RawDefId { + fn decode(self, cdata: CrateMetadataRef<'_>) -> DefId { + let krate = CrateNum::from_u32(self.krate); + let krate = cdata.map_encoded_cnum_to_current(krate); + DefId { krate, index: DefIndex::from_u32(self.index) } + } +} + #[derive(Encodable, Decodable)] crate struct CrateDep { pub name: Symbol, @@ -309,7 +333,7 @@ define_tables! { mir_for_ctfe: Table)>, promoted_mir: Table>)>, thir_abstract_const: Table])>, - impl_parent: Table, + impl_parent: Table, impl_polarity: Table, impl_constness: Table, impl_defaultness: Table, @@ -322,7 +346,7 @@ define_tables! { generator_kind: Table, trait_def: Table, - trait_item_def_id: Table>, + trait_item_def_id: Table, inherent_impls: Table>, expn_that_defined: Table>, unused_generic_params: Table>>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 3e0aa0728df..b336649d366 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -200,6 +200,34 @@ impl FixedSizeEncoding for Option { } } +// We directly encode RawDefId because using a `Lazy` would incur a 50% overhead in the worst case. +impl FixedSizeEncoding for Option { + fixed_size_encoding_byte_len_and_defaults!(2 * u32::BYTE_LEN); + + #[inline] + fn from_bytes(b: &[u8]) -> Self { + let krate = u32::from_bytes(&b[0..4]); + let index = u32::from_bytes(&b[4..8]); + if krate == 0 { + return None; + } + Some(RawDefId { krate: krate - 1, index }) + } + + #[inline] + fn write_to_bytes(self, b: &mut [u8]) { + match self { + None => 0u32.write_to_bytes(b), + Some(RawDefId { krate, index }) => { + // CrateNum is less than `CrateNum::MAX_AS_U32`. + debug_assert!(krate < u32::MAX); + (1 + krate).write_to_bytes(&mut b[0..4]); + index.write_to_bytes(&mut b[4..8]); + } + } + } +} + // NOTE(eddyb) there could be an impl for `usize`, which would enable a more // generic `Lazy` impl, but in the general case we might not need / want to // fit every `usize` in `u32`.