Skip to content

Commit 2ae197d

Browse files
committed
Adapt table sizes to the contents
1 parent a161ab0 commit 2ae197d

File tree

4 files changed

+102
-45
lines changed

4 files changed

+102
-45
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
360360
self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len))
361361
}
362362

363-
fn read_lazy_table<I, T>(&mut self, len: usize) -> LazyTable<I, T> {
364-
self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, len))
363+
fn read_lazy_table<I, T>(&mut self, width: usize, len: usize) -> LazyTable<I, T> {
364+
self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len))
365365
}
366366

367367
#[inline]
@@ -665,8 +665,9 @@ impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
665665

666666
impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T> {
667667
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
668+
let width = decoder.read_usize();
668669
let len = decoder.read_usize();
669-
decoder.read_lazy_table(len)
670+
decoder.read_lazy_table(width, len)
670671
}
671672
}
672673

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
129129

130130
impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
131131
fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
132-
e.emit_usize(self.encoded_size);
132+
e.emit_usize(self.width);
133+
e.emit_usize(self.len);
133134
e.emit_lazy_distance(self.position);
134135
}
135136
}

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ impl<T> LazyArray<T> {
136136
/// eagerly and in-order.
137137
struct LazyTable<I, T> {
138138
position: NonZeroUsize,
139-
encoded_size: usize,
139+
width: usize,
140+
len: usize,
140141
_marker: PhantomData<fn(I) -> T>,
141142
}
142143

@@ -147,9 +148,10 @@ impl<I: 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for LazyTable<I,
147148
impl<I, T> LazyTable<I, T> {
148149
fn from_position_and_encoded_size(
149150
position: NonZeroUsize,
150-
encoded_size: usize,
151+
width: usize,
152+
len: usize,
151153
) -> LazyTable<I, T> {
152-
LazyTable { position, encoded_size, _marker: PhantomData }
154+
LazyTable { position, width, len, _marker: PhantomData }
153155
}
154156
}
155157

compiler/rustc_metadata/src/rmeta/table.rs

Lines changed: 91 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ impl IsDefault for u32 {
3838
}
3939
}
4040

