diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c2ec9115d31..c640e411f63 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,7 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob}; use crate::schema::*; -use crate::table::Table; +use crate::table::PerDefTable; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; @@ -255,10 +255,10 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, } } -impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> +impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> where T: LazyMeta, { - fn specialized_decode(&mut self) -> Result>, Self::Error> { + fn specialized_decode(&mut self) -> Result>, Self::Error> { let len = self.read_usize()?; self.read_lazy_with_meta(len) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 53d3039a284..df99541df58 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ use crate::schema::*; -use crate::table::Table; +use crate::table::PerDefTable; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_table: Table>, + entries_table: PerDefTable>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -114,10 +114,10 @@ impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { } } -impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> +impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> where T: LazyMeta, { - fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { + fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; self.emit_lazy_distance(*lazy) } @@ -1925,7 +1925,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_table: Table::new(tcx.hir().definitions().def_index_count()), + entries_table: PerDefTable::new(tcx.hir().definitions().def_index_count()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 6ae20a9d438..dffc8f33b2d 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::table::Table; +use crate::table::PerDefTable; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -162,6 +162,7 @@ crate enum LazyState { // Only needed when `T` itself contains a parameter (e.g. `'tcx`). macro_rules! Lazy { (Table<$T:ty>) => {Lazy, usize>}; + (PerDefTable<$T:ty>) => {Lazy, usize>}; ([$T:ty]) => {Lazy<[$T], usize>}; ($T:ty) => {Lazy<$T, ()>}; } @@ -196,7 +197,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!(Table>), + pub entries_table: Lazy!(PerDefTable>), /// The DefIndex's of any proc macros delcared by /// this crate diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index e18535060e6..c60c8e2cbce 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -73,44 +73,41 @@ impl FixedSizeEncoding for u32 { /// (e.g. while visiting the definitions of a crate), and on-demand decoding /// of specific indices (e.g. queries for per-definition data). /// Similar to `Vec>`, but with zero-copy decoding. +// FIXME(eddyb) newtype `[u8]` here, such that `Box>` would be used +// when building it, and `Lazy>` or `&Table` when reading it. +// Sadly, that doesn't work for `DefPerTable`, which is `(Table, Table)`, +// and so would need two lengths in its metadata, which is not supported yet. crate struct Table> { - positions: Vec, + bytes: Vec, _marker: PhantomData, } impl> Table { - crate fn new(max_index: usize) -> Self { + crate fn new(len: usize) -> Self { Table { - positions: vec![0; max_index * 4], + bytes: vec![0; len * 4], _marker: PhantomData, } } - crate fn record(&mut self, def_id: DefId, entry: Lazy) { - assert!(def_id.is_local()); - self.record_index(def_id.index, entry); - } - - crate fn record_index(&mut self, item: DefIndex, entry: Lazy) { + crate fn record(&mut self, i: usize, entry: Lazy) { let position: u32 = entry.position.get().try_into().unwrap(); - let array_index = item.index(); - let positions = &mut self.positions; - assert!(u32::read_from_bytes_at(positions, array_index) == 0, - "recorded position for item {:?} twice, first at {:?} and now at {:?}", - item, - u32::read_from_bytes_at(positions, array_index), + assert!(u32::read_from_bytes_at(&self.bytes, i) == 0, + "recorded position for index {:?} twice, first at {:?} and now at {:?}", + i, + u32::read_from_bytes_at(&self.bytes, i), position); - position.write_to_bytes_at(positions, array_index) + position.write_to_bytes_at(&mut self.bytes, i) } crate fn encode(&self, buf: &mut Encoder) -> Lazy { let pos = buf.position(); - buf.emit_raw_bytes(&self.positions); + buf.emit_raw_bytes(&self.bytes); Lazy::from_position_and_meta( NonZeroUsize::new(pos as usize).unwrap(), - self.positions.len() / 4, + self.bytes.len(), ) } } @@ -119,22 +116,62 @@ impl> LazyMeta for Table { type Meta = usize; fn min_size(len: usize) -> usize { - len * 4 + len } } impl Lazy> { - /// Given the metadata, extract out the offset of a particular - /// DefIndex (if any). + /// Given the metadata, extract out the offset of a particular index (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { - debug!("Table::lookup: index={:?} len={:?}", - def_index, - self.meta); + crate fn lookup(&self, bytes: &[u8], i: usize) -> Option> { + debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - let bytes = &bytes[self.position.get()..][..self.meta * 4]; - let position = u32::read_from_bytes_at(bytes, def_index.index()); + let bytes = &bytes[self.position.get()..][..self.meta]; + let position = u32::read_from_bytes_at(bytes, i); debug!("Table::lookup: position={:?}", position); + NonZeroUsize::new(position as usize).map(Lazy::from_position) } } + + +/// Per-definition table, similar to `Table` but keyed on `DefIndex`. +// FIXME(eddyb) replace by making `Table` behave like `IndexVec`, +// and by using `newtype_index!` to define `DefIndex`. +crate struct PerDefTable>(Table); + +impl> PerDefTable { + crate fn new(def_index_count: usize) -> Self { + PerDefTable(Table::new(def_index_count)) + } + + crate fn record(&mut self, def_id: DefId, entry: Lazy) { + assert!(def_id.is_local()); + self.0.record(def_id.index.index(), entry); + } + + crate fn encode(&self, buf: &mut Encoder) -> Lazy { + let lazy = self.0.encode(buf); + Lazy::from_position_and_meta(lazy.position, lazy.meta) + } +} + +impl> LazyMeta for PerDefTable { + type Meta = as LazyMeta>::Meta; + + fn min_size(meta: Self::Meta) -> usize { + Table::::min_size(meta) + } +} + +impl Lazy> { + fn as_table(&self) -> Lazy> { + Lazy::from_position_and_meta(self.position, self.meta) + } + + /// Given the metadata, extract out the offset of a particular DefIndex (if any). + #[inline(never)] + crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { + self.as_table().lookup(bytes, def_index.index()) + } +}