Skip to content

Commit 7d1271f

Browse files
committed
rustc_metadata: split tables into an usize-keyed Table and a DefIndex-keyed PerDefTable.
1 parent 2a119f3 commit 7d1271f

File tree

4 files changed

+104
-59
lines changed

4 files changed

+104
-59
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: 86 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,43 @@ use log::debug;
1010
/// (e.g. while visiting the definitions of a crate), and on-demand decoding
1111
/// of specific indices (e.g. queries for per-definition data).
1212
/// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
13+
// FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
14+
// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
15+
// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
16+
// and so would need two lengths in its metadata, which is not supported yet.
1317
pub struct Table<T: LazyMeta<Meta = ()>> {
14-
positions: [Vec<u8>; 2],
18+
bytes: Vec<u8>,
1519
_marker: PhantomData<T>,
1620
}
1721

1822
impl<T: LazyMeta<Meta = ()>> Table<T> {
19-
pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self {
23+
pub fn new(len: usize) -> Self {
2024
Table {
21-
positions: [vec![0; max_index_lo * 4],
22-
vec![0; max_index_hi * 4]],
25+
bytes: vec![0; len * 4],
2326
_marker: PhantomData,
2427
}
2528
}
2629

27-
pub fn record(&mut self, def_id: DefId, entry: Lazy<T>) {
28-
assert!(def_id.is_local());
29-
self.record_index(def_id.index, entry);
30-
}
31-
32-
pub fn record_index(&mut self, item: DefIndex, entry: Lazy<T>) {
30+
pub fn record(&mut self, i: usize, entry: Lazy<T>) {
3331
let position = entry.position.get() as u32;
3432
assert_eq!(position as usize, entry.position.get());
35-
let space_index = item.address_space().index();
36-
let array_index = item.as_array_index();
37-
38-
let destination = &mut self.positions[space_index][array_index * 4..];
39-
assert!(read_le_u32(destination) == 0,
40-
"recorded position for item {:?} twice, first at {:?} and now at {:?}",
41-
item,
42-
read_le_u32(destination),
33+
34+
let bytes = &mut self.bytes[i * 4..];
35+
assert!(read_le_u32(bytes) == 0,
36+
"recorded position for index {:?} twice, first at {:?} and now at {:?}",
37+
i,
38+
read_le_u32(bytes),
4339
position);
4440

45-
write_le_u32(destination, position);
41+
write_le_u32(bytes, position);
4642
}
4743

4844
pub fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
4945
let pos = buf.position();
50-
51-
// First we write the length of the lower range ...
52-
buf.emit_raw_bytes(&(self.positions[0].len() as u32 / 4).to_le_bytes());
53-
// ... then the values in the lower range ...
54-
buf.emit_raw_bytes(&self.positions[0]);
55-
// ... then the values in the higher range.
56-
buf.emit_raw_bytes(&self.positions[1]);
46+
buf.emit_raw_bytes(&self.bytes);
5747
Lazy::from_position_and_meta(
5848
NonZeroUsize::new(pos as usize).unwrap(),
59-
(self.positions[0].len() + self.positions[1].len()) / 4 + 1,
49+
self.bytes.len(),
6050
)
6151
}
6252
}
@@ -65,30 +55,20 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
6555
type Meta = usize;
6656

6757
fn min_size(len: usize) -> usize {
68-
len * 4
58+
len
6959
}
7060
}
7161

7262
impl<T: Encodable> Lazy<Table<T>> {
73-
/// Given the metadata, extract out the offset of a particular
74-
/// DefIndex (if any).
63+
/// Given the metadata, extract out the offset of a particular index (if any).
7564
#[inline(never)]
76-
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> {
77-
debug!("Table::lookup: index={:?} len={:?}",
78-
def_index,
79-
self.meta);
80-
81-
let i = def_index.as_array_index() + match def_index.address_space() {
82-
DefIndexAddressSpace::Low => 0,
83-
DefIndexAddressSpace::High => {
84-
// This is a DefIndex in the higher range, so find out where
85-
// that starts:
86-
read_le_u32(&bytes[self.position.get()..]) as usize
87-
}
88-
};
89-
90-
let position = read_le_u32(&bytes[self.position.get() + (1 + i) * 4..]);
65+
pub fn lookup(&self, bytes: &[u8], i: usize) -> Option<Lazy<T>> {
66+
debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
67+
68+
let bytes = &bytes[self.position.get()..][..self.meta];
69+
let position = read_le_u32(&bytes[i * 4..]);
9170
debug!("Table::lookup: position={:?}", position);
71+
9272
NonZeroUsize::new(position as usize).map(Lazy::from_position)
9373
}
9474
}
@@ -102,3 +82,64 @@ fn read_le_u32(b: &[u8]) -> u32 {
10282
fn write_le_u32(b: &mut [u8], x: u32) {
10383
b[..4].copy_from_slice(&x.to_le_bytes());
10484
}
85+
86+
/// Per-definition table, similar to `Table` but keyed on `DefIndex`.
87+
/// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in.
88+
pub struct PerDefTable<T: LazyMeta<Meta = ()>> {
89+
lo: Table<T>,
90+
hi: Table<T>,
91+
}
92+
93+
impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
94+
pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self {
95+
PerDefTable {
96+
lo: Table::new(max_index_lo),
97+
hi: Table::new(max_index_hi),
98+
}
99+
}
100+
101+
pub fn record(&mut self, def_id: DefId, entry: Lazy<T>) {
102+
assert!(def_id.is_local());
103+
let space_index = def_id.index.address_space().index();
104+
let array_index = def_id.index.as_array_index();
105+
[&mut self.lo, &mut self.hi][space_index].record(array_index, entry);
106+
}
107+
108+
pub fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
109+
let lo = self.lo.encode(buf);
110+
let hi = self.hi.encode(buf);
111+
assert_eq!(lo.position.get() + lo.meta, hi.position.get());
112+
113+
Lazy::from_position_and_meta(
114+
lo.position,
115+
[lo.meta, hi.meta],
116+
)
117+
}
118+
}
119+
120+
impl<T: LazyMeta<Meta = ()>> LazyMeta for PerDefTable<T> {
121+
type Meta = [<Table<T> as LazyMeta>::Meta; 2];
122+
123+
fn min_size([lo, hi]: Self::Meta) -> usize {
124+
Table::<T>::min_size(lo) + Table::<T>::min_size(hi)
125+
}
126+
}
127+
128+
impl<T: Encodable> Lazy<PerDefTable<T>> {
129+
fn table_for_space(&self, space: DefIndexAddressSpace) -> Lazy<Table<T>> {
130+
let space_index = space.index();
131+
let offset = space_index.checked_sub(1).map_or(0, |i| self.meta[i]);
132+
Lazy::from_position_and_meta(
133+
NonZeroUsize::new(self.position.get() + offset).unwrap(),
134+
self.meta[space_index]
135+
)
136+
}
137+
138+
/// Given the metadata, extract out the offset of a particular DefIndex (if any).
139+
#[inline(never)]
140+
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> {
141+
self.table_for_space(def_index.address_space())
142+
.lookup(bytes, def_index.as_array_index())
143+
}
144+
}
145+

0 commit comments

Comments
 (0)