@@ -72,53 +72,42 @@ impl FixedSizeEncoding for u32 {
7272/// (e.g. while visiting the definitions of a crate), and on-demand decoding
7373/// of specific indices (e.g. queries for per-definition data).
7474/// Similar to `Vec<Lazy<T>>`, but with zero-copy decoding.
75+ // FIXME(eddyb) newtype `[u8]` here, such that `Box<Table<T>>` would be used
76+ // when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
77+ // Sadly, that doesn't work for `DefPerTable`, which is `(Table<T>, Table<T>)`,
78+ // and so would need two lengths in its metadata, which is not supported yet.
7579pub struct Table < T : LazyMeta < Meta = ( ) > > {
76- positions : [ Vec < u8 > ; 2 ] ,
80+ bytes : Vec < u8 > ,
7781 _marker : PhantomData < T > ,
7882}
7983
8084impl < T : LazyMeta < Meta = ( ) > > Table < T > {
81- pub fn new ( ( max_index_lo , max_index_hi ) : ( usize , usize ) ) -> Self {
85+ pub fn new ( len : usize ) -> Self {
8286 Table {
83- positions : [ vec ! [ 0 ; max_index_lo * 4 ] ,
84- vec ! [ 0 ; max_index_hi * 4 ] ] ,
87+ bytes : vec ! [ 0 ; len * 4 ] ,
8588 _marker : PhantomData ,
8689 }
8790 }
8891
89- pub fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
90- assert ! ( def_id. is_local( ) ) ;
91- self . record_index ( def_id. index , entry) ;
92- }
93-
94- pub fn record_index ( & mut self , item : DefIndex , entry : Lazy < T > ) {
92+ pub fn record ( & mut self , i : usize , entry : Lazy < T > ) {
9593 let position = entry. position . get ( ) as u32 ;
9694 assert_eq ! ( position as usize , entry. position. get( ) ) ;
97- let space_index = item. address_space ( ) . index ( ) ;
98- let array_index = item. as_array_index ( ) ;
99-
100- let positions = & mut self . positions [ space_index] ;
101- assert ! ( u32 :: read_from_bytes_at( positions, array_index) == 0 ,
102- "recorded position for item {:?} twice, first at {:?} and now at {:?}" ,
103- item,
104- u32 :: read_from_bytes_at( positions, array_index) ,
95+
96+ assert ! ( u32 :: read_from_bytes_at( & self . bytes, i) == 0 ,
97+ "recorded position for index {:?} twice, first at {:?} and now at {:?}" ,
98+ i,
99+ u32 :: read_from_bytes_at( & self . bytes, i) ,
105100 position) ;
106101
107- position. write_to_bytes_at ( positions , array_index )
102+ position. write_to_bytes_at ( & mut self . bytes , i )
108103 }
109104
110105 pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
111106 let pos = buf. position ( ) ;
112-
113- // First we write the length of the lower range ...
114- buf. emit_raw_bytes ( & ( self . positions [ 0 ] . len ( ) as u32 / 4 ) . to_le_bytes ( ) ) ;
115- // ... then the values in the lower range ...
116- buf. emit_raw_bytes ( & self . positions [ 0 ] ) ;
117- // ... then the values in the higher range.
118- buf. emit_raw_bytes ( & self . positions [ 1 ] ) ;
107+ buf. emit_raw_bytes ( & self . bytes ) ;
119108 Lazy :: from_position_and_meta (
120109 NonZeroUsize :: new ( pos as usize ) . unwrap ( ) ,
121- ( self . positions [ 0 ] . len ( ) + self . positions [ 1 ] . len ( ) ) / 4 + 1 ,
110+ self . bytes . len ( ) ,
122111 )
123112 }
124113}
@@ -127,31 +116,81 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
127116 type Meta = usize ;
128117
129118 fn min_size ( len : usize ) -> usize {
130- len * 4
119+ len
131120 }
132121}
133122
134123impl < T : Encodable > Lazy < Table < T > > {
135- /// Given the metadata, extract out the offset of a particular
136- /// DefIndex (if any).
124+ /// Given the metadata, extract out the offset of a particular index (if any).
137125 #[ inline( never) ]
138- pub fn lookup ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < Lazy < T > > {
139- let bytes = & bytes[ self . position . get ( ) ..] ;
140- debug ! ( "Table::lookup: index={:?} len={:?}" ,
141- def_index,
142- self . meta) ;
143-
144- let i = def_index. as_array_index ( ) + match def_index. address_space ( ) {
145- DefIndexAddressSpace :: Low => 0 ,
146- DefIndexAddressSpace :: High => {
147- // This is a DefIndex in the higher range, so find out where
148- // that starts:
149- u32:: read_from_bytes_at ( bytes, 0 ) as usize
150- }
151- } ;
152-
153- let position = u32:: read_from_bytes_at ( bytes, 1 + i) ;
126+ pub fn lookup ( & self , bytes : & [ u8 ] , i : usize ) -> Option < Lazy < T > > {
127+ debug ! ( "Table::lookup: index={:?} len={:?}" , i, self . meta) ;
128+
129+ let bytes = & bytes[ self . position . get ( ) ..] [ ..self . meta ] ;
130+ let position = u32:: read_from_bytes_at ( bytes, i) ;
154131 debug ! ( "Table::lookup: position={:?}" , position) ;
132+
155133 NonZeroUsize :: new ( position as usize ) . map ( Lazy :: from_position)
156134 }
157135}
136+
137+
138+ /// Per-definition table, similar to `Table` but keyed on `DefIndex`.
139+ /// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in.
140+ pub struct PerDefTable < T : LazyMeta < Meta = ( ) > > {
141+ lo : Table < T > ,
142+ hi : Table < T > ,
143+ }
144+
145+ impl < T : LazyMeta < Meta = ( ) > > PerDefTable < T > {
146+ pub fn new ( ( max_index_lo, max_index_hi) : ( usize , usize ) ) -> Self {
147+ PerDefTable {
148+ lo : Table :: new ( max_index_lo) ,
149+ hi : Table :: new ( max_index_hi) ,
150+ }
151+ }
152+
153+ pub fn record ( & mut self , def_id : DefId , entry : Lazy < T > ) {
154+ assert ! ( def_id. is_local( ) ) ;
155+ let space_index = def_id. index . address_space ( ) . index ( ) ;
156+ let array_index = def_id. index . as_array_index ( ) ;
157+ [ & mut self . lo , & mut self . hi ] [ space_index] . record ( array_index, entry) ;
158+ }
159+
160+ pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
161+ let lo = self . lo . encode ( buf) ;
162+ let hi = self . hi . encode ( buf) ;
163+ assert_eq ! ( lo. position. get( ) + lo. meta, hi. position. get( ) ) ;
164+
165+ Lazy :: from_position_and_meta (
166+ lo. position ,
167+ [ lo. meta , hi. meta ] ,
168+ )
169+ }
170+ }
171+
172+ impl < T : LazyMeta < Meta = ( ) > > LazyMeta for PerDefTable < T > {
173+ type Meta = [ <Table < T > as LazyMeta >:: Meta ; 2 ] ;
174+
175+ fn min_size ( [ lo, hi] : Self :: Meta ) -> usize {
176+ Table :: < T > :: min_size ( lo) + Table :: < T > :: min_size ( hi)
177+ }
178+ }
179+
180+ impl < T : Encodable > Lazy < PerDefTable < T > > {
181+ fn table_for_space ( & self , space : DefIndexAddressSpace ) -> Lazy < Table < T > > {
182+ let space_index = space. index ( ) ;
183+ let offset = space_index. checked_sub ( 1 ) . map_or ( 0 , |i| self . meta [ i] ) ;
184+ Lazy :: from_position_and_meta (
185+ NonZeroUsize :: new ( self . position . get ( ) + offset) . unwrap ( ) ,
186+ self . meta [ space_index]
187+ )
188+ }
189+
190+ /// Given the metadata, extract out the offset of a particular DefIndex (if any).
191+ #[ inline( never) ]
192+ pub fn lookup ( & self , bytes : & [ u8 ] , def_index : DefIndex ) -> Option < Lazy < T > > {
193+ self . table_for_space ( def_index. address_space ( ) )
194+ . lookup ( bytes, def_index. as_array_index ( ) )
195+ }
196+ }
0 commit comments