Skip to content

Commit cef4950

Browse files
committed
rustc_metadata: generalize Table<T> to hold T, not Lazy<T>, elements.
1 parent 677f0df commit cef4950

File tree

4 files changed

+78
-48
lines changed

4 files changed

+78
-48
lines changed

src/librustc_metadata/decoder.rs

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

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

77
use rustc_index::vec::IndexVec;
88
use rustc_data_structures::sync::{Lrc, ReadGuard};
@@ -256,7 +256,7 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a,
256256
}
257257

258258
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<PerDefTable<T>>> for DecodeContext<'a, 'tcx>
259-
where T: LazyMeta<Meta = ()>,
259+
where Option<T>: FixedSizeEncoding,
260260
{
261261
fn specialized_decode(&mut self) -> Result<Lazy<PerDefTable<T>>, Self::Error> {
262262
let len = self.read_usize()?;
@@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata {
481481
}
482482

483483
fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
484-
self.root.per_def.entry.lookup(self.blob.raw_bytes(), item_id)
484+
self.root.per_def.entry.get(self.blob.raw_bytes(), item_id)
485485
}
486486

487487
fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {

src/librustc_metadata/encoder.rs

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

44
use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
55
EncodedMetadata, ForeignModule};
@@ -61,7 +61,7 @@ struct EncodeContext<'tcx> {
6161
}
6262

6363
struct PerDefTables<'tcx> {
64-
entry: PerDefTable<Entry<'tcx>>,
64+
entry: PerDefTable<Lazy<Entry<'tcx>>>,
6565
}
6666

6767
macro_rules! encoder_methods {
@@ -119,7 +119,7 @@ impl<'tcx, T: Encodable> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
119119
}
120120

121121
impl<'tcx, T> SpecializedEncoder<Lazy<PerDefTable<T>>> for EncodeContext<'tcx>
122-
where T: LazyMeta<Meta = ()>,
122+
where Option<T>: FixedSizeEncoding,
123123
{
124124
fn specialized_encode(&mut self, lazy: &Lazy<PerDefTable<T>>) -> Result<(), Self::Error> {
125125
self.emit_usize(lazy.meta)?;
@@ -280,14 +280,14 @@ impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I
280280
}
281281
}
282282

283-
// Shorthand for `$self.$tables.$table.record($key, $self.lazy($value))`, which would
283+
// Shorthand for `$self.$tables.$table.set($key, $self.lazy($value))`, which would
284284
// normally need extra variables to avoid errors about multiple mutable borrows.
285285
macro_rules! record {
286286
($self:ident.$tables:ident.$table:ident[$key:expr] <- $value:expr) => {{
287287
{
288288
let value = $value;
289289
let lazy = $self.lazy(value);
290-
$self.$tables.$table.record($key, lazy);
290+
$self.$tables.$table.set($key, lazy);
291291
}
292292
}}
293293
}

