Skip to content

Commit

Permalink
Document in the code how this scheme works
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Aug 30, 2023
1 parent e0103a7 commit 225b3c0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ impl<T> LazyArray<T> {
/// eagerly and in-order.
struct LazyTable<I, T> {
position: NonZeroUsize,
/// The encoded size of the elements of a table is selected at runtime to drop
/// trailing zeroes. This is the number of bytes used for each table element.
width: usize,
/// How many elements are in the table.
len: usize,
_marker: PhantomData<fn(I) -> T>,
}
Expand Down
36 changes: 22 additions & 14 deletions compiler/rustc_metadata/src/rmeta/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ impl<T> LazyArray<T> {
let position = (self.position.get() as u64).to_le_bytes();
let len = (self.num_elems as u64).to_le_bytes();

// Element width is selected at runtime on a per-table basis by omitting trailing
// zero bytes in table elements. This works very naturally when table elements are
// simple numbers but `LazyArray` is a pair of integers. If naively encoded, the second
// element would shield the trailing zeroes in the first. Interleaving the bytes
// of the position and length exposes trailing zeroes in both to the optimization.
// We encode length second because we generally expect it to be smaller.
for i in 0..8 {
b[2 * i] = position[i];
b[2 * i + 1] = len[i];
Expand All @@ -359,18 +365,26 @@ impl<T> LazyArray<T> {
}
}

// Decoding helper for the encoding scheme used by `LazyArray`.
// Interleaving the bytes of the two integers exposes trailing bytes in the first integer
// to the varint scheme that we use for tables.
#[inline]
fn decode_interleaved(encoded: &[u8; 16]) -> ([u8; 8], [u8; 8]) {
let mut first = [0u8; 8];
let mut second = [0u8; 8];
for i in 0..8 {
first[i] = encoded[2 * i];
second[i] = encoded[2 * i + 1];
}
(first, second)
}

impl<T> FixedSizeEncoding for LazyArray<T> {
type ByteArray = [u8; 16];

#[inline]
fn from_bytes(b: &[u8; 16]) -> Self {
let mut position = [0u8; 8];
let mut meta = [0u8; 8];

for i in 0..8 {
position[i] = b[2 * i];
meta[i] = b[2 * i + 1];
}
let (position, meta) = decode_interleaved(b);

if meta == [0; 8] {
return Default::default();
Expand All @@ -390,13 +404,7 @@ impl<T> FixedSizeEncoding for Option<LazyArray<T>> {

#[inline]
fn from_bytes(b: &[u8; 16]) -> Self {
let mut position = [0u8; 8];
let mut meta = [0u8; 8];

for i in 0..8 {
position[i] = b[2 * i];
meta[i] = b[2 * i + 1];
}
let (position, meta) = decode_interleaved(b);

LazyArray::from_bytes_impl(&position, &meta)
}
Expand Down

0 comments on commit 225b3c0

Please sign in to comment.