diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2019-04-13 23:30:53 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2019-10-15 18:23:51 +0300 |
| commit | cef495028019b5bbb380bfa1d7a10e9e06dbf166 (patch) | |
| tree | 90d4903ae2df9c398147d8889f0beb206c721327 | |
| parent | 677f0df63b7f39c3b22a84004c1697e85743c470 (diff) | |
| download | rust-cef495028019b5bbb380bfa1d7a10e9e06dbf166.tar.gz rust-cef495028019b5bbb380bfa1d7a10e9e06dbf166.zip | |
rustc_metadata: generalize Table<T> to hold T, not Lazy<T>, elements.
| -rw-r--r-- | src/librustc_metadata/decoder.rs | 6 | ||||
| -rw-r--r-- | src/librustc_metadata/encoder.rs | 10 | ||||
| -rw-r--r-- | src/librustc_metadata/schema.rs | 2 | ||||
| -rw-r--r-- | src/librustc_metadata/table.rs | 108 |
4 files changed, 78 insertions, 48 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 7ba395a1bd5..f1ae0487529 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::PerDefTable; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; @@ -256,7 +256,7 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, } impl<'a, 'tcx, T> SpecializedDecoder<Lazy<PerDefTable<T>>> for DecodeContext<'a, 'tcx> - where T: LazyMeta<Meta = ()>, + where Option<T>: FixedSizeEncoding, { fn specialized_decode(&mut self) -> Result<Lazy<PerDefTable<T>>, Self::Error> { let len = self.read_usize()?; @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> { - self.root.per_def.entry.lookup(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.get(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 51634e372a2..c9426aaece9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ use crate::schema::*; -use crate::table::PerDefTable; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -61,7 +61,7 @@ struct EncodeContext<'tcx> { } struct PerDefTables<'tcx> { - entry: PerDefTable<Entry<'tcx>>, + entry: PerDefTable<Lazy<Entry<'tcx>>>, } macro_rules! encoder_methods { @@ -119,7 +119,7 @@ impl<'tcx, T: Encodable> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> { } impl<'tcx, T> SpecializedEncoder<Lazy<PerDefTable<T>>> for EncodeContext<'tcx> - where T: LazyMeta<Meta = ()>, + where Option<T>: FixedSizeEncoding, { fn specialized_encode(&mut self, lazy: &Lazy<PerDefTable<T>>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; @@ -280,14 +280,14 @@ impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I } } -// Shorthand for `$self.$tables.$table.record($key, $self.lazy($value))`, which would +// Shorthand for `$self.$tables.$table.set($key, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident.$table:ident[$key:expr] <- $value:expr) => {{ { let value = $value; let lazy = $self.lazy(value); - $self.$tables.$table.record($key, lazy); + $self.$tables.$table.set($key, lazy); } }} } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 9d6748732b8..e70ba2532ca 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -229,7 +229,7 @@ crate struct TraitImpls { #[derive(RustcEncodable, RustcDecodable)] crate struct LazyPerDefTables<'tcx> { - pub entry: Lazy!(PerDefTable<Entry<'tcx>>), + pub entry: Lazy!(PerDefTable<Lazy<Entry<'tcx>>>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c60c8e2cbce..c069ea2830c 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -8,7 +8,10 @@ use std::num::NonZeroUsize; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. -trait FixedSizeEncoding { +/// Used mainly for Lazy positions and lengths. +/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, +/// but this has no impact on safety. +crate trait FixedSizeEncoding: Default { const BYTE_LEN: usize; // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, @@ -38,7 +41,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults { b.len() / BYTE_LEN, ) }; - Self::from_bytes(&b[i]) + FixedSizeEncoding::from_bytes(&b[i]) } fn write_to_bytes_at(self, b: &mut [u8], i: usize) { const BYTE_LEN: usize = $byte_len; @@ -69,37 +72,69 @@ impl FixedSizeEncoding for u32 { } } -/// Random-access position table, allowing encoding in an arbitrary order -/// (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<Lazy<T>>`, but with zero-copy decoding. -// FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used +// 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`. +impl<T: Encodable> FixedSizeEncoding for Option<Lazy<T>> { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position(NonZeroUsize::new(u32::from_bytes(b) as usize)?)) + } + + fn write_to_bytes(self, b: &mut [u8]) { + let position = self.map_or(0, |lazy| lazy.position.get()); + let position: u32 = position.try_into().unwrap(); + + position.write_to_bytes(b) + } +} + +impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> { + 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 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..]); + } +} + +/// Random-access table, similar to `Vec<Option<T>>`, but without requiring +/// encoding or decoding all the values eagerly and in-order. +// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used // when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it. // Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`, // and so would need two lengths in its metadata, which is not supported yet. -crate struct Table<T: LazyMeta<Meta = ()>> { +crate struct Table<T> where Option<T>: FixedSizeEncoding { + // FIXME(eddyb) store `[u8; <Option<T>>::BYTE_LEN]` instead of `u8` in `Vec`, + // once that starts being allowed by the compiler (i.e. lazy normalization). bytes: Vec<u8>, _marker: PhantomData<T>, } -impl<T: LazyMeta<Meta = ()>> Table<T> { +impl<T> Table<T> where Option<T>: FixedSizeEncoding { crate fn new(len: usize) -> Self { Table { - bytes: vec![0; len * 4], + // FIXME(eddyb) only allocate and encode as many entries as needed. + bytes: vec![0; len * <Option<T>>::BYTE_LEN], _marker: PhantomData, } } - crate fn record(&mut self, i: usize, entry: Lazy<T>) { - let position: u32 = entry.position.get().try_into().unwrap(); - - 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(&mut self.bytes, i) + crate fn set(&mut self, i: usize, value: T) { + Some(value).write_to_bytes_at(&mut self.bytes, i); } crate fn encode(&self, buf: &mut Encoder) -> Lazy<Self> { @@ -112,7 +147,7 @@ impl<T: LazyMeta<Meta = ()>> Table<T> { } } -impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> { +impl<T> LazyMeta for Table<T> where Option<T>: FixedSizeEncoding { type Meta = usize; fn min_size(len: usize) -> usize { @@ -120,34 +155,29 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> { } } -impl<T: Encodable> Lazy<Table<T>> { - /// Given the metadata, extract out the offset of a particular index (if any). +impl<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding { + /// Given the metadata, extract out the value at a particular index (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], i: usize) -> Option<Lazy<T>> { + crate fn get(&self, bytes: &[u8], i: usize) -> Option<T> { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - 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) + <Option<T>>::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i) } } - /// 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<T: LazyMeta<Meta = ()>>(Table<T>); +crate struct PerDefTable<T>(Table<T>) where Option<T>: FixedSizeEncoding; -impl<T: LazyMeta<Meta = ()>> PerDefTable<T> { +impl<T> PerDefTable<T> where Option<T>: FixedSizeEncoding { crate fn new(def_index_count: usize) -> Self { PerDefTable(Table::new(def_index_count)) } - crate fn record(&mut self, def_id: DefId, entry: Lazy<T>) { + crate fn set(&mut self, def_id: DefId, value: T) { assert!(def_id.is_local()); - self.0.record(def_id.index.index(), entry); + self.0.set(def_id.index.index(), value); } crate fn encode(&self, buf: &mut Encoder) -> Lazy<Self> { @@ -156,7 +186,7 @@ impl<T: LazyMeta<Meta = ()>> PerDefTable<T> { } } -impl<T: LazyMeta<Meta = ()>> LazyMeta for PerDefTable<T> { +impl<T> LazyMeta for PerDefTable<T> where Option<T>: FixedSizeEncoding { type Meta = <Table<T> as LazyMeta>::Meta; fn min_size(meta: Self::Meta) -> usize { @@ -164,14 +194,14 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for PerDefTable<T> { } } -impl<T: Encodable> Lazy<PerDefTable<T>> { +impl<T> Lazy<PerDefTable<T>> where Option<T>: FixedSizeEncoding { fn as_table(&self) -> Lazy<Table<T>> { Lazy::from_position_and_meta(self.position, self.meta) } - /// Given the metadata, extract out the offset of a particular DefIndex (if any). + /// Given the metadata, extract out the value at a particular DefIndex (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> { - self.as_table().lookup(bytes, def_index.index()) + crate fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option<T> { + self.as_table().get(bytes, def_index.index()) } } |
