From e505857914795dd2171acb4193a010f9d09ebc7c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 22 May 2019 13:46:14 +0300 Subject: [PATCH 01/13] rustc_metadata: remove now-redundant length from the start of the encoding. --- src/librustc_metadata/index.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 037f9d3563083..8db7a51700bce 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -110,12 +110,8 @@ impl Index<'tcx> { crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); - - // First we write the length of the lower range ... - buf.emit_raw_bytes(&(self.positions.len() as u32 / 4).to_le_bytes()); - // ... then the values. buf.emit_raw_bytes(&self.positions); - Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4 + 1) + Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4) } } @@ -124,12 +120,12 @@ impl Lazy<[Index<'tcx>]> { /// DefIndex (if any). #[inline(never)] crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { - let bytes = &bytes[self.position..]; debug!("Index::lookup: index={:?} len={:?}", def_index, self.meta); - let position = u32::read_from_bytes_at(bytes, 1 + def_index.index()); + let bytes = &bytes[self.position..][..self.meta * 4]; + let position = u32::read_from_bytes_at(bytes, def_index.index()); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None From ea134563e709af1fdcf07766b281b0407b1e3500 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 18:24:38 +0300 Subject: [PATCH 02/13] rustc_metadata: use NonZeroUsize for the position of a Lazy. --- src/librustc_metadata/decoder.rs | 20 +++++++++++++------- src/librustc_metadata/encoder.rs | 16 +++++++++------- src/librustc_metadata/index.rs | 14 +++++++++----- src/librustc_metadata/schema.rs | 13 +++++++------ 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6969d608d76da..a2955212bd493 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -25,6 +25,7 @@ use rustc::util::captures::Captures; use std::io; use std::mem; +use std::num::NonZeroUsize; use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; @@ -131,7 +132,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { impl<'a, 'tcx, T: Decodable> Lazy { crate fn decode>(self, meta: M) -> T { - let mut dcx = meta.decoder(self.position); + let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } @@ -142,7 +143,7 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { self, meta: M, ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { - let mut dcx = meta.decoder(self.position); + let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } @@ -166,13 +167,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { let position = match self.lazy_state { LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { + let start = start.get(); assert!(distance + min_size <= start); start - distance - min_size } - LazyState::Previous(last_min_end) => last_min_end + distance, + LazyState::Previous(last_min_end) => last_min_end.get() + distance, }; - self.lazy_state = LazyState::Previous(position + min_size); - Ok(Lazy::from_position_and_meta(position, meta)) + self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); + Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) } } @@ -384,7 +386,9 @@ impl<'tcx> MetadataBlob { } crate fn get_rustc_version(&self) -> String { - Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) + Lazy::::from_position( + NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap(), + ).decode(self) } crate fn get_root(&self) -> CrateRoot<'tcx> { @@ -393,7 +397,9 @@ impl<'tcx> MetadataBlob { let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::>::from_position(pos).decode(self) + Lazy::>::from_position( + NonZeroUsize::new(pos).unwrap(), + ).decode(self) } crate fn list_crate_metadata(&self, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 03a14f886455a..76bac1251260c 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -23,11 +23,12 @@ use rustc::session::config::{self, CrateType}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::Lrc; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; use std::hash::Hash; +use std::num::NonZeroUsize; use std::path::Path; -use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast; use syntax::attr; @@ -271,10 +272,11 @@ impl<'tcx> EncodeContext<'tcx> { &mut self, lazy: Lazy, ) -> Result<(), ::Error> { - let min_end = lazy.position + T::min_size(lazy.meta); + let min_end = lazy.position.get() + T::min_size(lazy.meta); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { + let start = start.get(); assert!(min_end <= start); start - min_end } @@ -284,10 +286,10 @@ impl<'tcx> EncodeContext<'tcx> { "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - lazy.position - last_min_end + lazy.position.get() - last_min_end.get() } }; - self.lazy_state = LazyState::Previous(min_end); + self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap()); self.emit_usize(distance) } @@ -295,14 +297,14 @@ impl<'tcx> EncodeContext<'tcx> { &mut self, value: impl EncodeContentsForLazy, ) -> Lazy { - let pos = self.position(); + let pos = NonZeroUsize::new(self.position()).unwrap(); assert_eq!(self.lazy_state, LazyState::NoNode); self.lazy_state = LazyState::NodeStart(pos); let meta = value.encode_contents_for_lazy(self); self.lazy_state = LazyState::NoNode; - assert!(pos + ::min_size(meta) <= self.position()); + assert!(pos.get() + ::min_size(meta) <= self.position()); Lazy::from_position_and_meta(pos, meta) } @@ -1934,7 +1936,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { // Encode the root position. let header = METADATA_HEADER.len(); - let pos = root.position; + let pos = root.position.get(); result[header + 0] = (pos >> 24) as u8; result[header + 1] = (pos >> 16) as u8; result[header + 2] = (pos >> 8) as u8; diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 8db7a51700bce..6f47ebb914464 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -3,6 +3,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; use rustc_serialize::opaque::Encoder; use std::marker::PhantomData; +use std::num::NonZeroUsize; use std::u32; use log::debug; @@ -94,8 +95,8 @@ impl Index<'tcx> { } fn record_index(&mut self, item: DefIndex, entry: Lazy>) { - assert!(entry.position < (u32::MAX as usize)); - let position = entry.position as u32; + assert!(entry.position.get() < (u32::MAX as usize)); + let position = entry.position.get() as u32; let array_index = item.index(); let positions = &mut self.positions; @@ -111,7 +112,10 @@ impl Index<'tcx> { crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); buf.emit_raw_bytes(&self.positions); - Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4) + Lazy::from_position_and_meta( + NonZeroUsize::new(pos as usize).unwrap(), + self.positions.len() / 4, + ) } } @@ -124,14 +128,14 @@ impl Lazy<[Index<'tcx>]> { def_index, self.meta); - let bytes = &bytes[self.position..][..self.meta * 4]; + let bytes = &bytes[self.position.get()..][..self.meta * 4]; let position = u32::read_from_bytes_at(bytes, def_index.index()); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None } else { debug!("Index::lookup: position={:?}", position); - Some(Lazy::from_position(position as usize)) + Some(Lazy::from_position(NonZeroUsize::new(position as usize).unwrap())) } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d3539e7140121..9541e5c39cda3 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -20,6 +20,7 @@ use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; +use std::num::NonZeroUsize; crate fn rustc_version() -> String { format!("rustc {}", @@ -102,13 +103,13 @@ crate struct Lazy::Meta> where T: ?Sized + LazyMeta, Meta: 'static + Copy, { - pub position: usize, + pub position: NonZeroUsize, pub meta: Meta, _marker: PhantomData, } impl Lazy { - crate fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { + crate fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy { Lazy { position, meta, @@ -118,14 +119,14 @@ impl Lazy { } impl Lazy { - crate fn from_position(position: usize) -> Lazy { + crate fn from_position(position: NonZeroUsize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } impl Lazy<[T]> { crate fn empty() -> Lazy<[T]> { - Lazy::from_position_and_meta(0, 0) + Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } } @@ -147,12 +148,12 @@ crate enum LazyState { /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. - NodeStart(usize), + NodeStart(NonZeroUsize), /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that /// previous `Lazy` would end (see their comments). - Previous(usize), + Previous(NonZeroUsize), } #[derive(RustcEncodable, RustcDecodable)] From 83b3c392187003236aafe10e153816c13f7b896d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 19:56:59 +0300 Subject: [PATCH 03/13] rustc_metadata: use 0 in index::Index to indicate missing entries. --- src/librustc_metadata/index.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 6f47ebb914464..d37765120be95 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -2,9 +2,9 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; use rustc_serialize::opaque::Encoder; +use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; -use std::u32; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. @@ -73,7 +73,7 @@ impl FixedSizeEncoding for u32 { /// of each DefIndex. It is not required that all definitions appear /// in the metadata, nor that they are serialized in order, and /// therefore we first allocate the vector here and fill it with -/// `u32::MAX`. Whenever an index is visited, we fill in the +/// `0`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. crate struct Index<'tcx> { @@ -84,7 +84,7 @@ crate struct Index<'tcx> { impl Index<'tcx> { crate fn new(max_index: usize) -> Self { Index { - positions: vec![0xff; max_index * 4], + positions: vec![0; max_index * 4], _marker: PhantomData, } } @@ -95,12 +95,11 @@ impl Index<'tcx> { } fn record_index(&mut self, item: DefIndex, entry: Lazy>) { - assert!(entry.position.get() < (u32::MAX as usize)); - let position = entry.position.get() as u32; + 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) == u32::MAX, + 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), @@ -130,12 +129,7 @@ impl Lazy<[Index<'tcx>]> { let bytes = &bytes[self.position.get()..][..self.meta * 4]; let position = u32::read_from_bytes_at(bytes, def_index.index()); - if position == u32::MAX { - debug!("Index::lookup: position=u32::MAX"); - None - } else { - debug!("Index::lookup: position={:?}", position); - Some(Lazy::from_position(NonZeroUsize::new(position as usize).unwrap())) - } + debug!("Index::lookup: position={:?}", position); + NonZeroUsize::new(position as usize).map(Lazy::from_position) } } From f49274032bc2819c6f9acaaf4e85e5200fc8bbba Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 23 May 2019 20:29:01 +0300 Subject: [PATCH 04/13] rustc_metadata: rename index::Index to table::Table. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 16 ++++++++-------- src/librustc_metadata/lib.rs | 10 +++++----- src/librustc_metadata/schema.rs | 4 ++-- src/librustc_metadata/{index.rs => table.rs} | 14 +++++++------- 5 files changed, 23 insertions(+), 23 deletions(-) rename src/librustc_metadata/{index.rs => table.rs} (94%) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a2955212bd493..684dfd69d2db7 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -472,7 +472,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) + self.root.entries_table.lookup(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 76bac1251260c..abfee8eaa3cd7 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ -use crate::index::Index; use crate::schema::*; +use crate::table::Table; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_index: Index<'tcx>, + entries_table: Table<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -325,7 +325,7 @@ impl<'tcx> EncodeContext<'tcx> { let entry = op(self, data); let entry = self.lazy(entry); - self.entries_index.record(id, entry); + self.entries_table.record(id, entry); } fn encode_info_for_items(&mut self) { @@ -477,8 +477,8 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); - let entries_index = self.entries_index.write_index(&mut self.opaque); - let entries_index_bytes = self.position() - i; + let entries_table = self.entries_table.encode(&mut self.opaque); + let entries_table_bytes = self.position() - i; // Encode the proc macro data i = self.position(); @@ -537,7 +537,7 @@ impl<'tcx> EncodeContext<'tcx> { impls, exported_symbols, interpret_alloc_index, - entries_index, + entries_table, }); let total_bytes = self.position(); @@ -562,7 +562,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" def-path table bytes: {}", def_path_table_bytes); println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); - println!(" entries index bytes: {}", entries_index_bytes); + println!(" entries table bytes: {}", entries_table_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -1916,7 +1916,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_index: Index::new(tcx.hir().definitions().def_index_count()), + entries_table: Table::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/lib.rs b/src/librustc_metadata/lib.rs index 6aa684b1c3d01..291ee23ff7262 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,15 +26,15 @@ extern crate rustc_data_structures; pub mod error_codes; -mod index; mod encoder; mod decoder; +mod dependency_format; mod cstore_impl; -mod schema; -mod native_libs; -mod link_args; mod foreign_modules; -mod dependency_format; +mod link_args; +mod native_libs; +mod schema; +mod table; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 9541e5c39cda3..52bbebb17f26a 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::index; +use crate::table::Table; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -186,7 +186,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, pub interpret_alloc_index: Lazy<[u32]>, - pub entries_index: Lazy<[index::Index<'tcx>]>, + pub entries_table: Lazy<[Table<'tcx>]>, /// The DefIndex's of any proc macros delcared by /// this crate diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/table.rs similarity index 94% rename from src/librustc_metadata/index.rs rename to src/librustc_metadata/table.rs index d37765120be95..c53d69907044f 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/table.rs @@ -76,14 +76,14 @@ impl FixedSizeEncoding for u32 { /// `0`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -crate struct Index<'tcx> { +crate struct Table<'tcx> { positions: Vec, _marker: PhantomData<&'tcx ()>, } -impl Index<'tcx> { +impl Table<'tcx> { crate fn new(max_index: usize) -> Self { - Index { + Table { positions: vec![0; max_index * 4], _marker: PhantomData, } @@ -108,7 +108,7 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { + crate fn encode(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); buf.emit_raw_bytes(&self.positions); Lazy::from_position_and_meta( @@ -118,18 +118,18 @@ impl Index<'tcx> { } } -impl Lazy<[Index<'tcx>]> { +impl Lazy<[Table<'tcx>]> { /// 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>> { - debug!("Index::lookup: index={:?} len={:?}", + debug!("Table::lookup: index={:?} len={:?}", def_index, self.meta); let bytes = &bytes[self.position.get()..][..self.meta * 4]; let position = u32::read_from_bytes_at(bytes, def_index.index()); - debug!("Index::lookup: position={:?}", position); + debug!("Table::lookup: position={:?}", position); NonZeroUsize::new(position as usize).map(Lazy::from_position) } } From ffd18fc22c7dcfd59bb09567217046f6e0b71e7f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 22:52:12 +0300 Subject: [PATCH 05/13] rustc_metadata: parametrize Table by element type. --- src/librustc_metadata/encoder.rs | 2 +- src/librustc_metadata/schema.rs | 54 ++++++++++++++++++-------------- src/librustc_metadata/table.rs | 25 +++++++-------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index abfee8eaa3cd7..ef11ebdae43b4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_table: Table<'tcx>, + entries_table: Table>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 52bbebb17f26a..a1b097225b7d2 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -156,6 +156,14 @@ crate enum LazyState { Previous(NonZeroUsize), } +// FIXME(#59875) `Lazy!(T)` replaces `Lazy`, passing the `Meta` parameter +// manually, instead of relying on the default, to get the correct variance. +// Only needed when `T` itself contains a parameter (e.g. `'tcx`). +macro_rules! Lazy { + ([$T:ty]) => {Lazy<[$T], usize>}; + ($T:ty) => {Lazy<$T, ()>}; +} + #[derive(RustcEncodable, RustcDecodable)] crate struct CrateRoot<'tcx> { pub name: Symbol, @@ -183,10 +191,10 @@ crate struct CrateRoot<'tcx> { pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy, pub impls: Lazy<[TraitImpls]>, - pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, + pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy<[Table<'tcx>]>, + pub entries_table: Lazy!([Table>]), /// The DefIndex's of any proc macros delcared by /// this crate @@ -226,14 +234,14 @@ crate struct Entry<'tcx> { pub stability: Option>, pub deprecation: Option>, - pub ty: Option>>, + pub ty: Option)>, pub inherent_impls: Lazy<[DefIndex]>, pub variances: Lazy<[ty::Variance]>, pub generics: Option>, - pub predicates: Option>>, - pub predicates_defined_on: Option>>, + pub predicates: Option)>, + pub predicates_defined_on: Option)>, - pub mir: Option>>, + pub mir: Option)>, pub promoted_mir: Option>>>, } @@ -253,22 +261,22 @@ crate enum EntryKind<'tcx> { OpaqueTy, Enum(ReprOptions), Field, - Variant(Lazy>), - Struct(Lazy>, ReprOptions), - Union(Lazy>, ReprOptions), - Fn(Lazy>), - ForeignFn(Lazy>), + Variant(Lazy!(VariantData<'tcx>)), + Struct(Lazy!(VariantData<'tcx>), ReprOptions), + Union(Lazy!(VariantData<'tcx>), ReprOptions), + Fn(Lazy!(FnData<'tcx>)), + ForeignFn(Lazy!(FnData<'tcx>)), Mod(Lazy), MacroDef(Lazy), - Closure(Lazy>), - Generator(Lazy>), - Trait(Lazy>), - Impl(Lazy>), - Method(Lazy>), + Closure(Lazy!(ClosureData<'tcx>)), + Generator(Lazy!(GeneratorData<'tcx>)), + Trait(Lazy!(TraitData<'tcx>)), + Impl(Lazy!(ImplData<'tcx>)), + Method(Lazy!(MethodData<'tcx>)), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, ConstQualif, Lazy), - TraitAlias(Lazy>), + TraitAlias(Lazy!(TraitAliasData<'tcx>)), } /// Additional data for EntryKind::Const and EntryKind::AssocConst @@ -298,7 +306,7 @@ crate struct FnData<'tcx> { pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, - pub sig: Lazy>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] @@ -309,7 +317,7 @@ crate struct VariantData<'tcx> { pub ctor: Option, /// If this is a tuple struct or variant /// ctor, this is its "function" signature. - pub ctor_sig: Option>>, + pub ctor_sig: Option)>, } #[derive(RustcEncodable, RustcDecodable)] @@ -318,12 +326,12 @@ crate struct TraitData<'tcx> { pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] crate struct TraitAliasData<'tcx> { - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] @@ -334,7 +342,7 @@ crate struct ImplData<'tcx> { /// This is `Some` only for impls of `CoerceUnsized`. pub coerce_unsized_info: Option, - pub trait_ref: Option>>, + pub trait_ref: Option)>, } @@ -385,7 +393,7 @@ crate struct MethodData<'tcx> { #[derive(RustcEncodable, RustcDecodable)] crate struct ClosureData<'tcx> { - pub sig: Lazy>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c53d69907044f..94966a44edd23 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -69,19 +69,16 @@ impl FixedSizeEncoding for u32 { } } -/// While we are generating the metadata, we also track the position -/// of each DefIndex. It is not required that all definitions appear -/// in the metadata, nor that they are serialized in order, and -/// therefore we first allocate the vector here and fill it with -/// `0`. Whenever an index is visited, we fill in the -/// appropriate spot by calling `record_position`. We should never -/// visit the same index twice. -crate struct Table<'tcx> { +/// 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>`, but with zero-copy decoding. +crate struct Table { positions: Vec, - _marker: PhantomData<&'tcx ()>, + _marker: PhantomData, } -impl Table<'tcx> { +impl Table { crate fn new(max_index: usize) -> Self { Table { positions: vec![0; max_index * 4], @@ -89,12 +86,12 @@ impl Table<'tcx> { } } - crate fn record(&mut self, def_id: DefId, entry: Lazy>) { + crate fn record(&mut self, def_id: DefId, entry: Lazy) { assert!(def_id.is_local()); self.record_index(def_id.index, entry); } - fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + crate fn record_index(&mut self, item: DefIndex, entry: Lazy) { let position: u32 = entry.position.get().try_into().unwrap(); let array_index = item.index(); @@ -118,11 +115,11 @@ impl Table<'tcx> { } } -impl Lazy<[Table<'tcx>]> { +impl Lazy<[Table]> { /// 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>> { + crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { debug!("Table::lookup: index={:?} len={:?}", def_index, self.meta); From dd1264e90a47d9818d868276cd09363fe78056c4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 23:36:00 +0300 Subject: [PATCH 06/13] rustc_metadata: replace Lazy<[Table]> with Lazy>. --- src/librustc_metadata/decoder.rs | 19 ++++++++++++++----- src/librustc_metadata/encoder.rs | 15 ++++++++++++--- src/librustc_metadata/schema.rs | 12 +++++++----- src/librustc_metadata/table.rs | 18 +++++++++++++----- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 684dfd69d2db7..c2ec9115d310d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,6 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob}; use crate::schema::*; +use crate::table::Table; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; @@ -28,7 +29,7 @@ use std::mem; use std::num::NonZeroUsize; use std::u32; -use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; +use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map::{self, respan, Spanned}; @@ -130,7 +131,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { } } -impl<'a, 'tcx, T: Decodable> Lazy { +impl<'a, 'tcx, T: Encodable + Decodable> Lazy { crate fn decode>(self, meta: M) -> T { let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); @@ -138,7 +139,7 @@ impl<'a, 'tcx, T: Decodable> Lazy { } } -impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { +impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> { crate fn decode>( self, meta: M, @@ -237,13 +238,13 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; if len == 0 { @@ -254,6 +255,14 @@ 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> { + let len = self.read_usize()?; + self.read_lazy_with_meta(len) + } +} impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index ef11ebdae43b4..53d3039a2842f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -98,13 +98,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> { } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { self.emit_lazy_distance(*lazy) } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; if lazy.meta == 0 { @@ -114,6 +114,15 @@ 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> { + self.emit_usize(lazy.meta)?; + self.emit_lazy_distance(*lazy) + } +} + impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { #[inline] fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { @@ -258,7 +267,7 @@ impl EncodeContentsForLazy for T { } } -impl EncodeContentsForLazy<[T]> for I +impl EncodeContentsForLazy<[T]> for I where I: IntoIterator, I::Item: EncodeContentsForLazy, { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index a1b097225b7d2..6ae20a9d438fa 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -14,6 +14,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc_index::vec::IndexVec; use rustc_data_structures::svh::Svh; +use rustc_serialize::Encodable; use syntax::{ast, attr}; use syntax::edition::Edition; use syntax::symbol::Symbol; @@ -53,7 +54,7 @@ crate trait LazyMeta { fn min_size(meta: Self::Meta) -> usize; } -impl LazyMeta for T { +impl LazyMeta for T { type Meta = (); fn min_size(_: ()) -> usize { @@ -62,7 +63,7 @@ impl LazyMeta for T { } } -impl LazyMeta for [T] { +impl LazyMeta for [T] { type Meta = usize; fn min_size(len: usize) -> usize { @@ -118,13 +119,13 @@ impl Lazy { } } -impl Lazy { +impl Lazy { crate fn from_position(position: NonZeroUsize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } -impl Lazy<[T]> { +impl Lazy<[T]> { crate fn empty() -> Lazy<[T]> { Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } @@ -160,6 +161,7 @@ crate enum LazyState { // manually, instead of relying on the default, to get the correct variance. // Only needed when `T` itself contains a parameter (e.g. `'tcx`). macro_rules! Lazy { + (Table<$T:ty>) => {Lazy, usize>}; ([$T:ty]) => {Lazy<[$T], usize>}; ($T:ty) => {Lazy<$T, ()>}; } @@ -194,7 +196,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!(Table>), /// 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 94966a44edd23..e18535060e6ac 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -1,7 +1,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; -use rustc_serialize::opaque::Encoder; +use rustc_serialize::{Encodable, opaque::Encoder}; use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; @@ -73,12 +73,12 @@ 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. -crate struct Table { +crate struct Table> { positions: Vec, _marker: PhantomData, } -impl Table { +impl> Table { crate fn new(max_index: usize) -> Self { Table { positions: vec![0; max_index * 4], @@ -105,7 +105,7 @@ impl Table { position.write_to_bytes_at(positions, array_index) } - crate fn encode(&self, buf: &mut Encoder) -> Lazy<[Self]> { + crate fn encode(&self, buf: &mut Encoder) -> Lazy { let pos = buf.position(); buf.emit_raw_bytes(&self.positions); Lazy::from_position_and_meta( @@ -115,7 +115,15 @@ impl Table { } } -impl Lazy<[Table]> { +impl> LazyMeta for Table { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len * 4 + } +} + +impl Lazy> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] From 5d52a7e0d0f230627c20dc874c17c528261a397f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 19:18:12 +0300 Subject: [PATCH 07/13] rustc_metadata: split tables into an usize-keyed Table and a DefIndex-keyed PerDefTable. --- src/librustc_metadata/decoder.rs | 6 +-- src/librustc_metadata/encoder.rs | 10 ++-- src/librustc_metadata/schema.rs | 5 +- src/librustc_metadata/table.rs | 91 ++++++++++++++++++++++---------- 4 files changed, 75 insertions(+), 37 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c2ec9115d310d..c640e411f6346 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 53d3039a2842f..df99541df5876 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 6ae20a9d438fa..dffc8f33b2de6 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 e18535060e6ac..c60c8e2cbce55 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()) + } +} From 677f0df63b7f39c3b22a84004c1697e85743c470 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 21:52:18 +0300 Subject: [PATCH 08/13] rustc_metadata: add a helper macro for recording into PerDefTable's. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 234 +++++++++++++++---------------- src/librustc_metadata/schema.rs | 9 +- 3 files changed, 118 insertions(+), 127 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c640e411f6346..7ba395a1bd50e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.entries_table.lookup(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.lookup(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 df99541df5876..51634e372a2cd 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_table: PerDefTable>, + per_def: PerDefTables<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -60,6 +60,10 @@ struct EncodeContext<'tcx> { source_file_cache: Lrc, } +struct PerDefTables<'tcx> { + entry: PerDefTable>, +} + macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { @@ -276,6 +280,18 @@ impl EncodeContentsForLazy<[T]> for I } } +// Shorthand for `$self.$tables.$table.record($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); + } + }} +} + impl<'tcx> EncodeContext<'tcx> { fn emit_lazy_distance( &mut self, @@ -318,31 +334,10 @@ impl<'tcx> EncodeContext<'tcx> { Lazy::from_position_and_meta(pos, meta) } - /// Emit the data for a `DefId` to the metadata. The function to - /// emit the data is `op`, and it will be given `data` as - /// arguments. This `record` function will call `op` to generate - /// the `Entry` (which may point to other encoded information) - /// and will then record the `Lazy` for use in the index. - // FIXME(eddyb) remove this. - fn record( - &mut self, - id: DefId, - op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, - data: DATA, - ) { - assert!(id.is_local()); - - let entry = op(self, data); - let entry = self.lazy(entry); - self.entries_table.record(id, entry); - } - fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, - (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis)); + self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis); krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in &krate.exported_macros { self.visit_macro_def(macro_def); @@ -486,8 +481,10 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); - let entries_table = self.entries_table.encode(&mut self.opaque); - let entries_table_bytes = self.position() - i; + let per_def = LazyPerDefTables { + entry: self.per_def.entry.encode(&mut self.opaque), + }; + let per_def_bytes = self.position() - i; // Encode the proc macro data i = self.position(); @@ -546,7 +543,7 @@ impl<'tcx> EncodeContext<'tcx> { impls, exported_symbols, interpret_alloc_index, - entries_table, + per_def, }); let total_bytes = self.position(); @@ -571,7 +568,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" def-path table bytes: {}", def_path_table_bytes); println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); - println!(" entries table bytes: {}", entries_table_bytes); + println!(" per-def table bytes: {}", per_def_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -596,8 +593,9 @@ impl EncodeContext<'tcx> { fn encode_enum_variant_info( &mut self, - (enum_did, index): (DefId, VariantIdx), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -619,7 +617,7 @@ impl EncodeContext<'tcx> { let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item(enum_id).vis; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Variant(self.lazy(data)), visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), span: self.lazy(tcx.def_span(def_id)), @@ -644,13 +642,14 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_enum_variant_ctor( &mut self, - (enum_did, index): (DefId, VariantIdx), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -677,7 +676,7 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Variant(self.lazy(data)), visibility: self.lazy(ctor_vis), span: self.lazy(tcx.def_span(def_id)), @@ -699,13 +698,16 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_info_for_mod( &mut self, - (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility), - ) -> Entry<'tcx> { + id: hir::HirId, + md: &hir::Mod, + attrs: &[ast::Attribute], + vis: &hir::Visibility, + ) { let tcx = self.tcx; let def_id = tcx.hir().local_def_id(id); debug!("EncodeContext::encode_info_for_mod({:?})", def_id); @@ -717,7 +719,7 @@ impl EncodeContext<'tcx> { }, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Mod(self.lazy(data)), visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), span: self.lazy(tcx.def_span(def_id)), @@ -737,13 +739,15 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } fn encode_field( &mut self, - (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize), - ) -> Entry<'tcx> { + adt_def_id: DefId, + variant_index: VariantIdx, + field_index: usize, + ) { let tcx = self.tcx; let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; @@ -754,7 +758,7 @@ impl EncodeContext<'tcx> { let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Field, visibility: self.lazy(field.vis), span: self.lazy(tcx.def_span(def_id)), @@ -772,10 +776,10 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } - fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { + fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let adt_def = tcx.adt_def(adt_def_id); @@ -811,7 +815,7 @@ impl EncodeContext<'tcx> { let repr_options = get_repr_options(tcx, adt_def_id); - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Struct(self.lazy(data), repr_options), visibility: self.lazy(ctor_vis), span: self.lazy(tcx.def_span(def_id)), @@ -833,7 +837,7 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_generics(&mut self, def_id: DefId) -> Lazy { @@ -854,7 +858,7 @@ impl EncodeContext<'tcx> { self.lazy(&*tcx.predicates_defined_on(def_id)) } - fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -908,7 +912,7 @@ impl EncodeContext<'tcx> { ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"), }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(trait_item.vis), span: self.lazy(ast_item.span), @@ -943,7 +947,7 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn metadata_output_only(&self) -> bool { @@ -951,7 +955,7 @@ impl EncodeContext<'tcx> { !self.tcx.sess.opts.output_types.should_codegen() } - fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_impl_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -1014,7 +1018,7 @@ impl EncodeContext<'tcx> { hir::ImplItemKind::TyAlias(..) => false, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(impl_item.vis), span: self.lazy(ast_item.span), @@ -1036,7 +1040,7 @@ impl EncodeContext<'tcx> { mir: if mir { self.encode_optimized_mir(def_id) } else { None }, promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - } + }) } fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) @@ -1110,7 +1114,7 @@ impl EncodeContext<'tcx> { self.lazy(rendered_const) } - fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { + fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_item({:?})", def_id); @@ -1136,7 +1140,7 @@ impl EncodeContext<'tcx> { EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); + return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis); } hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, @@ -1245,7 +1249,7 @@ impl EncodeContext<'tcx> { _ => false, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), span: self.lazy(item.span), @@ -1340,20 +1344,22 @@ impl EncodeContext<'tcx> { // necessary.) predicates_defined_on: match item.kind { hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)), + hir::ItemKind::TraitAlias(..) => { + Some(self.encode_predicates_defined_on(def_id)) + } _ => None, // not *wrong* for other kinds of items, but not needed }, mir: if mir { self.encode_optimized_mir(def_id) } else { None }, promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - } + }) } /// Serialize the text of exported macros - fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { + fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::MacroDef(self.lazy(MacroDef { body: pprust::tts_to_string(macro_def.body.clone()), legacy: macro_def.legacy, @@ -1373,7 +1379,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, promoted_mir: None, - } + }) } fn encode_info_for_generic_param( @@ -1381,9 +1387,9 @@ impl EncodeContext<'tcx> { def_id: DefId, entry_kind: EntryKind<'tcx>, encode_type: bool, - ) -> Entry<'tcx> { + ) { let tcx = self.tcx; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: entry_kind, visibility: self.lazy(ty::Visibility::Public), span: self.lazy(tcx.def_span(def_id)), @@ -1400,26 +1406,10 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } - } - - fn encode_info_for_ty_param( - &mut self, - (def_id, encode_type): (DefId, bool), - ) -> Entry<'tcx> { - debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) - } - - fn encode_info_for_const_param( - &mut self, - def_id: DefId, - ) -> Entry<'tcx> { - debug!("EncodeContext::encode_info_for_const_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) + }) } - fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; @@ -1443,7 +1433,7 @@ impl EncodeContext<'tcx> { _ => bug!("closure that is neither generator nor closure") }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(ty::Visibility::Public), span: self.lazy(tcx.def_span(def_id)), @@ -1461,10 +1451,10 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } - fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_anon_const(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -1472,7 +1462,7 @@ impl EncodeContext<'tcx> { let const_data = self.encode_rendered_const_for_body(body_id); let mir = tcx.mir_const_qualif(def_id).0; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Const(ConstQualif { mir }, const_data), visibility: self.lazy(ty::Visibility::Public), span: self.lazy(tcx.def_span(def_id)), @@ -1490,7 +1480,7 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { @@ -1668,9 +1658,11 @@ impl EncodeContext<'tcx> { Lazy::empty() } - fn encode_info_for_foreign_item(&mut self, - (def_id, nitem): (DefId, &hir::ForeignItem)) - -> Entry<'tcx> { + fn encode_info_for_foreign_item( + &mut self, + def_id: DefId, + nitem: &hir::ForeignItem, + ) { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); @@ -1690,7 +1682,7 @@ impl EncodeContext<'tcx> { hir::ForeignItemKind::Type => EntryKind::ForeignType, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), span: self.lazy(nitem.span), @@ -1711,10 +1703,11 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } } +// FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. impl Visitor<'tcx> for EncodeContext<'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::OnlyBodies(&self.tcx.hir()) @@ -1726,7 +1719,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { fn visit_anon_const(&mut self, c: &'tcx AnonConst) { intravisit::walk_anon_const(self, c); let def_id = self.tcx.hir().local_def_id(c.hir_id); - self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); + self.encode_info_for_anon_const(def_id); } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); @@ -1734,24 +1727,21 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { match item.kind { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these - _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), + _ => self.encode_info_for_item(def_id, item), } self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); let def_id = self.tcx.hir().local_def_id(ni.hir_id); - self.record(def_id, - EncodeContext::encode_info_for_foreign_item, - (def_id, ni)); + self.encode_info_for_foreign_item(def_id, ni); } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); self.encode_info_for_generics(generics); } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); + self.encode_info_for_macro_def(macro_def); } } @@ -1759,10 +1749,10 @@ impl EncodeContext<'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter_enumerated() { - for (field_index, field) in variant.fields.iter().enumerate() { - self.record(field.did, - EncodeContext::encode_field, - (adt_def_id, variant_index, field_index)); + for (field_index, _field) in variant.fields.iter().enumerate() { + // FIXME(eddyb) `adt_def_id` is leftover from incremental isolation, + // pass `def`, `variant` or `field` instead. + self.encode_field(adt_def_id, variant_index, field_index); } } } @@ -1773,14 +1763,14 @@ impl EncodeContext<'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => continue, GenericParamKind::Type { ref default, .. } => { - self.record( + self.encode_info_for_generic_param( def_id, - EncodeContext::encode_info_for_ty_param, - (def_id, default.is_some()), + EntryKind::TypeParam, + default.is_some(), ); } GenericParamKind::Const { .. } => { - self.record(def_id, EncodeContext::encode_info_for_const_param, def_id); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); } } } @@ -1790,7 +1780,7 @@ impl EncodeContext<'tcx> { match expr.kind { hir::ExprKind::Closure(..) => { let def_id = self.tcx.hir().local_def_id(expr.hir_id); - self.record(def_id, EncodeContext::encode_info_for_closure, def_id); + self.encode_info_for_closure(def_id); } _ => {} } @@ -1821,14 +1811,14 @@ impl EncodeContext<'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { - self.record(variant.def_id, - EncodeContext::encode_enum_variant_info, - (def_id, i)); - - if let Some(ctor_def_id) = variant.ctor_def_id { - self.record(ctor_def_id, - EncodeContext::encode_enum_variant_ctor, - (def_id, i)); + // FIXME(eddyb) `def_id` is leftover from incremental isolation, + // pass `def` or `variant` instead. + self.encode_enum_variant_info(def_id, i); + + // FIXME(eddyb) `def_id` is leftover from incremental isolation, + // pass `def`, `variant` or `ctor_def_id` instead. + if let Some(_ctor_def_id) = variant.ctor_def_id { + self.encode_enum_variant_ctor(def_id, i); } } } @@ -1838,9 +1828,7 @@ impl EncodeContext<'tcx> { // If the struct has a constructor, encode it. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); - self.record(ctor_def_id, - EncodeContext::encode_struct_ctor, - (def_id, ctor_def_id)); + self.encode_struct_ctor(def_id, ctor_def_id); } } hir::ItemKind::Union(..) => { @@ -1848,16 +1836,12 @@ impl EncodeContext<'tcx> { } hir::ItemKind::Impl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(trait_item_def_id, - EncodeContext::encode_info_for_impl_item, - trait_item_def_id); + self.encode_info_for_impl_item(trait_item_def_id); } } hir::ItemKind::Trait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(item_def_id, - EncodeContext::encode_info_for_trait_item, - item_def_id); + self.encode_info_for_trait_item(item_def_id); } } } @@ -1925,7 +1909,9 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_table: PerDefTable::new(tcx.hir().definitions().def_index_count()), + per_def: PerDefTables { + entry: 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 dffc8f33b2de6..9d6748732b8be 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -197,7 +197,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!(PerDefTable>), + pub per_def: LazyPerDefTables<'tcx>, /// The DefIndex's of any proc macros delcared by /// this crate @@ -227,6 +227,11 @@ crate struct TraitImpls { pub impls: Lazy<[DefIndex]>, } +#[derive(RustcEncodable, RustcDecodable)] +crate struct LazyPerDefTables<'tcx> { + pub entry: Lazy!(PerDefTable>), +} + #[derive(RustcEncodable, RustcDecodable)] crate struct Entry<'tcx> { pub kind: EntryKind<'tcx>, @@ -245,7 +250,7 @@ crate struct Entry<'tcx> { pub predicates_defined_on: Option)>, pub mir: Option)>, - pub promoted_mir: Option>>>, + pub promoted_mir: Option>)>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] From cef495028019b5bbb380bfa1d7a10e9e06dbf166 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 23:30:53 +0300 Subject: [PATCH 09/13] rustc_metadata: generalize Table to hold T, not Lazy, elements. --- src/librustc_metadata/decoder.rs | 6 +- src/librustc_metadata/encoder.rs | 10 +-- src/librustc_metadata/schema.rs | 2 +- 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 7ba395a1bd50e..f1ae048752989 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> for DecodeContext<'a, } impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> - where T: LazyMeta, + where Option: FixedSizeEncoding, { fn specialized_decode(&mut self) -> Result>, Self::Error> { let len = self.read_usize()?; @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - 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 51634e372a2cd..c9426aaece941 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: PerDefTable>>, } macro_rules! encoder_methods { @@ -119,7 +119,7 @@ impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { } impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> - where T: LazyMeta, + where Option: FixedSizeEncoding, { fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; @@ -280,14 +280,14 @@ impl 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 9d6748732b8be..e70ba2532caaf 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>), + pub entry: Lazy!(PerDefTable>>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c60c8e2cbce55..c069ea2830c13 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>`, but with zero-copy decoding. -// FIXME(eddyb) newtype `[u8]` here, such that `Box>` would be used +// NOTE(eddyb) there could be an impl for `usize`, which would enable a more +// generic `Lazy` impl, but in the general case we might not need / want to +// fit every `usize` in `u32`. +impl FixedSizeEncoding for Option> { + 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 FixedSizeEncoding for Option> { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position_and_meta( + >>::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::::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>`, but without requiring +/// 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. -crate struct Table> { +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). bytes: Vec, _marker: PhantomData, } -impl> Table { +impl Table where Option: 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 * >::BYTE_LEN], _marker: PhantomData, } } - crate fn record(&mut self, i: usize, entry: Lazy) { - 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 { @@ -112,7 +147,7 @@ impl> Table { } } -impl> LazyMeta for Table { +impl LazyMeta for Table where Option: FixedSizeEncoding { type Meta = usize; fn min_size(len: usize) -> usize { @@ -120,34 +155,29 @@ impl> LazyMeta for Table { } } -impl Lazy> { - /// Given the metadata, extract out the offset of a particular index (if any). +impl Lazy> where Option: 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> { + crate fn get(&self, bytes: &[u8], i: usize) -> Option { 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) + >::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>(Table); +crate struct PerDefTable(Table) where Option: FixedSizeEncoding; -impl> PerDefTable { +impl PerDefTable where Option: 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) { + 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 { @@ -156,7 +186,7 @@ impl> PerDefTable { } } -impl> LazyMeta for PerDefTable { +impl LazyMeta for PerDefTable where Option: FixedSizeEncoding { type Meta = as LazyMeta>::Meta; fn min_size(meta: Self::Meta) -> usize { @@ -164,14 +194,14 @@ impl> LazyMeta for PerDefTable { } } -impl Lazy> { +impl Lazy> where Option: FixedSizeEncoding { 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). + /// 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> { - self.as_table().lookup(bytes, def_index.index()) + crate fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option { + self.as_table().get(bytes, def_index.index()) } } From 972b93b20e2d21307622eacb812d8a552ecf0f81 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 01:36:08 +0300 Subject: [PATCH 10/13] rustc_metadata: use decoder::Metadata instead of &[u8] for Lazy>::get. --- src/librustc_metadata/decoder.rs | 10 +++++----- src/librustc_metadata/table.rs | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f1ae048752989..6da936374c789 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -132,8 +132,8 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { } impl<'a, 'tcx, T: Encodable + Decodable> Lazy { - crate fn decode>(self, meta: M) -> T { - let mut dcx = meta.decoder(self.position.get()); + crate fn decode>(self, metadata: M) -> T { + let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } @@ -142,9 +142,9 @@ impl<'a, 'tcx, T: Encodable + Decodable> Lazy { impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> { crate fn decode>( self, - meta: M, + metadata: M, ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { - let mut dcx = meta.decoder(self.position.get()); + let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.per_def.entry.get(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.get(self, item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c069ea2830c13..0585aa1d3884e 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -1,3 +1,4 @@ +use crate::decoder::Metadata; use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; @@ -158,10 +159,15 @@ impl LazyMeta for Table where Option: FixedSizeEncoding { impl Lazy> where Option: FixedSizeEncoding { /// Given the metadata, extract out the value at a particular index (if any). #[inline(never)] - crate fn get(&self, bytes: &[u8], i: usize) -> Option { + crate fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + i: usize, + ) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - >::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i) + let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; + >::read_from_bytes_at(bytes, i) } } @@ -201,7 +207,11 @@ impl Lazy> where Option: FixedSizeEncoding { /// Given the metadata, extract out the value at a particular DefIndex (if any). #[inline(never)] - crate fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option { - self.as_table().get(bytes, def_index.index()) + crate fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + def_index: DefIndex, + ) -> Option { + self.as_table().get(metadata, def_index.index()) } } From ee747f645ffdfcea4f39ad4ccc4d83742a4ea3aa Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 04:19:28 +0300 Subject: [PATCH 11/13] rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA). --- src/librustc_metadata/decoder.rs | 194 +++---- src/librustc_metadata/encoder.rs | 833 +++++++++++++------------------ src/librustc_metadata/schema.rs | 39 +- 3 files changed, 469 insertions(+), 597 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6da936374c789..962846b047533 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -473,27 +473,20 @@ impl<'a, 'tcx> CrateMetadata { self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() } - fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { - match self.is_proc_macro(id) { - true => None, - false => Some(self.entry(id)), - } - } - - fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.per_def.entry.get(self, item_id) - } - - fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { - match self.maybe_entry(item_id) { - None => { - bug!("entry: id not found: {:?} in crate {:?} with number {}", - item_id, - self.root.name, - self.cnum) - } - Some(d) => d.decode(self), - } + fn maybe_kind(&self, item_id: DefIndex) -> Option> { + self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self)) + } + + fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> { + assert!(!self.is_proc_macro(item_id)); + self.maybe_kind(item_id).unwrap_or_else(|| { + bug!( + "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", + item_id, + self.root.name, + self.cnum, + ) + }) } fn local_def_id(&self, index: DefIndex) -> DefId { @@ -529,7 +522,7 @@ impl<'a, 'tcx> CrateMetadata { crate fn def_kind(&self, index: DefIndex) -> Option { if !self.is_proc_macro(index) { - self.entry(index).kind.def_kind() + self.kind(index).def_kind() } else { Some(DefKind::Macro( macro_kind(self.raw_proc_macro(index)) @@ -538,7 +531,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span { - self.entry(index).span.decode((self, sess)) + self.root.per_def.span.get(self, index).unwrap().decode((self, sess)) } crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { @@ -567,12 +560,12 @@ impl<'a, 'tcx> CrateMetadata { helper_attrs, self.root.edition, Symbol::intern(name), - &self.get_attributes(&self.entry(id), sess), + &self.get_item_attrs(id, sess), ) } crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { - match self.entry(item_id).kind { + match self.kind(item_id) { EntryKind::Trait(data) => { let data = data.decode((self, sess)); ty::TraitDef::new(self.local_def_id(item_id), @@ -597,18 +590,24 @@ impl<'a, 'tcx> CrateMetadata { fn get_variant( &self, tcx: TyCtxt<'tcx>, - item: &Entry<'_>, + kind: &EntryKind<'_>, index: DefIndex, parent_did: DefId, - adt_kind: ty::AdtKind, ) -> ty::VariantDef { - let data = match item.kind { + let data = match kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => data.decode(self), _ => bug!(), }; + let adt_kind = match kind { + EntryKind::Variant(_) => ty::AdtKind::Enum, + EntryKind::Struct(..) => ty::AdtKind::Struct, + EntryKind::Union(..) => ty::AdtKind::Union, + _ => bug!(), + }; + let variant_did = if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { @@ -622,14 +621,12 @@ impl<'a, 'tcx> CrateMetadata { variant_did, ctor_did, data.discr, - item.children.decode(self).map(|index| { - let f = self.entry(index); - ty::FieldDef { + self.root.per_def.children.get(self, index).unwrap_or(Lazy::empty()) + .decode(self).map(|index| ty::FieldDef { did: self.local_def_id(index), ident: Ident::with_dummy_span(self.item_name(index)), - vis: f.visibility.decode(self) - } - }).collect(), + vis: self.get_visibility(index), + }).collect(), data.ctor_kind, adt_kind, parent_did, @@ -638,28 +635,28 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { - let item = self.entry(item_id); + let kind = self.kind(item_id); let did = self.local_def_id(item_id); - let (kind, repr) = match item.kind { + let (adt_kind, repr) = match kind { EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; - let variants = if let ty::AdtKind::Enum = kind { - item.children + let variants = if let ty::AdtKind::Enum = adt_kind { + self.root.per_def.children.get(self, item_id).unwrap_or(Lazy::empty()) .decode(self) .map(|index| { - self.get_variant(tcx, &self.entry(index), index, did, kind) + self.get_variant(tcx, &self.kind(index), index, did) }) .collect() } else { - std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect() + std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect() }; - tcx.alloc_adt_def(did, kind, variants, repr) + tcx.alloc_adt_def(did, adt_kind, variants, repr) } crate fn get_predicates( @@ -667,7 +664,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.entry(item_id).predicates.unwrap().decode((self, tcx)) + self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx)) } crate fn get_predicates_defined_on( @@ -675,7 +672,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx)) + self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx)) } crate fn get_super_predicates( @@ -683,7 +680,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - let super_predicates = match self.entry(item_id).kind { + let super_predicates = match self.kind(item_id) { EntryKind::Trait(data) => data.decode(self).super_predicates, EntryKind::TraitAlias(data) => data.decode(self).super_predicates, _ => bug!("def-index does not refer to trait or trait alias"), @@ -693,34 +690,35 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { - self.entry(item_id).generics.unwrap().decode((self, sess)) + self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess)) } crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - self.entry(id).ty.unwrap().decode((self, tcx)) + self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx)) } crate fn get_stability(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { true => self.root.proc_macro_stability.clone(), - false => self.entry(id).stability.map(|stab| stab.decode(self)), + false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)), } } crate fn get_deprecation(&self, id: DefIndex) -> Option { - self.entry_unless_proc_macro(id) - .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) + self.root.per_def.deprecation.get(self, id) + .filter(|_| !self.is_proc_macro(id)) + .map(|depr| depr.decode(self)) } crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility { match self.is_proc_macro(id) { true => ty::Visibility::Public, - false => self.entry(id).visibility.decode(self), + false => self.root.per_def.visibility.get(self, id).unwrap().decode(self), } } fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Impl(data) => data.decode(self), _ => bug!(), } @@ -816,38 +814,42 @@ impl<'a, 'tcx> CrateMetadata { } // Find the item. - let item = match self.maybe_entry(id) { + let kind = match self.maybe_kind(id) { None => return, - Some(item) => item.decode((self, sess)), + Some(kind) => kind, }; // Iterate over all children. let macros_only = self.dep_kind.lock().macros_only(); - for child_index in item.children.decode((self, sess)) { + let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()); + for child_index in children.decode((self, sess)) { if macros_only { continue } // Get the item. - if let Some(child) = self.maybe_entry(child_index) { - let child = child.decode((self, sess)); - match child.kind { + if let Some(child_kind) = self.maybe_kind(child_index) { + match child_kind { EntryKind::MacroDef(..) => {} _ if macros_only => continue, _ => {} } // Hand off the item to the callback. - match child.kind { + match child_kind { // FIXME(eddyb) Don't encode these in children. EntryKind::ForeignMod => { - for child_index in child.children.decode((self, sess)) { + let child_children = + self.root.per_def.children.get(self, child_index) + .unwrap_or(Lazy::empty()); + for child_index in child_children.decode((self, sess)) { if let Some(kind) = self.def_kind(child_index) { callback(def::Export { res: Res::Def(kind, self.local_def_id(child_index)), ident: Ident::with_dummy_span(self.item_name(child_index)), vis: self.get_visibility(child_index), - span: self.entry(child_index).span.decode((self, sess)), + span: self.root.per_def.span.get(self, child_index).unwrap() + .decode((self, sess)), }); } } @@ -859,7 +861,7 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); - let span = child.span.decode((self, sess)); + let span = self.get_span(child_index, sess); if let (Some(kind), Some(name)) = (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) { let ident = Ident::from_interned_str(name); @@ -912,7 +914,7 @@ impl<'a, 'tcx> CrateMetadata { } } - if let EntryKind::Mod(data) = item.kind { + if let EntryKind::Mod(data) = kind { for exp in data.decode((self, sess)).reexports.decode((self, sess)) { match exp.res { Res::Def(DefKind::Macro(..), _) => {} @@ -926,15 +928,16 @@ impl<'a, 'tcx> CrateMetadata { crate fn is_item_mir_available(&self, id: DefIndex) -> bool { !self.is_proc_macro(id) && - self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() + self.root.per_def.mir.get(self, id).is_some() } crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { - self.entry_unless_proc_macro(id) - .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) + self.root.per_def.mir.get(self, id) + .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) + .decode((self, tcx)) } crate fn get_promoted_mir( @@ -942,15 +945,16 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> IndexVec> { - self.entry_unless_proc_macro(id) - .and_then(|entry| entry.promoted_mir.map(|promoted| promoted.decode((self, tcx)))) + self.root.per_def.promoted_mir.get(self, id) + .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) + .decode((self, tcx)) } crate fn mir_const_qualif(&self, id: DefIndex) -> u8 { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Const(qualif, _) | EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) | EntryKind::AssocConst(AssocContainer::ImplFinal, qualif, _) => { @@ -961,12 +965,11 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { - let item = self.entry(id); let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); - let (kind, container, has_self) = match item.kind { + let (kind, container, has_self) = match self.kind(id) { EntryKind::AssocConst(container, _, _) => { (ty::AssocKind::Const, container, false) } @@ -986,7 +989,7 @@ impl<'a, 'tcx> CrateMetadata { ty::AssocItem { ident: Ident::from_interned_str(name), kind, - vis: item.visibility.decode(self), + vis: self.get_visibility(id), defaultness: container.defaultness(), def_id: self.local_def_id(id), container: container.with_def_id(parent), @@ -995,11 +998,12 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_item_variances(&self, id: DefIndex) -> Vec { - self.entry(id).variances.decode(self).collect() + self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty()) + .decode(self).collect() } crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { - match self.entry(node_id).kind { + match self.kind(node_id) { EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => data.decode(self).ctor_kind, @@ -1008,7 +1012,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { - match self.entry(node_id).kind { + match self.kind(node_id) { EntryKind::Struct(data, _) => { data.decode(self).ctor.map(|index| self.local_def_id(index)) } @@ -1030,8 +1034,9 @@ impl<'a, 'tcx> CrateMetadata { node_id }; - let item = self.entry(item_id); - Lrc::from(self.get_attributes(&item, sess)) + Lrc::from(self.root.per_def.attributes.get(self, item_id).unwrap_or(Lazy::empty()) + .decode((self, sess)) + .collect::>()) } crate fn get_struct_field_names( @@ -1039,17 +1044,12 @@ impl<'a, 'tcx> CrateMetadata { id: DefIndex, sess: &Session, ) -> Vec> { - self.entry(id) - .children + self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()) .decode(self) .map(|index| respan(self.get_span(index, sess), self.item_name(index))) .collect() } - fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec { - item.attributes.decode((self, sess)).collect() - } - // Translate a DefId from the current compilation environment to a DefId // for an external crate. fn reverse_translate_def_id(&self, did: DefId) -> Option { @@ -1070,10 +1070,11 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> &'tcx [DefId] { - tcx.arena.alloc_from_iter(self.entry(id) - .inherent_impls - .decode(self) - .map(|index| self.local_def_id(index))) + tcx.arena.alloc_from_iter( + self.root.per_def.inherent_impls.get(self, id).unwrap_or(Lazy::empty()) + .decode(self) + .map(|index| self.local_def_id(index)) + ) } crate fn get_implementations_for_trait( @@ -1115,7 +1116,7 @@ impl<'a, 'tcx> CrateMetadata { _ => return None, } def_key.parent.and_then(|parent_index| { - match self.entry(parent_index).kind { + match self.kind(parent_index) { EntryKind::Trait(_) | EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)), _ => None, @@ -1168,7 +1169,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_fn_param_names(&self, id: DefIndex) -> Vec { - let param_names = match self.entry(id).kind { + let param_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, EntryKind::Method(data) => data.decode(self).fn_data.param_names, @@ -1191,7 +1192,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_rendered_const(&self, id: DefIndex) -> String { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Const(_, data) | EntryKind::AssocConst(_, _, data) => data.decode(self).0, _ => bug!(), @@ -1199,15 +1200,14 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_macro(&self, id: DefIndex) -> MacroDef { - let entry = self.entry(id); - match entry.kind { + match self.kind(id) { EntryKind::MacroDef(macro_def) => macro_def.decode(self), _ => bug!(), } } crate fn is_const_fn_raw(&self, id: DefIndex) -> bool { - let constness = match self.entry(id).kind { + let constness = match self.kind(id) { EntryKind::Method(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const, @@ -1217,16 +1217,16 @@ impl<'a, 'tcx> CrateMetadata { } crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, EntryKind::ForeignFn(data) => data.decode(self).asyncness, - _ => bug!("asyncness: expect functions entry."), + _ => bug!("asyncness: expected function kind"), } } crate fn is_foreign_item(&self, id: DefIndex) -> bool { - match self.entry(id).kind { + match self.kind(id) { EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => true, @@ -1235,7 +1235,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn static_mutability(&self, id: DefIndex) -> Option { - match self.entry(id).kind { + match self.kind(id) { EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Some(hir::MutImmutable), EntryKind::MutStatic | @@ -1245,7 +1245,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let sig = match self.entry(id).kind { + let sig = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).sig, EntryKind::Method(data) => data.decode(self).fn_data.sig, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c9426aaece941..3bc3fee4164f2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -15,7 +15,7 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::traits::specialization_graph; -use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; +use rustc::ty::{self, Ty, TyCtxt, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::layout::VariantIdx; @@ -61,7 +61,23 @@ struct EncodeContext<'tcx> { } struct PerDefTables<'tcx> { - entry: PerDefTable>>, + kind: PerDefTable>>, + visibility: PerDefTable>, + span: PerDefTable>, + attributes: PerDefTable>, + children: PerDefTable>, + stability: PerDefTable>, + deprecation: PerDefTable>, + + ty: PerDefTable>>, + inherent_impls: PerDefTable>, + variances: PerDefTable>, + generics: PerDefTable>, + predicates: PerDefTable>>, + predicates_defined_on: PerDefTable>>, + + mir: PerDefTable>>, + promoted_mir: PerDefTable>>>, } macro_rules! encoder_methods { @@ -482,7 +498,23 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); let per_def = LazyPerDefTables { - entry: self.per_def.entry.encode(&mut self.opaque), + kind: self.per_def.kind.encode(&mut self.opaque), + visibility: self.per_def.visibility.encode(&mut self.opaque), + span: self.per_def.span.encode(&mut self.opaque), + attributes: self.per_def.attributes.encode(&mut self.opaque), + children: self.per_def.children.encode(&mut self.opaque), + stability: self.per_def.stability.encode(&mut self.opaque), + deprecation: self.per_def.deprecation.encode(&mut self.opaque), + + ty: self.per_def.ty.encode(&mut self.opaque), + inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), + variances: self.per_def.variances.encode(&mut self.opaque), + generics: self.per_def.generics.encode(&mut self.opaque), + predicates: self.per_def.predicates.encode(&mut self.opaque), + predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), + + mir: self.per_def.mir.encode(&mut self.opaque), + promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque), }; let per_def_bytes = self.position() - i; @@ -578,17 +610,14 @@ impl<'tcx> EncodeContext<'tcx> { } impl EncodeContext<'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { + fn encode_variances_of(&mut self, def_id: DefId) { debug!("EncodeContext::encode_variances_of({:?})", def_id); - let tcx = self.tcx; - self.lazy(&tcx.variances_of(def_id)[..]) + record!(self.per_def.variances[def_id] <- &self.tcx.variances_of(def_id)[..]); } - fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { - let tcx = self.tcx; - let ty = tcx.type_of(def_id); - debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); - self.lazy(ty) + fn encode_item_type(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_item_type({:?})", def_id); + record!(self.per_def.ty[def_id] <- self.tcx.type_of(def_id)); } fn encode_enum_variant_info( @@ -617,32 +646,25 @@ impl EncodeContext<'tcx> { let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item(enum_id).vis; - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy(variant.fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data))); + record!(self.per_def.visibility[def_id] <- + ty::Visibility::from_hir(enum_vis, enum_id, self.tcx)); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); + record!(self.per_def.children[def_id] <- variant.fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_enum_variant_ctor( @@ -676,29 +698,19 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data))); + record!(self.per_def.visibility[def_id] <- ctor_vis); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_info_for_mod( @@ -719,27 +731,15 @@ impl EncodeContext<'tcx> { }, }; - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Mod(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(attrs), - children: self.lazy(md.item_ids.iter().map(|item_id| { - tcx.hir().local_def_id(item_id.id).index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- EntryKind::Mod(self.lazy(data))); + record!(self.per_def.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx)); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- attrs); + record!(self.per_def.children[def_id] <- md.item_ids.iter().map(|item_id| { + tcx.hir().local_def_id(item_id.id).index + })); + self.encode_stability(def_id); + self.encode_deprecation(def_id); } fn encode_field( @@ -758,25 +758,15 @@ impl EncodeContext<'tcx> { let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Field, - visibility: self.lazy(field.vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- EntryKind::Field); + record!(self.per_def.visibility[def_id] <- field.vis); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- &variant_data.fields()[field_index].attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_predicates(def_id); } fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { @@ -813,49 +803,35 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - let repr_options = get_repr_options(tcx, adt_def_id); - - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Struct(self.lazy(data), repr_options), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + record!(self.per_def.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr)); + record!(self.per_def.visibility[def_id] <- ctor_vis); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } - fn encode_generics(&mut self, def_id: DefId) -> Lazy { + fn encode_generics(&mut self, def_id: DefId) { debug!("EncodeContext::encode_generics({:?})", def_id); - let tcx = self.tcx; - self.lazy(tcx.generics_of(def_id)) + record!(self.per_def.generics[def_id] <- self.tcx.generics_of(def_id)); } - fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { + fn encode_predicates(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates({:?})", def_id); - let tcx = self.tcx; - self.lazy(&*tcx.predicates_of(def_id)) + record!(self.per_def.predicates[def_id] <- &*self.tcx.predicates_of(def_id)); } - fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { + fn encode_predicates_defined_on(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); - let tcx = self.tcx; - self.lazy(&*tcx.predicates_defined_on(def_id)) + record!(self.per_def.predicates_defined_on[def_id] <- + &*self.tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) { @@ -875,7 +851,7 @@ impl EncodeContext<'tcx> { span_bug!(ast_item.span, "traits cannot have final items"), }; - let kind = match trait_item.kind { + record!(self.per_def.kind[def_id] <- match trait_item.kind { ty::AssocKind::Const => { let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); @@ -884,7 +860,7 @@ impl EncodeContext<'tcx> { EntryKind::AssocConst(container, ConstQualif { mir: 0 }, rendered_const) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.kind { + let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind { let param_names = match *m { hir::TraitMethod::Required(ref names) => { self.encode_fn_param_names(names) @@ -894,10 +870,10 @@ impl EncodeContext<'tcx> { } }; FnData { - asyncness: method_sig.header.asyncness, + asyncness: m_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -910,44 +886,31 @@ impl EncodeContext<'tcx> { } ty::AssocKind::Type => EntryKind::AssocType(container), ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"), - }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(trait_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match trait_item.kind { - ty::AssocKind::Const | - ty::AssocKind::Method => { - Some(self.encode_item_type(def_id)) - } - ty::AssocKind::Type => { - if trait_item.defaultness.has_value() { - Some(self.encode_item_type(def_id)) - } else { - None - } + }); + record!(self.per_def.visibility[def_id] <- trait_item.vis); + record!(self.per_def.span[def_id] <- ast_item.span); + record!(self.per_def.attributes[def_id] <- &ast_item.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + match trait_item.kind { + ty::AssocKind::Const | + ty::AssocKind::Method => { + self.encode_item_type(def_id); + } + ty::AssocKind::Type => { + if trait_item.defaultness.has_value() { + self.encode_item_type(def_id); } - ty::AssocKind::OpaqueTy => unreachable!(), - }, - inherent_impls: Lazy::empty(), - variances: if trait_item.kind == ty::AssocKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + } + ty::AssocKind::OpaqueTy => unreachable!(), + } + if trait_item.kind == ty::AssocKind::Method { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn metadata_output_only(&self) -> bool { @@ -970,7 +933,7 @@ impl EncodeContext<'tcx> { span_bug!(ast_item.span, "impl items always have values (currently)"), }; - let kind = match impl_item.kind { + record!(self.per_def.kind[def_id] <- match impl_item.kind { ty::AssocKind::Const => { if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind { let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; @@ -988,7 +951,7 @@ impl EncodeContext<'tcx> { asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -1001,8 +964,18 @@ impl EncodeContext<'tcx> { } ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container), ty::AssocKind::Type => EntryKind::AssocType(container) - }; - + }); + record!(self.per_def.visibility[def_id] <- impl_item.vis); + record!(self.per_def.span[def_id] <- ast_item.span); + record!(self.per_def.attributes[def_id] <- &ast_item.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if impl_item.kind == ty::AssocKind::Method { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); let mir = match ast_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(ref sig, _) => { @@ -1017,30 +990,10 @@ impl EncodeContext<'tcx> { hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => false, }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(impl_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if impl_item.kind == ty::AssocKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: if mir { self.encode_optimized_mir(def_id) } else { None }, - promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - }) + if mir { + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); + } } fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) @@ -1060,51 +1013,44 @@ impl EncodeContext<'tcx> { self.lazy(param_names.iter().map(|ident| ident.name)) } - fn encode_optimized_mir(&mut self, def_id: DefId) -> Option>> { + fn encode_optimized_mir(&mut self, def_id: DefId) { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - let mir = self.tcx.optimized_mir(def_id); - Some(self.lazy(mir)) - } else { - None + record!(self.per_def.mir[def_id] <- self.tcx.optimized_mir(def_id)); } } - fn encode_promoted_mir( - &mut self, - def_id: DefId, - ) -> Option>>> { + fn encode_promoted_mir(&mut self, def_id: DefId) { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - let promoted = self.tcx.promoted_mir(def_id); - Some(self.lazy(promoted)) - } else { - None + record!(self.per_def.promoted_mir[def_id] <- self.tcx.promoted_mir(def_id)); } } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { + fn encode_inherent_implementations(&mut self, def_id: DefId) { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); - if implementations.is_empty() { - Lazy::empty() - } else { - self.lazy(implementations.iter().map(|&def_id| { + if !implementations.is_empty() { + record!(self.per_def.inherent_impls[def_id] <- implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index - })) + })); } } - fn encode_stability(&mut self, def_id: DefId) -> Option> { + fn encode_stability(&mut self, def_id: DefId) { debug!("EncodeContext::encode_stability({:?})", def_id); - self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) + if let Some(stab) = self.tcx.lookup_stability(def_id) { + record!(self.per_def.stability[def_id] <- stab) + } } - fn encode_deprecation(&mut self, def_id: DefId) -> Option> { + fn encode_deprecation(&mut self, def_id: DefId) { debug!("EncodeContext::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(depr)) + if let Some(depr) = self.tcx.lookup_deprecation(def_id) { + record!(self.per_def.deprecation[def_id] <- depr); + } } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy { @@ -1119,11 +1065,11 @@ impl EncodeContext<'tcx> { debug!("EncodeContext::encode_info_for_item({:?})", def_id); - let kind = match item.kind { + record!(self.per_def.kind[def_id] <- match item.kind { hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, hir::ItemKind::Const(_, body_id) => { - let mir = tcx.at(item.span).mir_const_qualif(def_id).0; + let mir = self.tcx.at(item.span).mir_const_qualif(def_id).0; EntryKind::Const( ConstQualif { mir }, self.encode_rendered_const_for_body(body_id) @@ -1146,42 +1092,42 @@ impl EncodeContext<'tcx> { hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, hir::ItemKind::TyAlias(..) => EntryKind::Type, hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy, - hir::ItemKind::Enum(..) => EntryKind::Enum(get_repr_options(tcx, def_id)), + hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr), hir::ItemKind::Struct(ref struct_def, _) => { - let variant = tcx.adt_def(def_id).non_enum_variant(); + let adt_def = self.tcx.adt_def(def_id); + let variant = adt_def.non_enum_variant(); // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method // needs to know - let ctor = struct_def.ctor_hir_id() - .map(|ctor_hir_id| tcx.hir().local_def_id(ctor_hir_id).index); - - let repr_options = get_repr_options(tcx, def_id); + let ctor = struct_def.ctor_hir_id().map(|ctor_hir_id| { + self.tcx.hir().local_def_id(ctor_hir_id).index + }); EntryKind::Struct(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, ctor_sig: None, - }), repr_options) + }), adt_def.repr) } hir::ItemKind::Union(..) => { - let variant = tcx.adt_def(def_id).non_enum_variant(); - let repr_options = get_repr_options(tcx, def_id); + let adt_def = self.tcx.adt_def(def_id); + let variant = adt_def.non_enum_variant(); EntryKind::Union(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, ctor_sig: None, - }), repr_options) + }), adt_def.repr) } hir::ItemKind::Impl(_, _, defaultness, ..) => { - let trait_ref = tcx.impl_trait_ref(def_id); - let polarity = tcx.impl_polarity(def_id); + let trait_ref = self.tcx.impl_trait_ref(def_id); + let polarity = self.tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { - let trait_def = tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { + let trait_def = self.tcx.trait_def(trait_ref.def_id); + trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| { match node { specialization_graph::Node::Impl(parent) => Some(parent), _ => None, @@ -1195,8 +1141,8 @@ impl EncodeContext<'tcx> { // "unsized info", else just store None let coerce_unsized_info = trait_ref.and_then(|t| { - if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() { - Some(tcx.at(item.span).coerce_unsized_info(def_id)) + if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() { + Some(self.tcx.at(item.span).coerce_unsized_info(def_id)) } else { None } @@ -1213,11 +1159,11 @@ impl EncodeContext<'tcx> { EntryKind::Impl(self.lazy(data)) } hir::ItemKind::Trait(..) => { - let trait_def = tcx.trait_def(def_id); + let trait_def = self.tcx.trait_def(def_id); let data = TraitData { unsafety: trait_def.unsafety, paren_sugar: trait_def.paren_sugar, - has_auto_impl: tcx.trait_is_auto(def_id), + has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; @@ -1233,7 +1179,95 @@ impl EncodeContext<'tcx> { } hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), - }; + }); + record!(self.per_def.visibility[def_id] <- + ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)); + record!(self.per_def.span[def_id] <- item.span); + record!(self.per_def.attributes[def_id] <- &item.attrs); + // FIXME(eddyb) there should be a nicer way to do this. + match item.kind { + hir::ItemKind::ForeignMod(ref fm) => record!(self.per_def.children[def_id] <- + fm.items + .iter() + .map(|foreign_item| tcx.hir().local_def_id( + foreign_item.hir_id).index) + ), + hir::ItemKind::Enum(..) => record!(self.per_def.children[def_id] <- + self.tcx.adt_def(def_id).variants.iter().map(|v| { + assert!(v.def_id.is_local()); + v.def_id.index + }) + ), + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) => record!(self.per_def.children[def_id] <- + self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + }) + ), + hir::ItemKind::Impl(..) | + hir::ItemKind::Trait(..) => { + let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); + record!(self.per_def.children[def_id] <- + associated_item_def_ids.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + }) + ); + } + _ => {} + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) => self.encode_item_type(def_id), + _ => {} + } + self.encode_inherent_implementations(def_id); + match item.kind { + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => {} + } + match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_generics(def_id); + self.encode_predicates(def_id); + } + _ => {} + } + // The only time that `predicates_defined_on` is used (on + // an external item) is for traits, during chalk lowering, + // so only encode it in that case as an efficiency + // hack. (No reason not to expand it in the future if + // necessary.) + match item.kind { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_predicates_defined_on(def_id); + } + _ => {} // not *wrong* for other kinds of items, but not needed + } let mir = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, @@ -1248,174 +1282,48 @@ impl EncodeContext<'tcx> { } _ => false, }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(item.span), - attributes: self.encode_attributes(&item.attrs), - children: match item.kind { - hir::ItemKind::ForeignMod(ref fm) => { - self.lazy(fm.items - .iter() - .map(|foreign_item| tcx.hir().local_def_id( - foreign_item.hir_id).index)) - } - hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.variants.iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - })) - } - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.non_enum_variant().fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })) - } - hir::ItemKind::Impl(..) | - hir::ItemKind::Trait(..) => { - self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - })) - } - _ => Lazy::empty(), - }, - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), - _ => None, - }, - inherent_impls: self.encode_inherent_implementations(def_id), - variances: match item.kind { - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), - hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), - _ => None, - }, - predicates: match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), - _ => None, - }, - - // The only time that `predicates_defined_on` is used (on - // an external item) is for traits, during chalk lowering, - // so only encode it in that case as an efficiency - // hack. (No reason not to expand it in the future if - // necessary.) - predicates_defined_on: match item.kind { - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => { - Some(self.encode_predicates_defined_on(def_id)) - } - _ => None, // not *wrong* for other kinds of items, but not needed - }, - - mir: if mir { self.encode_optimized_mir(def_id) } else { None }, - promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - }) + if mir { + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); + } } /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tts_to_string(macro_def.body.clone()), - legacy: macro_def.legacy, - })), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(macro_def.span), - attributes: self.encode_attributes(¯o_def.attrs), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - children: Lazy::empty(), - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef { + body: pprust::tts_to_string(macro_def.body.clone()), + legacy: macro_def.legacy, + }))); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- macro_def.span); + record!(self.per_def.attributes[def_id] <- ¯o_def.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); } fn encode_info_for_generic_param( &mut self, def_id: DefId, - entry_kind: EntryKind<'tcx>, + kind: EntryKind<'tcx>, encode_type: bool, ) { - let tcx = self.tcx; - record!(self.per_def.entry[def_id] <- Entry { - kind: entry_kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- kind); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + if encode_type { + self.encode_item_type(def_id); + } } fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); - let tcx = self.tcx; let tables = self.tcx.typeck_tables_of(def_id); let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); - let kind = match tables.node_type(hir_id).kind { + + record!(self.per_def.kind[def_id] <- match tables.node_type(hir_id).kind { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { @@ -1430,61 +1338,32 @@ impl EncodeContext<'tcx> { EntryKind::Closure(self.lazy(data)) } - _ => bug!("closure that is neither generator nor closure") - }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: None, - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + _ => bug!("closure that is neither generator nor closure"), + }); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_info_for_anon_const(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); - let tcx = self.tcx; - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let body_id = tcx.hir().body_owned_by(id); + let id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); + let body_id = self.tcx.hir().body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); - let mir = tcx.mir_const_qualif(def_id).0; - - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Const(ConstQualif { mir }, const_data), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) - } + let mir = self.tcx.mir_const_qualif(def_id).0; - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { - self.lazy(attrs) + record!(self.per_def.kind[def_id] <- EntryKind::Const(ConstQualif { mir }, const_data)); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { @@ -1667,7 +1546,7 @@ impl EncodeContext<'tcx> { debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); - let kind = match nitem.kind { + record!(self.per_def.kind[def_id] <- match nitem.kind { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { asyncness: hir::IsAsync::NotAsync, @@ -1680,30 +1559,19 @@ impl EncodeContext<'tcx> { hir::ForeignItemKind::Static(_, hir::MutMutable) => EntryKind::ForeignMutStatic, hir::ForeignItemKind::Static(_, hir::MutImmutable) => EntryKind::ForeignImmStatic, hir::ForeignItemKind::Type => EntryKind::ForeignType, - }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(nitem.span), - attributes: self.encode_attributes(&nitem.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: match nitem.kind { - hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + }); + record!(self.per_def.visibility[def_id] <- + ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx)); + record!(self.per_def.span[def_id] <- nitem.span); + record!(self.per_def.attributes[def_id] <- &nitem.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if let hir::ForeignItemKind::Fn(..) = nitem.kind { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); } } @@ -1906,11 +1774,28 @@ 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 { - entry: PerDefTable::new(tcx.hir().definitions().def_index_count()), + 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), }, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), @@ -1939,11 +1824,3 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { EncodedMetadata { raw_data: result } } - -fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { - let ty = tcx.type_of(did); - match ty.kind { - ty::Adt(ref def, _) => return def.repr, - _ => bug!("{} is not an ADT", ty), - } -} diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index e70ba2532caaf..96f35783278fa 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -229,28 +229,23 @@ crate struct TraitImpls { #[derive(RustcEncodable, RustcDecodable)] crate struct LazyPerDefTables<'tcx> { - pub entry: Lazy!(PerDefTable>>), -} - -#[derive(RustcEncodable, RustcDecodable)] -crate struct Entry<'tcx> { - pub kind: EntryKind<'tcx>, - pub visibility: Lazy, - pub span: Lazy, - pub attributes: Lazy<[ast::Attribute]>, - pub children: Lazy<[DefIndex]>, - pub stability: Option>, - pub deprecation: Option>, - - pub ty: Option)>, - pub inherent_impls: Lazy<[DefIndex]>, - pub variances: Lazy<[ty::Variance]>, - pub generics: Option>, - pub predicates: Option)>, - pub predicates_defined_on: Option)>, - - pub mir: Option)>, - pub promoted_mir: Option>)>, + pub kind: Lazy!(PerDefTable)>), + pub visibility: Lazy!(PerDefTable>), + pub span: Lazy!(PerDefTable>), + pub attributes: Lazy!(PerDefTable>), + pub children: Lazy!(PerDefTable>), + pub stability: Lazy!(PerDefTable>), + pub deprecation: Lazy!(PerDefTable>), + + pub ty: Lazy!(PerDefTable)>), + pub inherent_impls: Lazy!(PerDefTable>), + pub variances: Lazy!(PerDefTable>), + pub generics: Lazy!(PerDefTable>), + pub predicates: Lazy!(PerDefTable)>), + pub predicates_defined_on: Lazy!(PerDefTable)>), + + pub mir: Lazy!(PerDefTable)>), + pub promoted_mir: Lazy!(PerDefTable>)>), } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] From 34066d60c38b8e1049a60e1eaf26cd84a67e7655 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 05:21:39 +0300 Subject: [PATCH 12/13] 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 3bc3fee4164f2..f1436e4c09dff 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 0585aa1d3884e..5cfa137d04f7d 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); From d89dddc9204a540efcd7f86c36d60381020b2422 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Oct 2019 18:42:08 +0300 Subject: [PATCH 13/13] rustc_metadata: address some review comments. --- src/librustc_metadata/table.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 5cfa137d04f7d..e164c28c953bc 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -23,7 +23,13 @@ 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. + + /// Read a `Self` value (encoded as `Self::BYTE_LEN` bytes), + /// from `&b[i * Self::BYTE_LEN..]`, returning `None` if `i` + /// is not in bounds, or `Some(Self::from_bytes(...))` otherwise. fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option; + /// Write a `Self` value (encoded as `Self::BYTE_LEN` bytes), + /// at `&mut b[i * Self::BYTE_LEN..]`, using `Self::write_to_bytes`. fn write_to_bytes_at(self, b: &mut [u8], i: usize); } @@ -112,8 +118,11 @@ impl FixedSizeEncoding for Option> { } } -/// Random-access table, similar to `Vec>`, but without requiring -/// encoding or decoding all the values eagerly and in-order. +/// Random-access table (i.e. offeringconstant-time `get`/`set`), similar to +/// `Vec>`, but without requiring encoding or decoding all the values +/// eagerly and in-order. +/// A total of `(max_idx + 1) * as FixedSizeEncoding>::BYTE_LEN` bytes +/// are used for a table, where `max_idx` is the largest index passed to `set`. // FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box>` would be used // when building it, and `Lazy>` or `&Table` when reading it. // (not sure if that is possible given that the `Vec` is being resized now) @@ -135,10 +144,16 @@ impl Default for Table where Option: FixedSizeEncoding { impl Table where Option: FixedSizeEncoding { crate fn set(&mut self, i: usize, value: T) { + // FIXME(eddyb) investigate more compact encodings for sparse tables. + // On the PR @michaelwoerister mentioned: + // > Space requirements could perhaps be optimized by using the HAMT `popcnt` + // > trick (i.e. divide things into buckets of 32 or 64 items and then + // > store bit-masks of which item in each bucket is actually serialized). 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); } @@ -170,12 +185,13 @@ impl Lazy> where Option: FixedSizeEncoding { ) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; + let start = self.position.get(); + let bytes = &metadata.raw_bytes()[start..start + self.meta]; >::maybe_read_from_bytes_at(bytes, i)? } } -/// Per-definition table, similar to `Table` but keyed on `DefIndex`. +/// Like a `Table` but using `DefIndex` instead of `usize` as keys. // FIXME(eddyb) replace by making `Table` behave like `IndexVec`, // and by using `newtype_index!` to define `DefIndex`. crate struct PerDefTable(Table) where Option: FixedSizeEncoding;