Directly encode DefId in metadata.

This commit is contained in:
Camille GILLOT 2022-04-10 00:16:55 +02:00
parent 6142f50845
commit b9287a83c5
4 changed files with 77 additions and 10 deletions

View File

@ -388,6 +388,17 @@ fn decode_query(
}
}
impl<'a, 'tcx> LazyQueryDecodable<'a, 'tcx, Option<DefId>> for Option<RawDefId> {
fn decode_query(
self,
cdata: CrateMetadataRef<'a>,
_: TyCtxt<'tcx>,
_: impl FnOnce() -> !,
) -> Option<DefId> {
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 @@ pub fn cdata(&self) -> CrateMetadataRef<'a> {
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<T: ?Sized + LazyMeta>(&mut self, meta: T::Meta) -> Lazy<T> {
@ -718,8 +730,7 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
}
}
impl<'a, 'tcx, I: Idx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
for Lazy<Table<I, T>>
impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for Lazy<Table<I, T>>
where
Option<T>: FixedSizeEncoding,
{
@ -856,6 +867,11 @@ fn maybe_kind(self, item_id: DefIndex) -> Option<EntryKind> {
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!(

View File

@ -147,8 +147,7 @@ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
}
}
impl<'a, 'tcx, I: Idx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
for Lazy<Table<I, T>>
impl<'a, 'tcx, I: Idx, T> Encodable<EncodeContext<'a, 'tcx>> for Lazy<Table<I, T>>
where
Option<T>: FixedSizeEncoding,
{
@ -1285,7 +1284,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'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());
}
}

View File

@ -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::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 @@ macro_rules! Lazy {
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<RawDefId> 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 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
thir_abstract_const: Table<DefIndex, Lazy!(&'tcx [thir::abstract_const::Node<'tcx>])>,
impl_parent: Table<DefIndex, Lazy!(DefId)>,
impl_parent: Table<DefIndex, RawDefId>,
impl_polarity: Table<DefIndex, ty::ImplPolarity>,
impl_constness: Table<DefIndex, hir::Constness>,
impl_defaultness: Table<DefIndex, hir::Defaultness>,
@ -322,7 +346,7 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
generator_kind: Table<DefIndex, Lazy!(hir::GeneratorKind)>,
trait_def: Table<DefIndex, Lazy!(ty::TraitDef)>,
trait_item_def_id: Table<DefIndex, Lazy<DefId>>,
trait_item_def_id: Table<DefIndex, RawDefId>,
inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
expn_that_defined: Table<DefIndex, Lazy<ExpnId>>,
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,

View File

@ -200,6 +200,34 @@ fn write_to_bytes(self, b: &mut [u8]) {
}
}
// We directly encode RawDefId because using a `Lazy` would incur a 50% overhead in the worst case.
impl FixedSizeEncoding for Option<RawDefId> {
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<T>` impl, but in the general case we might not need / want to
// fit every `usize` in `u32`.