41+
impl IsDefault for u64 {
42+
fn is_default(&self) -> bool {
43+
*self == 0
44+
}
45+
}
46+
4147
impl<T> IsDefault for LazyArray<T> {
4248
fn is_default(&self) -> bool {
4349
self.num_elems == 0
@@ -89,6 +95,20 @@ impl FixedSizeEncoding for u32 {
8995
}
9096
}
9197

98+
impl FixedSizeEncoding for u64 {
99+
type ByteArray = [u8; 8];
100+
101+
#[inline]
102+
fn from_bytes(b: &[u8; 8]) -> Self {
103+
Self::from_le_bytes(*b)
104+
}
105+
106+
#[inline]
107+
fn write_to_bytes(self, b: &mut [u8; 8]) {
108+
*b = self.to_le_bytes();
109+
}
110+
}
111+
92112
macro_rules! fixed_size_enum {
93113
($ty:ty { $(($($pat:tt)*))* }) => {
94114
impl FixedSizeEncoding for Option<$ty> {
@@ -299,21 +319,21 @@ impl FixedSizeEncoding for UnusedGenericParams {
299319
// generic `LazyValue<T>` impl, but in the general case we might not need / want
300320
// to fit every `usize` in `u32`.
301321
impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
302-
type ByteArray = [u8; 4];
322+
type ByteArray = [u8; 8];
303323

304324
#[inline]
305-
fn from_bytes(b: &[u8; 4]) -> Self {
306-
let position = NonZeroUsize::new(u32::from_bytes(b) as usize)?;
325+
fn from_bytes(b: &[u8; 8]) -> Self {
326+
let position = NonZeroUsize::new(u64::from_bytes(b) as usize)?;
307327
Some(LazyValue::from_position(position))
308328
}
309329

310330
#[inline]
311-
fn write_to_bytes(self, b: &mut [u8; 4]) {
331+
fn write_to_bytes(self, b: &mut [u8; 8]) {
312332
match self {
313333
None => unreachable!(),
314334
Some(lazy) => {
315335
let position = lazy.position.get();
316-
let position: u32 = position.try_into().unwrap();
336+
let position: u64 = position.try_into().unwrap();
317337
position.write_to_bytes(b)
318338
}
319339
}
@@ -322,55 +342,67 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
322342

323343
impl<T> LazyArray<T> {
324344
#[inline]
325-
fn write_to_bytes_impl(self, b: &mut [u8; 8]) {
326-
let ([position_bytes, meta_bytes], []) = b.as_chunks_mut::<4>() else { panic!() };
345+
fn write_to_bytes_impl(self, b: &mut [u8; 16]) {
346+
let position = (self.position.get() as u64).to_le_bytes();
347+
let len = (self.num_elems as u64).to_le_bytes();
327348

328-
let position = self.position.get();
329-
let position: u32 = position.try_into().unwrap();
330-
position.write_to_bytes(position_bytes);
331-
332-
let len = self.num_elems;
333-
let len: u32 = len.try_into().unwrap();
334-
len.write_to_bytes(meta_bytes);
349+
for i in 0..8 {
350+
b[2 * i] = position[i];
351+
b[2 * i + 1] = len[i];
352+
}
335353
}
336354

337-
fn from_bytes_impl(position_bytes: &[u8; 4], meta_bytes: &[u8; 4]) -> Option<LazyArray<T>> {
338-
let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
339-
let len = u32::from_bytes(meta_bytes) as usize;
355+
fn from_bytes_impl(position: &[u8; 8], meta: &[u8; 8]) -> Option<LazyArray<T>> {
356+
let position = NonZeroUsize::new(u64::from_bytes(&position) as usize)?;
357+
let len = u64::from_bytes(&meta) as usize;
340358
Some(LazyArray::from_position_and_num_elems(position, len))
341359
}
342360
}
343361

344362
impl<T> FixedSizeEncoding for LazyArray<T> {
345-
type ByteArray = [u8; 8];
363+
type ByteArray = [u8; 16];
346364

347365
#[inline]
348-
fn from_bytes(b: &[u8; 8]) -> Self {
349-
let ([position_bytes, meta_bytes], []) = b.as_chunks::<4>() else { panic!() };
350-
if *meta_bytes == [0; 4] {
366+
fn from_bytes(b: &[u8; 16]) -> Self {
367+
let mut position = [0u8; 8];
368+
let mut meta = [0u8; 8];
369+
370+
for i in 0..8 {
371+
position[i] = b[2 * i];
372+
meta[i] = b[2 * i + 1];
373+
}
374+
375+
if meta == [0; 8] {
351376
return Default::default();
352377
}
353-
LazyArray::from_bytes_impl(position_bytes, meta_bytes).unwrap()
378+
LazyArray::from_bytes_impl(&position, &meta).unwrap()
354379
}
355380

356381
#[inline]
357-
fn write_to_bytes(self, b: &mut [u8; 8]) {
382+
fn write_to_bytes(self, b: &mut [u8; 16]) {
358383
assert!(!self.is_default());
359384
self.write_to_bytes_impl(b)
360385
}
361386
}
362387

363388
impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
364-
type ByteArray = [u8; 8];
389+
type ByteArray = [u8; 16];
365390

366391
#[inline]
367-
fn from_bytes(b: &[u8; 8]) -> Self {
368-
let ([position_bytes, meta_bytes], []) = b.as_chunks::<4>() else { panic!() };
369-
LazyArray::from_bytes_impl(position_bytes, meta_bytes)
392+
fn from_bytes(b: &[u8; 16]) -> Self {
393+
let mut position = [0u8; 8];
394+
let mut meta = [0u8; 8];
395+
396+
for i in 0..8 {
397+
position[i] = b[2 * i];
398+
meta[i] = b[2 * i + 1];
399+
}
400+
401+
LazyArray::from_bytes_impl(&position, &meta)
370402
}
371403

372404
#[inline]
373-
fn write_to_bytes(self, b: &mut [u8; 8]) {
405+
fn write_to_bytes(self, b: &mut [u8; 16]) {
374406
match self {
375407
None => unreachable!(),
376408
Some(lazy) => lazy.write_to_bytes_impl(b),
@@ -380,13 +412,14 @@ impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
380412

381413
/// Helper for constructing a table's serialization (also see `Table`).
382414
pub(super) struct TableBuilder<I: Idx, T: FixedSizeEncoding> {
415+
width: usize,
383416
blocks: IndexVec<I, T::ByteArray>,
384417
_marker: PhantomData<T>,
385418
}
386419

387420
impl<I: Idx, T: FixedSizeEncoding> Default for TableBuilder<I, T> {
388421
fn default() -> Self {
389-
TableBuilder { blocks: Default::default(), _marker: PhantomData }
422+
TableBuilder { width: 0, blocks: Default::default(), _marker: PhantomData }
390423
}
391424
}
392425

@@ -414,22 +447,33 @@ impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBui
414447
// > store bit-masks of which item in each bucket is actually serialized).
415448
let block = self.blocks.ensure_contains_elem(i, || [0; N]);
416449
value.write_to_bytes(block);
450+
if self.width != N {
451+
let width = N - trailing_zeros(block);
452+
self.width = self.width.max(width);
453+
}
417454
}
418455
}
419456

420457
pub(crate) fn encode(&self, buf: &mut FileEncoder) -> LazyTable<I, T> {
421458
let pos = buf.position();
459+
460+
let width = self.width;
422461
for block in &self.blocks {
423-
buf.emit_raw_bytes(block);
462+
buf.emit_raw_bytes(&block[..width]);
424463
}
425-
let num_bytes = self.blocks.len() * N;
464+
426465
LazyTable::from_position_and_encoded_size(
427466
NonZeroUsize::new(pos as usize).unwrap(),
428-
num_bytes,
467+
width,
468+
self.blocks.len(),
429469
)
430470
}
431471
}
432472

473+
fn trailing_zeros(x: &[u8]) -> usize {
474+
x.iter().rev().take_while(|b| **b == 0).count()
475+
}
476+
433477
impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]> + ParameterizedOverTcx>
434478
LazyTable<I, T>
435479
where
@@ -438,16 +482,25 @@ where
438482
/// Given the metadata, extract out the value at a particular index (if any).
439483
#[inline(never)]
440484
pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(&self, metadata: M, i: I) -> T::Value<'tcx> {
441-
trace!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size);
485+
trace!("LazyTable::lookup: index={:?} len={:?}", i, self.len);
486+
487+
// Access past the end of the table returns a Default
488+
if i.index() >= self.len {
489+
return Default::default();
490+
}
491+
492+
let width = self.width;
493+
let start = self.position.get() + (width * i.index());
494+
let end = start + width;
495+
let bytes = &metadata.blob()[start..end];
442496

443-
let start = self.position.get();
444-
let bytes = &metadata.blob()[start..start + self.encoded_size];
445-
let (bytes, []) = bytes.as_chunks::<N>() else { panic!() };
446-
bytes.get(i.index()).map_or_else(Default::default, FixedSizeEncoding::from_bytes)
497+
let mut fixed = [0u8; N];
498+
fixed[..width].copy_from_slice(bytes);
499+
FixedSizeEncoding::from_bytes(&fixed)
447500
}
448501

449502
/// Size of the table in entries, including possible gaps.
450503
pub(super) fn size(&self) -> usize {
451-
self.encoded_size / N
504+
self.len
452505
}
453506
}

0 commit comments

Comments
 (0)