@@ -10,53 +10,43 @@ use log::debug;
1010/// (e.g. while visiting the definitions of a crate), and on-demand decoding
1111/// of specific indices (e.g. queries for per-definition data).
1212/// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
13+ // FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
14+ // when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
15+ // Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
16+ // and so would need two lengths in its metadata, which is not supported yet.
1317pub struct Table < T : LazyMeta < Meta = ( ) > > {
14- positions : [ Vec < u8 > ; 2 ] ,
18+ bytes : Vec < u8 > ,
1519 _marker : PhantomData < T > ,
1620}
1721
1822impl < T : LazyMeta < Meta = ( ) > > Table < T > {
19- pub fn new ( ( max_index_lo , max_index_hi ) : ( usize , usize ) ) -> Self {
23+ pub fn new ( len : usize ) -> Self {
2024 Table {
21- positions : [ vec ! [ 0 ; max_index_lo * 4 ] ,
22- vec ! [ 0 ; max_index_hi * 4 ] ] ,
25+ bytes : vec ! [ 0 ; len * 4 ] ,
2326 _marker : PhantomData ,
2427 }
2528 }
2629
27- pub fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
28- assert ! ( def_id. is_local( ) ) ;
29- self . record_index ( def_id. index , entry) ;
30- }
31-
32- pub fn record_index ( & mut self , item : DefIndex , entry : Lazy < T > ) {
30+ pub fn record ( & mut self , i : usize , entry : Lazy < T > ) {
3331 let position = entry. position . get ( ) as u32 ;
3432 assert_eq ! ( position as usize , entry. position. get( ) ) ;
35- let space_index = item. address_space ( ) . index ( ) ;
36- let array_index = item. as_array_index ( ) ;
37-
38- let destination = & mut self . positions [ space_index] [ array_index * 4 ..] ;
39- assert ! ( read_le_u32( destination) == 0 ,
40- "recorded position for item {:?} twice, first at {:?} and now at {:?}" ,
41- item,
42- read_le_u32( destination) ,
33+
34+ let bytes = & mut self . bytes [ i * 4 ..] ;
35+ assert ! ( read_le_u32( bytes) == 0 ,
36+ "recorded position for index {:?} twice, first at {:?} and now at {:?}" ,
37+ i,
38+ read_le_u32( bytes) ,
4339 position) ;
4440
45- write_le_u32 ( destination , position) ;
41+ write_le_u32 ( bytes , position) ;
4642 }
4743
4844 pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
4945 let pos = buf. position ( ) ;
50-
51- // First we write the length of the lower range ...
52- buf. emit_raw_bytes ( & ( self . positions [ 0 ] . len ( ) as u32 / 4 ) . to_le_bytes ( ) ) ;
53- // ... then the values in the lower range ...
54- buf. emit_raw_bytes ( & self . positions [ 0 ] ) ;
55- // ... then the values in the higher range.
56- buf. emit_raw_bytes ( & self . positions [ 1 ] ) ;
46+ buf. emit_raw_bytes ( & self . bytes ) ;
5747 Lazy :: from_position_and_meta (
5848 NonZeroUsize :: new ( pos as usize ) . unwrap ( ) ,
59- ( self . positions [ 0 ] . len ( ) + self . positions [ 1 ] . len ( ) ) / 4 + 1 ,
49+ self . bytes . len ( ) ,
6050 )
6151 }
6252}
@@ -65,30 +55,20 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
6555 type Meta = usize ;
6656
6757 fn min_size ( len : usize ) -> usize {
68- len * 4
58+ len
6959 }
7060}
7161
7262impl < T : Encodable > Lazy < Table < T > > {
73- /// Given the metadata, extract out the offset of a particular
74- /// DefIndex (if any).
63+ /// Given the metadata, extract out the offset of a particular index (if any).
7564 #[ inline( never) ]
76- pub fn lookup ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < Lazy < T > > {
77- debug ! ( "Table::lookup: index={:?} len={:?}" ,
78- def_index,
79- self . meta) ;
80-
81- let i = def_index. as_array_index ( ) + match def_index. address_space ( ) {
82- DefIndexAddressSpace :: Low => 0 ,
83- DefIndexAddressSpace :: High => {
84- // This is a DefIndex in the higher range, so find out where
85- // that starts:
86- read_le_u32 ( & bytes[ self . position . get ( ) ..] ) as usize
87- }
88- } ;
89-
90- let position = read_le_u32 ( & bytes[ self . position . get ( ) + ( 1 + i) * 4 ..] ) ;
65+ pub fn lookup ( & self , bytes : & [ u8 ] , i : usize ) -> Option < Lazy < T > > {
66+ debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
67+
68+ let bytes = & bytes[ self . position . get ( ) ..] [ ..self . meta ] ;
69+ let position = read_le_u32 ( & bytes[ i * 4 ..] ) ;
9170 debug ! ( "Table::lookup: position={:?}" , position) ;
71+
9272 NonZeroUsize :: new ( position as usize ) . map ( Lazy :: from_position)
9373 }
9474}
@@ -102,3 +82,64 @@ fn read_le_u32(b: &[u8]) -> u32 {
10282fn write_le_u32 ( b : & mut [ u8 ] , x : u32 ) {
10383 b[ ..4 ] . copy_from_slice ( & x. to_le_bytes ( ) ) ;
10484}
85+
86+ /// Per-definition table, similar to `Table` but keyed on `DefIndex`.
87+ /// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in.
88+ pub struct PerDefTable < T : LazyMeta < Meta = ( ) > > {
89+ lo : Table < T > ,
90+ hi : Table < T > ,
91+ }
92+
93+ impl < T : LazyMeta < Meta = ( ) > > PerDefTable < T > {
94+ pub fn new ( ( max_index_lo, max_index_hi) : ( usize , usize ) ) -> Self {
95+ PerDefTable {
96+ lo : Table :: new ( max_index_lo) ,
97+ hi : Table :: new ( max_index_hi) ,
98+ }
99+ }
100+
101+ pub fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
102+ assert ! ( def_id. is_local( ) ) ;
103+ let space_index = def_id. index . address_space ( ) . index ( ) ;
104+ let array_index = def_id. index . as_array_index ( ) ;
105+ [ & mut self . lo , & mut self . hi ] [ space_index] . record ( array_index, entry) ;
106+ }
107+
108+ pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
109+ let lo = self . lo . encode ( buf) ;
110+ let hi = self . hi . encode ( buf) ;
111+ assert_eq ! ( lo. position. get( ) + lo. meta, hi. position. get( ) ) ;
112+
113+ Lazy :: from_position_and_meta (
114+ lo. position ,
115+ [ lo. meta , hi. meta ] ,
116+ )
117+ }
118+ }
119+
120+ impl < T : LazyMeta < Meta = ( ) > > LazyMeta for PerDefTable < T > {
121+ type Meta = [ <Table < T > as LazyMeta >:: Meta ; 2 ] ;
122+
123+ fn min_size ( [ lo, hi] : Self :: Meta ) -> usize {
124+ Table :: < T > :: min_size ( lo) + Table :: < T > :: min_size ( hi)
125+ }
126+ }
127+
128+ impl < T : Encodable > Lazy < PerDefTable < T > > {
129+ fn table_for_space ( & self , space : DefIndexAddressSpace ) -> Lazy < Table < T > > {
130+ let space_index = space. index ( ) ;
131+ let offset = space_index. checked_sub ( 1 ) . map_or ( 0 , |i| self . meta [ i] ) ;
132+ Lazy :: from_position_and_meta (
133+ NonZeroUsize :: new ( self . position . get ( ) + offset) . unwrap ( ) ,
134+ self . meta [ space_index]
135+ )
136+ }
137+
138+ /// Given the metadata, extract out the offset of a particular DefIndex (if any).
139+ #[ inline( never) ]
140+ pub fn lookup ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < Lazy < T > > {
141+ self . table_for_space ( def_index. address_space ( ) )
142+ . lookup ( bytes, def_index. as_array_index ( ) )
143+ }
144+ }
145+
0 commit comments