Skip to content

Commit 71696e5

Browse files
committed
Auto merge of #119226 - Mark-Simulacrum:format-efficiency, r=TaKO8Ki
Improve coding efficiency for RawDefId This copies the scheme already used for LazyArray, cutting a couple hundred kilobytes from libcore's metadata.
2 parents 13ea97c + 2fec2d6 commit 71696e5

File tree

1 file changed

+36
-23
lines changed
  • compiler/rustc_metadata/src/rmeta

1 file changed

+36
-23
lines changed

compiler/rustc_metadata/src/rmeta/table.rs

+36-23
Original file line numberDiff line numberDiff line change
@@ -232,24 +232,30 @@ impl FixedSizeEncoding for Option<RawDefId> {
232232
type ByteArray = [u8; 8];
233233

234234
#[inline]
235-
fn from_bytes(b: &[u8; 8]) -> Self {
236-
let krate = u32::from_le_bytes(b[0..4].try_into().unwrap());
235+
fn from_bytes(encoded: &[u8; 8]) -> Self {
236+
let (index, krate) = decode_interleaved(encoded);
237+
let krate = u32::from_le_bytes(krate);
237238
if krate == 0 {
238239
return None;
239240
}
240-
let index = u32::from_le_bytes(b[4..8].try_into().unwrap());
241+
let index = u32::from_le_bytes(index);
242+
241243
Some(RawDefId { krate: krate - 1, index })
242244
}
243245

244246
#[inline]
245-
fn write_to_bytes(self, b: &mut [u8; 8]) {
247+
fn write_to_bytes(self, dest: &mut [u8; 8]) {
246248
match self {
247249
None => unreachable!(),
248250
Some(RawDefId { krate, index }) => {
249-
// CrateNum is less than `CrateNum::MAX_AS_U32`.
250251
debug_assert!(krate < u32::MAX);
251-
b[0..4].copy_from_slice(&(1 + krate).to_le_bytes());
252-
b[4..8].copy_from_slice(&index.to_le_bytes());
252+
// CrateNum is less than `CrateNum::MAX_AS_U32`.
253+
let krate = (krate + 1).to_le_bytes();
254+
let index = index.to_le_bytes();
255+
256+
// CrateNum is usually much smaller than the index within the crate, so put it in
257+
// the second slot.
258+
encode_interleaved(index, krate, dest);
253259
}
254260
}
255261
}
@@ -351,20 +357,11 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
351357

352358
impl<T> LazyArray<T> {
353359
#[inline]
354-
fn write_to_bytes_impl(self, b: &mut [u8; 16]) {
360+
fn write_to_bytes_impl(self, dest: &mut [u8; 16]) {
355361
let position = (self.position.get() as u64).to_le_bytes();
356362
let len = (self.num_elems as u64).to_le_bytes();
357363

358-
// Element width is selected at runtime on a per-table basis by omitting trailing
359-
// zero bytes in table elements. This works very naturally when table elements are
360-
// simple numbers but `LazyArray` is a pair of integers. If naively encoded, the second
361-
// element would shield the trailing zeroes in the first. Interleaving the bytes
362-
// of the position and length exposes trailing zeroes in both to the optimization.
363-
// We encode length second because we generally expect it to be smaller.
364-
for i in 0..8 {
365-
b[2 * i] = position[i];
366-
b[2 * i + 1] = len[i];
367-
}
364+
encode_interleaved(position, len, dest)
368365
}
369366

370367
fn from_bytes_impl(position: &[u8; 8], meta: &[u8; 8]) -> Option<LazyArray<T>> {
@@ -374,20 +371,36 @@ impl<T> LazyArray<T> {
374371
}
375372
}
376373

377-
// Decoding helper for the encoding scheme used by `LazyArray`.
378374
// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
379375
// to the varint scheme that we use for tables.
380376
#[inline]
381-
fn decode_interleaved(encoded: &[u8; 16]) -> ([u8; 8], [u8; 8]) {
382-
let mut first = [0u8; 8];
383-
let mut second = [0u8; 8];
384-
for i in 0..8 {
377+
fn decode_interleaved<const N: usize, const M: usize>(encoded: &[u8; N]) -> ([u8; M], [u8; M]) {
378+
assert_eq!(M * 2, N);
379+
let mut first = [0u8; M];
380+
let mut second = [0u8; M];
381+
for i in 0..M {
385382
first[i] = encoded[2 * i];
386383
second[i] = encoded[2 * i + 1];
387384
}
388385
(first, second)
389386
}
390387

388+
// Element width is selected at runtime on a per-table basis by omitting trailing
389+
// zero bytes in table elements. This works very naturally when table elements are
390+
// simple numbers but sometimes we have a pair of integers. If naively encoded, the second element
391+
// would shield the trailing zeroes in the first. Interleaving the bytes exposes trailing zeroes in
392+
// both to the optimization.
393+
//
394+
// Prefer passing a and b such that `b` is usually smaller.
395+
#[inline]
396+
fn encode_interleaved<const N: usize, const M: usize>(a: [u8; M], b: [u8; M], dest: &mut [u8; N]) {
397+
assert_eq!(M * 2, N);
398+
for i in 0..M {
399+
dest[2 * i] = a[i];
400+
dest[2 * i + 1] = b[i];
401+
}
402+
}
403+
391404
impl<T> FixedSizeEncoding for LazyArray<T> {
392405
type ByteArray = [u8; 16];
393406

0 commit comments

Comments
 (0)