Skip to content

Commit

Permalink
rustc_metadata: split tables into an usize-keyed Table and a DefIndex…
Browse files Browse the repository at this point in the history
…-keyed PerDefTable.
  • Loading branch information
eddyb committed Oct 15, 2019
1 parent dd1264e commit 5d52a7e
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 37 deletions.
6 changes: 3 additions & 3 deletions src/librustc_metadata/decoder.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -255,10 +255,10 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a,
}
}

impl<'a, 'tcx, T> SpecializedDecoder<Lazy<Table<T>>> for DecodeContext<'a, 'tcx>
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<PerDefTable<T>>> for DecodeContext<'a, 'tcx>
where T: LazyMeta<Meta = ()>,
{
fn specialized_decode(&mut self) -> Result<Lazy<Table<T>>, Self::Error> {
fn specialized_decode(&mut self) -> Result<Lazy<PerDefTable<T>>, Self::Error> {
let len = self.read_usize()?;
self.read_lazy_with_meta(len)
}
Expand Down
10 changes: 5 additions & 5 deletions 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};
Expand Down Expand Up @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> {
opaque: opaque::Encoder,
tcx: TyCtxt<'tcx>,

entries_table: Table<Entry<'tcx>>,
entries_table: PerDefTable<Entry<'tcx>>,

lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
Expand Down Expand Up @@ -114,10 +114,10 @@ impl<'tcx, T: Encodable> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
}
}

impl<'tcx, T> SpecializedEncoder<Lazy<Table<T>>> for EncodeContext<'tcx>
impl<'tcx, T> SpecializedEncoder<Lazy<PerDefTable<T>>> for EncodeContext<'tcx>
where T: LazyMeta<Meta = ()>,
{
fn specialized_encode(&mut self, lazy: &Lazy<Table<T>>) -> Result<(), Self::Error> {
fn specialized_encode(&mut self, lazy: &Lazy<PerDefTable<T>>) -> Result<(), Self::Error> {
self.emit_usize(lazy.meta)?;
self.emit_lazy_distance(*lazy)
}
Expand Down Expand Up @@ -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(),
Expand Down
5 changes: 3 additions & 2 deletions 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};
Expand Down Expand Up @@ -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<Table<$T>, usize>};
(PerDefTable<$T:ty>) => {Lazy<PerDefTable<$T>, usize>};
([$T:ty]) => {Lazy<[$T], usize>};
($T:ty) => {Lazy<$T, ()>};
}
Expand Down Expand Up @@ -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<Entry<'tcx>>),
pub entries_table: Lazy!(PerDefTable<Entry<'tcx>>),

/// The DefIndex's of any proc macros delcared by
/// this crate
Expand Down
91 changes: 64 additions & 27 deletions src/librustc_metadata/table.rs
Expand Up @@ -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<Lazy<T>>`, but with zero-copy decoding.
// FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
// and so would need two lengths in its metadata, which is not supported yet.
crate struct Table<T: LazyMeta<Meta = ()>> {
positions: Vec<u8>,
bytes: Vec<u8>,
_marker: PhantomData<T>,
}

impl<T: LazyMeta<Meta = ()>> Table<T> {
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<T>) {
assert!(def_id.is_local());
self.record_index(def_id.index, entry);
}

crate fn record_index(&mut self, item: DefIndex, entry: Lazy<T>) {
crate fn record(&mut self, i: usize, entry: Lazy<T>) {
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<Self> {
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(),
)
}
}
Expand All @@ -119,22 +116,62 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
type Meta = usize;

fn min_size(len: usize) -> usize {
len * 4
len
}
}

impl<T: Encodable> Lazy<Table<T>> {
/// 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<Lazy<T>> {
debug!("Table::lookup: index={:?} len={:?}",
def_index,
self.meta);
crate fn lookup(&self, bytes: &[u8], i: usize) -> Option<Lazy<T>> {
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<T: LazyMeta<Meta = ()>>(Table<T>);

impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
crate fn new(def_index_count: usize) -> Self {
PerDefTable(Table::new(def_index_count))
}

crate fn record(&mut self, def_id: DefId, entry: Lazy<T>) {
assert!(def_id.is_local());
self.0.record(def_id.index.index(), entry);
}

crate fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
let lazy = self.0.encode(buf);
Lazy::from_position_and_meta(lazy.position, lazy.meta)
}
}

impl<T: LazyMeta<Meta = ()>> LazyMeta for PerDefTable<T> {
type Meta = <Table<T> as LazyMeta>::Meta;

fn min_size(meta: Self::Meta) -> usize {
Table::<T>::min_size(meta)
}
}

impl<T: Encodable> Lazy<PerDefTable<T>> {
fn as_table(&self) -> Lazy<Table<T>> {
Lazy::from_position_and_meta(self.position, self.meta)
}

/// Given the metadata, extract out the offset of a particular DefIndex (if any).
#[inline(never)]
crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> {
self.as_table().lookup(bytes, def_index.index())
}
}

0 comments on commit 5d52a7e

Please sign in to comment.