@@ -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+
4147impl < 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+
92112macro_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`.
301321impl < 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
323343impl < 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
344362impl < 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
363388impl < 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`).
382414pub ( super ) struct TableBuilder < I : Idx , T : FixedSizeEncoding > {
415+ width : usize ,
383416 blocks : IndexVec < I , T :: ByteArray > ,
384417 _marker : PhantomData < T > ,
385418}
386419
387420impl < 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+
433477impl < I : Idx , const N : usize , T : FixedSizeEncoding < ByteArray = [ u8 ; N ] > + ParameterizedOverTcx >
434478 LazyTable < I , T >
435479where
@@ -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