Skip to content

Commit 47dfc2f

Browse files
committed
rustc_metadata: split tables into an usize-keyed Table and a DefIndex-keyed PerDefTable.
1 parent 538f882 commit 47dfc2f

File tree

4 files changed

+103
-60
lines changed

4 files changed

+103
-60
lines changed

src/librustc_metadata/decoder.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
44
use crate::schema::*;
5-
use crate::table::Table;
5+
use crate::table::PerDefTable;
66

77
use rustc_data_structures::sync::{Lrc, ReadGuard};
88
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
@@ -254,12 +254,15 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a,
254254
}
255255
}
256256

257-
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<Table<T>>> for DecodeContext<'a, 'tcx>
257+
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<PerDefTable<T>>> for DecodeContext<'a, 'tcx>
258258
where T: LazyMeta<Meta = ()>,
259259
{
260-
fn specialized_decode(&mut self) -> Result<Lazy<Table<T>>, Self::Error> {
261-
let len = self.read_usize()?;
262-
self.read_lazy_with_meta(len)
260+
fn specialized_decode(&mut self) -> Result<Lazy<PerDefTable<T>>, Self::Error> {
261+
let lo_hi = [
262+
self.read_usize()?,
263+
self.read_usize()?,
264+
];
265+
self.read_lazy_with_meta(lo_hi)
263266
}
264267
}
265268

src/librustc_metadata/encoder.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::schema::*;
2-
use crate::table::Table;
2+
use crate::table::PerDefTable;
33

44
use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
55
EncodedMetadata, ForeignModule};
@@ -45,7 +45,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
4545
opaque: opaque::Encoder,
4646
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
4747

48-
entries_table: Table<Entry<'tcx>>,
48+
entries_table: PerDefTable<Entry<'tcx>>,
4949

5050
lazy_state: LazyState,
5151
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@@ -112,11 +112,12 @@ impl<'a, 'tcx, T: Encodable> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'a,
112112
}
113113
}
114114

