@@ -72,53 +72,42 @@ impl FixedSizeEncoding for u32 {
72
72
/// (e.g. while visiting the definitions of a crate), and on-demand decoding
73
73
/// of specific indices (e.g. queries for per-definition data).
74
74
/// 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.
75
79
pub struct Table < T : LazyMeta < Meta = ( ) > > {
76
- positions : [ Vec < u8 > ; 2 ] ,
80
+ bytes : Vec < u8 > ,
77
81
_marker : PhantomData < T > ,
78
82
}
79
83
80
84
impl < 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 {
82
86
Table {
83
- positions : [ vec ! [ 0 ; max_index_lo * 4 ] ,
84
- vec ! [ 0 ; max_index_hi * 4 ] ] ,
87
+ bytes : vec ! [ 0 ; len * 4 ] ,
85
88
_marker : PhantomData ,
86
89
}
87
90
}
88
91
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 > ) {
95
93
let position = entry. position . get ( ) as u32 ;
96
94
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) ,
105
100
position) ;
106
101
107
- position. write_to_bytes_at ( positions , array_index )
102
+ position. write_to_bytes_at ( & mut self . bytes , i )
108
103
}
109
104
110
105
pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
111
106
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 ) ;
119
108
Lazy :: from_position_and_meta (
120
109
NonZeroUsize :: new ( pos as usize ) . unwrap ( ) ,
121
- ( self . positions [ 0 ] . len ( ) + self . positions [ 1 ] . len ( ) ) / 4 + 1 ,
110
+ self . bytes . len ( ) ,
122
111
)
123
112
}
124
113
}
@@ -127,31 +116,81 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
127
116
type Meta = usize ;
128
117
129
118
fn min_size ( len : usize ) -> usize {
130
- len * 4
119
+ len
131
120
}
132
121
}
133
122
134
123
impl < 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).
137
125
#[ 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) ;
154
131
debug ! ( "Table::lookup: position={:?}" , position) ;
132
+
155
133
NonZeroUsize :: new ( position as usize ) . map ( Lazy :: from_position)
156
134
}
157
135
}
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