src/librustc_metadata/schema.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ crate struct TraitImpls {
229229

230230
#[derive(RustcEncodable, RustcDecodable)]
231231
crate struct LazyPerDefTables<'tcx> {
232-
pub entry: Lazy!(PerDefTable<Entry<'tcx>>),
232+
pub entry: Lazy!(PerDefTable<Lazy<Entry<'tcx>>>),
233233
}
234234

235235
#[derive(RustcEncodable, RustcDecodable)]

src/librustc_metadata/table.rs

Lines changed: 69 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use std::num::NonZeroUsize;
88
use log::debug;
99

1010
/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
11-
trait FixedSizeEncoding {
11+
/// Used mainly for Lazy positions and lengths.
12+
/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
13+
/// but this has no impact on safety.
14+
crate trait FixedSizeEncoding: Default {
1215
const BYTE_LEN: usize;
1316

1417
// FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
@@ -38,7 +41,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults {
3841
b.len() / BYTE_LEN,
3942
)
4043
};
41-
Self::from_bytes(&b[i])
44+
FixedSizeEncoding::from_bytes(&b[i])
4245
}
4346
fn write_to_bytes_at(self, b: &mut [u8], i: usize) {
4447
const BYTE_LEN: usize = $byte_len;
@@ -69,37 +72,69 @@ impl FixedSizeEncoding for u32 {
6972
}
7073
}
7174

72-
/// Random-access position table, allowing encoding in an arbitrary order
73-
/// (e.g. while visiting the definitions of a crate), and on-demand decoding
74-
/// of specific indices (e.g. queries for per-definition data).
75-
/// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
76-
// FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
75+
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
76+
// generic `Lazy<T>` impl, but in the general case we might not need / want to
77+
// fit every `usize` in `u32`.
78+
impl<T: Encodable> FixedSizeEncoding for Option<Lazy<T>> {
79+
fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN);
80+
81+
fn from_bytes(b: &[u8]) -> Self {
82+
Some(Lazy::from_position(NonZeroUsize::new(u32::from_bytes(b) as usize)?))
83+
}
84+
85+
fn write_to_bytes(self, b: &mut [u8]) {
86+
let position = self.map_or(0, |lazy| lazy.position.get());
87+
let position: u32 = position.try_into().unwrap();
88+
89+
position.write_to_bytes(b)
90+
}
91+
}
92+
93+
impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
94+
fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2);
95+
96+
fn from_bytes(b: &[u8]) -> Self {
97+
Some(Lazy::from_position_and_meta(
98+
<Option<Lazy<T>>>::from_bytes(b)?.position,
99+
u32::from_bytes(&b[u32::BYTE_LEN..]) as usize,
100+
))
101+
}
102+
103+
fn write_to_bytes(self, b: &mut [u8]) {
104+
self.map(|lazy| Lazy::<T>::from_position(lazy.position))
105+
.write_to_bytes(b);
106+
107+
let len = self.map_or(0, |lazy| lazy.meta);
108+
let len: u32 = len.try_into().unwrap();
109+
110+
len.write_to_bytes(&mut b[u32::BYTE_LEN..]);
111+
}
112+
}
113+
114+
/// Random-access table, similar to `Vec<Option<T>>`, but without requiring
115+
/// encoding or decoding all the values eagerly and in-order.
116+
// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used
77117
// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
78118
// Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
79119
// and so would need two lengths in its metadata, which is not supported yet.
80-
crate struct Table<T: LazyMeta<Meta = ()>> {
120+
crate struct Table<T> where Option<T>: FixedSizeEncoding {
121+
// FIXME(eddyb) store `[u8; <Option<T>>::BYTE_LEN]` instead of `u8` in `Vec`,
122+
// once that starts being allowed by the compiler (i.e. lazy normalization).
81123
bytes: Vec<u8>,
82124
_marker: PhantomData<T>,
83125
}
84126

85-
impl<T: LazyMeta<Meta = ()>> Table<T> {
127+
impl<T> Table<T> where Option<T>: FixedSizeEncoding {
86128
crate fn new(len: usize) -> Self {
87129
Table {
88-
bytes: vec![0; len * 4],
130+
// FIXME(eddyb) only allocate and encode as many entries as needed.
131+
bytes: vec![0; len * <Option<T>>::BYTE_LEN],
89132
_marker: PhantomData,
90133
}
91134
}
92135

93-
crate fn record(&mut self, i: usize, entry: Lazy<T>) {
94-
let position: u32 = entry.position.get().try_into().unwrap();
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),
100-
position);
101-
102-
position.write_to_bytes_at(&mut self.bytes, i)
136+
crate fn set(&mut self, i: usize, value: T) {
137+
Some(value).write_to_bytes_at(&mut self.bytes, i);
103138
}
104139

105140
crate fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
@@ -112,42 +147,37 @@ impl<T: LazyMeta<Meta = ()>> Table<T> {
112147
}
113148
}
114149

115-
impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
150+
impl<T> LazyMeta for Table<T> where Option<T>: FixedSizeEncoding {
116151
type Meta = usize;
117152

118153
fn min_size(len: usize) -> usize {
119154
len
120155
}
121156
}
122157

123-
impl<T: Encodable> Lazy<Table<T>> {
124-
/// Given the metadata, extract out the offset of a particular index (if any).
158+
impl<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding {
159+
/// Given the metadata, extract out the value at a particular index (if any).
125160
#[inline(never)]
126-
crate fn lookup(&self, bytes: &[u8], i: usize) -> Option<Lazy<T>> {
161+
crate fn get(&self, bytes: &[u8], i: usize) -> Option<T> {
127162
debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
128163

129-
let bytes = &bytes[self.position.get()..][..self.meta];
130-
let position = u32::read_from_bytes_at(bytes, i);
131-
debug!("Table::lookup: position={:?}", position);
132-
133-
NonZeroUsize::new(position as usize).map(Lazy::from_position)
164+
<Option<T>>::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i)
134165
}
135166
}
136167

137-
138168
/// Per-definition table, similar to `Table` but keyed on `DefIndex`.
139169
// FIXME(eddyb) replace by making `Table` behave like `IndexVec`,
140170
// and by using `newtype_index!` to define `DefIndex`.
141-
crate struct PerDefTable<T: LazyMeta<Meta = ()>>(Table<T>);
171+
crate struct PerDefTable<T>(Table<T>) where Option<T>: FixedSizeEncoding;
142172

143-
impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
173+
impl<T> PerDefTable<T> where Option<T>: FixedSizeEncoding {
144174
crate fn new(def_index_count: usize) -> Self {
145175
PerDefTable(Table::new(def_index_count))
146176
}
147177

148-
crate fn record(&mut self, def_id: DefId, entry: Lazy<T>) {
178+
crate fn set(&mut self, def_id: DefId, value: T) {
149179
assert!(def_id.is_local());
150-
self.0.record(def_id.index.index(), entry);
180+
self.0.set(def_id.index.index(), value);
151181
}
152182

153183
crate fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
@@ -156,22 +186,22 @@ impl<T: LazyMeta<Meta = ()>> PerDefTable<T> {
156186
}
157187
}
158188

159-
impl<T: LazyMeta<Meta = ()>> LazyMeta for PerDefTable<T> {
189+
impl<T> LazyMeta for PerDefTable<T> where Option<T>: FixedSizeEncoding {
160190
type Meta = <Table<T> as LazyMeta>::Meta;
161191

162192
fn min_size(meta: Self::Meta) -> usize {
163193
Table::<T>::min_size(meta)
164194
}
165195
}
166196

167-
impl<T: Encodable> Lazy<PerDefTable<T>> {
197+
impl<T> Lazy<PerDefTable<T>> where Option<T>: FixedSizeEncoding {
168198
fn as_table(&self) -> Lazy<Table<T>> {
169199
Lazy::from_position_and_meta(self.position, self.meta)
170200
}
171201

172-
/// Given the metadata, extract out the offset of a particular DefIndex (if any).
202+
/// Given the metadata, extract out the value at a particular DefIndex (if any).
173203
#[inline(never)]
174-
crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<T>> {
175-
self.as_table().lookup(bytes, def_index.index())
204+
crate fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option<T> {
205+
self.as_table().get(bytes, def_index.index())
176206
}
177207
}

0 commit comments

Comments
 (0)