@@ -38,6 +38,12 @@ impl IsDefault for u32 {
38
38
}
39
39
}
40
40
41
+ impl IsDefault for u64 {
42
+ fn is_default ( & self ) -> bool {
43
+ * self == 0
44
+ }
45
+ }
46
+
41
47
impl < T > IsDefault for LazyArray < T > {
42
48
fn is_default ( & self ) -> bool {
43
49
self . num_elems == 0
@@ -89,6 +95,20 @@ impl FixedSizeEncoding for u32 {
89
95
}
90
96
}
91
97
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
+
92
112
macro_rules! fixed_size_enum {
93
113
( $ty: ty { $( ( $( $pat: tt) * ) ) * } ) => {
94
114
impl FixedSizeEncoding for Option <$ty> {
@@ -299,21 +319,21 @@ impl FixedSizeEncoding for UnusedGenericParams {
299
319
// generic `LazyValue<T>` impl, but in the general case we might not need / want
300
320
// to fit every `usize` in `u32`.
301
321
impl < T > FixedSizeEncoding for Option < LazyValue < T > > {
302
- type ByteArray = [ u8 ; 4 ] ;
322
+ type ByteArray = [ u8 ; 8 ] ;
303
323
304
324
#[ 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 ) ?;
307
327
Some ( LazyValue :: from_position ( position) )
308
328
}
309
329
310
330
#[ inline]
311
- fn write_to_bytes ( self , b : & mut [ u8 ; 4 ] ) {
331
+ fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
312
332
match self {
313
333
None => unreachable ! ( ) ,
314
334
Some ( lazy) => {
315
335
let position = lazy. position . get ( ) ;
316
- let position: u32 = position. try_into ( ) . unwrap ( ) ;
336
+ let position: u64 = position. try_into ( ) . unwrap ( ) ;
317
337
position. write_to_bytes ( b)
318
338
}
319
339
}
@@ -322,55 +342,67 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
322
342
323
343
impl < T > LazyArray < T > {
324
344
#[ 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 ( ) ;
327
348
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
+ }
335
353
}
336
354
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 ;
340
358
Some ( LazyArray :: from_position_and_num_elems ( position, len) )
341
359
}
342
360
}
343
361
344
362
impl < T > FixedSizeEncoding for LazyArray < T > {
345
- type ByteArray = [ u8 ; 8 ] ;
363
+ type ByteArray = [ u8 ; 16 ] ;
346
364
347
365
#[ 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 ] {
351
376
return Default :: default ( ) ;
352
377
}
353
- LazyArray :: from_bytes_impl ( position_bytes , meta_bytes ) . unwrap ( )
378
+ LazyArray :: from_bytes_impl ( & position , & meta ) . unwrap ( )
354
379
}
355
380
356
381
#[ inline]
357
- fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
382
+ fn write_to_bytes ( self , b : & mut [ u8 ; 16 ] ) {
358
383
assert ! ( !self . is_default( ) ) ;
359
384
self . write_to_bytes_impl ( b)
360
385
}
361
386
}
362
387
363
388
impl < T > FixedSizeEncoding for Option < LazyArray < T > > {
364
- type ByteArray = [ u8 ; 8 ] ;
389
+ type ByteArray = [ u8 ; 16 ] ;
365
390
366
391
#[ 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)
370
402
}
371
403
372
404
#[ inline]
373
- fn write_to_bytes ( self , b : & mut [ u8 ; 8 ] ) {
405
+ fn write_to_bytes ( self , b : & mut [ u8 ; 16 ] ) {
374
406
match self {
375
407
None => unreachable ! ( ) ,
376
408
Some ( lazy) => lazy. write_to_bytes_impl ( b) ,
@@ -380,13 +412,14 @@ impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
380
412
381
413
/// Helper for constructing a table's serialization (also see `Table`).
382
414
pub ( super ) struct TableBuilder < I : Idx , T : FixedSizeEncoding > {
415
+ width : usize ,
383
416
blocks : IndexVec < I , T :: ByteArray > ,
384
417
_marker : PhantomData < T > ,
385
418
}
386
419
387
420
impl < I : Idx , T : FixedSizeEncoding > Default for TableBuilder < I , T > {
388
421
fn default ( ) -> Self {
389
- TableBuilder { blocks : Default :: default ( ) , _marker : PhantomData }
422
+ TableBuilder { width : 0 , blocks : Default :: default ( ) , _marker : PhantomData }
390
423
}
391
424
}
392
425
@@ -414,22 +447,33 @@ impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBui
414
447
// > store bit-masks of which item in each bucket is actually serialized).
415
448
let block = self . blocks . ensure_contains_elem ( i, || [ 0 ; N ] ) ;
416
449
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
+ }
417
454
}
418
455
}
419
456
420
457
pub ( crate ) fn encode ( & self , buf : & mut FileEncoder ) -> LazyTable < I , T > {
421
458
let pos = buf. position ( ) ;
459
+
460
+ let width = self . width ;
422
461
for block in & self . blocks {
423
- buf. emit_raw_bytes ( block) ;
462
+ buf. emit_raw_bytes ( & block[ ..width ] ) ;
424
463
}
425
- let num_bytes = self . blocks . len ( ) * N ;
464
+
426
465
LazyTable :: from_position_and_encoded_size (
427
466
NonZeroUsize :: new ( pos as usize ) . unwrap ( ) ,
428
- num_bytes,
467
+ width,
468
+ self . blocks . len ( ) ,
429
469
)
430
470
}
431
471
}
432
472
473
+ fn trailing_zeros ( x : & [ u8 ] ) -> usize {
474
+ x. iter ( ) . rev ( ) . take_while ( |b| * * b == 0 ) . count ( )
475
+ }
476
+
433
477
impl < I : Idx , const N : usize , T : FixedSizeEncoding < ByteArray = [ u8 ; N ] > + ParameterizedOverTcx >
434
478
LazyTable < I , T >
435
479
where
@@ -438,16 +482,25 @@ where
438
482
/// Given the metadata, extract out the value at a particular index (if any).
439
483
#[ inline( never) ]
440
484
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] ;
442
496
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)
447
500
}
448
501
449
502
/// Size of the table in entries, including possible gaps.
450
503
pub ( super ) fn size ( & self ) -> usize {
451
- self . encoded_size / N
504
+ self . len
452
505
}
453
506
}
0 commit comments