115-
impl<'a, 'tcx, T> SpecializedEncoder<Lazy<Table<T>>> for EncodeContext<'a, 'tcx>
115+
impl<'a, 'tcx, T> SpecializedEncoder<Lazy<PerDefTable<T>>> for EncodeContext<'a, 'tcx>
116116
where T: LazyMeta<Meta = ()>,
117117
{
118-
fn specialized_encode(&mut self, lazy: &Lazy<Table<T>>) -> Result<(), Self::Error> {
119-
self.emit_usize(lazy.meta)?;
118+
fn specialized_encode(&mut self, lazy: &Lazy<PerDefTable<T>>) -> Result<(), Self::Error> {
119+
self.emit_usize(lazy.meta[0])?;
120+
self.emit_usize(lazy.meta[1])?;
120121
self.emit_lazy_distance(*lazy)
121122
}
122123
}
@@ -1884,7 +1885,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
18841885
let mut ecx = EncodeContext {
18851886
opaque: encoder,
18861887
tcx,
1887-
entries_table: Table::new(tcx.hir().definitions().def_index_counts_lo_hi()),
1888+
entries_table: PerDefTable::new(tcx.hir().definitions().def_index_counts_lo_hi()),
18881889
lazy_state: LazyState::NoNode,
18891890
type_shorthands: Default::default(),
18901891
predicate_shorthands: Default::default(),

src/librustc_metadata/schema.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::table::Table;
1+
use crate::table::PerDefTable;
22

33
use rustc::hir;
44
use rustc::hir::def::{self, CtorKind};
@@ -159,7 +159,7 @@ pub enum LazyState {
159159
// manually, instead of relying on the default, to get the correct variance.
160160
// Only needed when `T` itself contains a parameter (e.g. `'tcx`).
161161
macro_rules! Lazy {
162-
(Table<$T:ty>) => {Lazy<Table<$T>, usize>};
162+
(PerDefTable<$T:ty>) => {Lazy<PerDefTable<$T>, [usize; 2]>};
163163
([$T:ty]) => {Lazy<[$T], usize>};
164164
($T:ty) => {Lazy<$T, ()>};
165165
}
@@ -193,7 +193,7 @@ pub struct CrateRoot<'tcx> {
193193
pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
194194
pub interpret_alloc_index: Lazy<[u32]>,
195195

196-
pub entries_table: Lazy!(Table<Entry<'tcx>>),
196+
pub entries_table: Lazy!(PerDefTable<Entry<'tcx>>),
197197

198198
pub compiler_builtins: bool,
199199
pub needs_allocator: bool,

src/librustc_metadata/table.rs

Lines changed: 85 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -72,53 +72,42 @@ impl FixedSizeEncoding for u32 {
7272
/// (e.g. while visiting the definitions of a crate), and on-demand decoding
7373
/// of specific indices (e.g. queries for per-definition data).
7474
/// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
75+
// FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
76+
// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
77+
// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
78+
// and so would need two lengths in its metadata, which is not supported yet.
7579
pub struct Table<T: LazyMeta<Meta = ()>> {
76-
positions: [Vec<u8>; 2],
80+
bytes: Vec<u8>,
7781
_marker: PhantomData<T>,
7882
}
7983

8084
impl<T: LazyMeta<Meta = ()>> Table<T> {
81-
pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self {
85+
pub fn new(len: usize) -> Self {
8286
Table {
83-
positions: [vec![0; max_index_lo * 4],
84-
vec![0; max_index_hi * 4]],
87+
bytes: vec![0; len * 4],
8588
_marker: PhantomData,
8689
}
8790
}
8891

89-
pub fn record(&mut self, def_id: DefId, entry: Lazy<T>) {
90-
assert!(def_id.is_local());
91-
self.record_index(def_id.index, entry);
92-
}
93-
94-
pub fn record_index(&mut self, item: DefIndex, entry: Lazy<T>) {
92+
pub fn record(&mut self, i: usize, entry: Lazy<T>) {
9593
let position = entry.position.get() as u32;
9694
assert_eq!(position as usize, entry.position.get());
97-
let space_index = item.address_space().index();
98-
let array_index = item.as_array_index();
99-
100-
let positions = &mut self.positions[space_index];
101-
assert!(u32::read_from_bytes_at(positions, array_index) == 0,
102-
"recorded position for item {:?} twice, first at {:?} and now at {:?}",
103-
item,
104-
u32::read_from_bytes_at(positions, array_index),
95+
96+
assert!(u32::read_from_bytes_at(&self.bytes, i) == 0,
97+
"recorded position for index {:?} twice, first at {:?} and now at {:?}",
98+
i,
99+
u32::read_from_bytes_at(&self.bytes, i),
105100
position);
106101

107-
position.write_to_bytes_at(positions, array_index)
102+
position.write_to_bytes_at(&mut self.bytes, i)
108103
}
109104

110105
pub fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
111106
let pos = buf.position();
112-
113-
// First we write the length of the lower range ...
114-
buf.emit_raw_bytes(&(self.positions[0].len() as u32 / 4).to_le_bytes());
115-
// ... then the values in the lower range ...
116-
buf.emit_raw_bytes(&self.positions[0]);
117-
// ... then the values in the higher range.
118-
buf.emit_raw_bytes(&self.positions[1]);
107+
buf.emit_raw_bytes(&self.bytes);
119108
Lazy::from_position_and_meta(
120109
NonZeroUsize::new(pos as usize).unwrap(),
121-
(self.positions[0].len() + self.positions[1].len()) / 4 + 1,
110+
self.bytes.len(),
122111
)
123112
}
124113
}
@@ -127,31 +116,81 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
127116
type Meta = usize;
128117

129118
fn min_size(len: usize) -> usize {
130-
len * 4
119+
len
131120
}
132121
}
133122

134123
impl<T: Encodable> Lazy<Table<T>> {
135-
/// Given the metadata, extract out the offset of a particular
136-
/// DefIndex (if any).
124+
/// Given the metadata, extract out the offset of a particular index (if any).
137125
#[inline(never)]
138-
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> {
139-
let bytes = &bytes[self.position.get()..];
140-
debug!("Table::lookup: index={:?} len={:?}",
141-
def_index,
142-
self.meta);
143-
144-
let i = def_index.as_array_index() + match def_index.address_space() {
145-
DefIndexAddressSpace::Low => 0,
146-
DefIndexAddressSpace::High => {
147-
// This is a DefIndex in the higher range, so find out where
148-
// that starts:
149-
u32::read_from_bytes_at(bytes, 0) as usize
150-
}
151-
};
152-
153-
let position = u32::read_from_bytes_at(bytes, 1 + i);
126+
pub fn lookup(&self, bytes: &[u8], i: usize) -> Option<Lazy<T>> {
127+
debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
128+
129+
let bytes = &bytes[self.position.get()..][..self.meta];
130+
let position = u32::read_from_bytes_at(bytes, i);
154131
debug!("Table::lookup: position={:?}", position);
132+
155133
NonZeroUsize::new(position as usize).map(Lazy::from_position)
156134
}
157135
}
136+
137+
138+
/// Per-definition table, similar to `Table` but keyed on `DefIndex`.
139+
/// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in.
140+
pub struct PerDefTable<T: LazyMeta<Meta = ()>> {
141+
lo: Table<T>,
142+
hi: Table<T>,
143+
}
144+
145+
impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
146+
pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self {
147+
PerDefTable {
148+
lo: Table::new(max_index_lo),
149+
hi: Table::new(max_index_hi),
150+
}
151+
}
152+
153+
pub fn record(&mut self, def_id: DefId, entry: Lazy<T>) {
154+
assert!(def_id.is_local());
155+
let space_index = def_id.index.address_space().index();
156+
let array_index = def_id.index.as_array_index();
157+
[&mut self.lo, &mut self.hi][space_index].record(array_index, entry);
158+
}
159+
160+
pub fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
161+
let lo = self.lo.encode(buf);
162+
let hi = self.hi.encode(buf);
163+
assert_eq!(lo.position.get() + lo.meta, hi.position.get());
164+
165+
Lazy::from_position_and_meta(
166+
lo.position,
167+
[lo.meta, hi.meta],
168+
)
169+
}
170+
}
171+
172+
impl<T: LazyMeta<Meta = ()>> LazyMeta for PerDefTable<T> {
173+
type Meta = [<Table<T> as LazyMeta>::Meta; 2];
174+
175+
fn min_size([lo, hi]: Self::Meta) -> usize {
176+
Table::<T>::min_size(lo) + Table::<T>::min_size(hi)
177+
}
178+
}
179+
180+
impl<T: Encodable> Lazy<PerDefTable<T>> {
181+
fn table_for_space(&self, space: DefIndexAddressSpace) -> Lazy<Table<T>> {
182+
let space_index = space.index();
183+
let offset = space_index.checked_sub(1).map_or(0, |i| self.meta[i]);
184+
Lazy::from_position_and_meta(
185+
NonZeroUsize::new(self.position.get() + offset).unwrap(),
186+
self.meta[space_index]
187+
)
188+
}
189+
190+
/// Given the metadata, extract out the offset of a particular DefIndex (if any).
191+
#[inline(never)]
192+
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> {
193+
self.table_for_space(def_index.address_space())
194+
.lookup(bytes, def_index.as_array_index())
195+
}
196+
}

0 commit comments

Comments
 (0)