Skip to content

Commit 5b3116c

Browse files
Specialize DefPathHash table to skip crate IDs
The current implementation is ad-hoc and likely should be replaced with a non-table based approach (i.e., fully pulling out DefPathHash from the rmeta table infrastructure, of which we use ~none now), but this was an easy way to get an initial PR out. The main pending question is whether the assumption made here that there is exactly one shared prefix accurate? If not, is it right that the number should be typically small? (If so a deduplication scheme of which this is a special case almost certainly makes sense).
1 parent 5151b8c commit 5b3116c

File tree

1 file changed

+52
-0
lines changed
  • compiler/rustc_metadata/src/rmeta

1 file changed

+52
-0
lines changed

compiler/rustc_metadata/src/rmeta/table.rs

+52
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ pub(super) trait FixedSizeEncoding: IsDefault {
6969
/// Cannot use an associated `const BYTE_LEN: usize` instead due to const eval limitations.
7070
type ByteArray;
7171

72+
const IS_DEF_PATH_HASH: bool = false;
73+
fn from_16_bytes(_: &[u8; 16]) -> Self {
74+
unreachable!()
75+
}
76+
7277
fn from_bytes(b: &Self::ByteArray) -> Self;
7378
fn write_to_bytes(self, b: &mut Self::ByteArray);
7479
}
@@ -223,6 +228,11 @@ fixed_size_enum! {
223228
impl FixedSizeEncoding for DefPathHash {
224229
type ByteArray = [u8; 16];
225230

231+
const IS_DEF_PATH_HASH: bool = true;
232+
fn from_16_bytes(b: &[u8; 16]) -> Self {
233+
DefPathHash(Fingerprint::from_le_bytes(*b))
234+
}
235+
226236
#[inline]
227237
fn from_bytes(b: &[u8; 16]) -> Self {
228238
DefPathHash(Fingerprint::from_le_bytes(*b))
@@ -482,6 +492,37 @@ impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBui
482492
pub(crate) fn encode(&self, buf: &mut FileEncoder) -> LazyTable<I, T> {
483493
let pos = buf.position();
484494

495+
if T::IS_DEF_PATH_HASH {
496+
if self.blocks.is_empty() {
497+
return LazyTable::from_position_and_encoded_size(
498+
NonZeroUsize::new(pos).unwrap(),
499+
0,
500+
0,
501+
);
502+
}
503+
let mut prefix: Option<[u8; 8]> = None;
504+
for block in self.blocks.iter() {
505+
if prefix.is_none() {
506+
prefix = Some(block[..8].try_into().unwrap());
507+
}
508+
assert_eq!(prefix.unwrap(), block[..8]);
509+
}
510+
buf.write_array(prefix.unwrap());
511+
512+
for block in &self.blocks {
513+
buf.write_with::<8>(|dest| {
514+
*dest = block[8..].try_into().unwrap();
515+
8
516+
});
517+
}
518+
519+
return LazyTable::from_position_and_encoded_size(
520+
NonZeroUsize::new(pos).unwrap(),
521+
0,
522+
self.blocks.len(),
523+
);
524+
}
525+
485526
let width = self.width;
486527
for block in &self.blocks {
487528
buf.write_with(|dest| {
@@ -516,6 +557,17 @@ where
516557
return Default::default();
517558
}
518559

560+
if T::IS_DEF_PATH_HASH {
561+
let region = &metadata.blob()[self.position.get()..];
562+
let prefix: [u8; 8] = region[..8].try_into().unwrap();
563+
let local_hash_region = &region[8..];
564+
let suffix: [u8; 8] = local_hash_region[i.index() * 8..][..8].try_into().unwrap();
565+
let mut combined = [0; 16];
566+
combined[..8].copy_from_slice(&prefix);
567+
combined[8..].copy_from_slice(&suffix);
568+
return FixedSizeEncoding::from_16_bytes(&combined);
569+
}
570+
519571
let width = self.width;
520572
let start = self.position.get() + (width * i.index());
521573
let end = start + width;

0 commit comments

Comments
 (0)