about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2019-04-14 05:21:39 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2019-10-15 18:23:51 +0300
commit34066d60c38b8e1049a60e1eaf26cd84a67e7655 (patch)
treeb8f06fcb74027c4e0f0c10c907048667afb50b29
parentee747f645ffdfcea4f39ad4ccc4d83742a4ea3aa (diff)
downloadrust-34066d60c38b8e1049a60e1eaf26cd84a67e7655.tar.gz
rust-34066d60c38b8e1049a60e1eaf26cd84a67e7655.zip
rustc_metadata: don't use more space than needed, for each Table.
-rw-r--r--src/librustc_metadata/encoder.rs22
-rw-r--r--src/librustc_metadata/table.rs32
2 files changed, 21 insertions, 33 deletions
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 3bc3fee4164..f1436e4c09d 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -60,6 +60,7 @@ struct EncodeContext<'tcx> {
     source_file_cache: Lrc<SourceFile>,
 }
 
+#[derive(Default)]
 struct PerDefTables<'tcx> {
     kind: PerDefTable<Lazy<EntryKind<'tcx>>>,
     visibility: PerDefTable<Lazy<ty::Visibility>>,
@@ -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 0585aa1d388..5cfa137d04f 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<Self>;
     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<Self> {
             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<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
 /// 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.
+// (not sure if that is possible given that the `Vec` is being resized now)
 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).
@@ -125,16 +124,21 @@ crate struct Table<T> where Option<T>: FixedSizeEncoding {
     _marker: PhantomData<T>,
 }
 
-impl<T> Table<T> where Option<T>: FixedSizeEncoding {
-    crate fn new(len: usize) -> Self {
+impl<T> Default for Table<T> where Option<T>: FixedSizeEncoding {
+    fn default() -> Self {
         Table {
-            // FIXME(eddyb) only allocate and encode as many entries as needed.
-            bytes: vec![0; len * <Option<T>>::BYTE_LEN],
+            bytes: vec![],
             _marker: PhantomData,
         }
     }
+}
 
+impl<T> Table<T> where Option<T>: FixedSizeEncoding {
     crate fn set(&mut self, i: usize, value: T) {
+        let needed = (i + 1) * <Option<T>>::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<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding {
         debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
 
         let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta];
-        <Option<T>>::read_from_bytes_at(bytes, i)
+        <Option<T>>::maybe_read_from_bytes_at(bytes, i)?
     }
 }
 
@@ -176,11 +180,13 @@ impl<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding {
 // and by using `newtype_index!` to define `DefIndex`.
 crate struct PerDefTable<T>(Table<T>) where Option<T>: FixedSizeEncoding;
 
-impl<T> PerDefTable<T> where Option<T>: FixedSizeEncoding {
-    crate fn new(def_index_count: usize) -> Self {
-        PerDefTable(Table::new(def_index_count))
+impl<T> Default for PerDefTable<T> where Option<T>: FixedSizeEncoding {
+    fn default() -> Self {
+        PerDefTable(Table::default())
     }
+}
 
+impl<T> PerDefTable<T> where Option<T>: FixedSizeEncoding {
     crate fn set(&mut self, def_id: DefId, value: T) {
         assert!(def_id.is_local());
         self.0.set(def_id.index.index(), value);