From 34066d60c38b8e1049a60e1eaf26cd84a67e7655 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 05:21:39 +0300 Subject: [PATCH] rustc_metadata: don't use more space than needed, for each Table. --- src/librustc_metadata/encoder.rs | 22 ++-------------------- src/librustc_metadata/table.rs | 32 +++++++++++++++++++------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3bc3fee4164f..f1436e4c09df 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -60,6 +60,7 @@ struct EncodeContext<'tcx> { source_file_cache: Lrc, } +#[derive(Default)] struct PerDefTables<'tcx> { kind: PerDefTable>>, visibility: PerDefTable>, @@ -1774,29 +1775,10 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { // Since encoding metadata is not in a query, and nothing is cached, // there's no need to do dep-graph tracking for any of it. let (root, mut result) = tcx.dep_graph.with_ignore(move || { - let def_count = tcx.hir().definitions().def_index_count(); let mut ecx = EncodeContext { opaque: encoder, tcx, - per_def: PerDefTables { - kind: PerDefTable::new(def_count), - visibility: PerDefTable::new(def_count), - span: PerDefTable::new(def_count), - attributes: PerDefTable::new(def_count), - children: PerDefTable::new(def_count), - stability: PerDefTable::new(def_count), - deprecation: PerDefTable::new(def_count), - - ty: PerDefTable::new(def_count), - inherent_impls: PerDefTable::new(def_count), - variances: PerDefTable::new(def_count), - generics: PerDefTable::new(def_count), - predicates: PerDefTable::new(def_count), - predicates_defined_on: PerDefTable::new(def_count), - - mir: PerDefTable::new(def_count), - promoted_mir: PerDefTable::new(def_count), - }, + per_def: Default::default(), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 0585aa1d3884..5cfa137d04f7 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -23,7 +23,7 @@ crate trait FixedSizeEncoding: Default { // FIXME(eddyb) make these generic functions, or at least defaults here. // (same problem as above, needs `[u8; Self::BYTE_LEN]`) // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used. - fn read_from_bytes_at(b: &[u8], i: usize) -> Self; + fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option; fn write_to_bytes_at(self, b: &mut [u8], i: usize); } @@ -31,7 +31,7 @@ crate trait FixedSizeEncoding: Default { macro_rules! fixed_size_encoding_byte_len_and_defaults { ($byte_len:expr) => { const BYTE_LEN: usize = $byte_len; - fn read_from_bytes_at(b: &[u8], i: usize) -> Self { + fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option { const BYTE_LEN: usize = $byte_len; // HACK(eddyb) ideally this would be done with fully safe code, // but slicing `[u8]` with `i * N..` is optimized worse, due to the @@ -42,7 +42,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults { b.len() / BYTE_LEN, ) }; - FixedSizeEncoding::from_bytes(&b[i]) + b.get(i).map(|b| FixedSizeEncoding::from_bytes(b)) } fn write_to_bytes_at(self, b: &mut [u8], i: usize) { const BYTE_LEN: usize = $byte_len; @@ -116,8 +116,7 @@ impl FixedSizeEncoding for Option> { /// encoding or decoding all the values eagerly and in-order. // FIXME(eddyb) replace `Vec` with `[_]` 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. +// (not sure if that is possible given that the `Vec` is being resized now) crate struct Table where Option: FixedSizeEncoding { // FIXME(eddyb) store `[u8; >::BYTE_LEN]` instead of `u8` in `Vec`, // once that starts being allowed by the compiler (i.e. lazy normalization). @@ -125,16 +124,21 @@ crate struct Table where Option: FixedSizeEncoding { _marker: PhantomData, } -impl Table where Option: FixedSizeEncoding { - crate fn new(len: usize) -> Self { +impl Default for Table where Option: FixedSizeEncoding { + fn default() -> Self { Table { - // FIXME(eddyb) only allocate and encode as many entries as needed. - bytes: vec![0; len * >::BYTE_LEN], + bytes: vec![], _marker: PhantomData, } } +} +impl Table where Option: FixedSizeEncoding { crate fn set(&mut self, i: usize, value: T) { + let needed = (i + 1) * >::BYTE_LEN; + if self.bytes.len() < needed { + self.bytes.resize(needed, 0); + } Some(value).write_to_bytes_at(&mut self.bytes, i); } @@ -167,7 +171,7 @@ impl Lazy> where Option: FixedSizeEncoding { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; - >::read_from_bytes_at(bytes, i) + >::maybe_read_from_bytes_at(bytes, i)? } } @@ -176,11 +180,13 @@ impl Lazy> where Option: FixedSizeEncoding { // and by using `newtype_index!` to define `DefIndex`. crate struct PerDefTable(Table) where Option: FixedSizeEncoding; -impl PerDefTable where Option: FixedSizeEncoding { - crate fn new(def_index_count: usize) -> Self { - PerDefTable(Table::new(def_index_count)) +impl Default for PerDefTable where Option: FixedSizeEncoding { + fn default() -> Self { + PerDefTable(Table::default()) } +} +impl PerDefTable where Option: FixedSizeEncoding { crate fn set(&mut self, def_id: DefId, value: T) { assert!(def_id.is_local()); self.0.set(def_id.index.index(), value);