@@ -10,53 +10,43 @@ use log::debug;
10
10
/// (e.g. while visiting the definitions of a crate), and on-demand decoding
11
11
/// of specific indices (e.g. queries for per-definition data).
12
12
/// 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.
13
17
pub struct Table < T : LazyMeta < Meta = ( ) > > {
14
- positions : [ Vec < u8 > ; 2 ] ,
18
+ bytes : Vec < u8 > ,
15
19
_marker : PhantomData < T > ,
16
20
}
17
21
18
22
impl < 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 {
20
24
Table {
21
- positions : [ vec ! [ 0 ; max_index_lo * 4 ] ,
22
- vec ! [ 0 ; max_index_hi * 4 ] ] ,
25
+ bytes : vec ! [ 0 ; len * 4 ] ,
23
26
_marker : PhantomData ,
24
27
}
25
28
}
26
29
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 > ) {
33
31
let position = entry. position . get ( ) as u32 ;
34
32
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) ,
43
39
position) ;
44
40
45
- write_le_u32 ( destination , position) ;
41
+ write_le_u32 ( bytes , position) ;
46
42
}
47
43
48
44
pub fn encode ( & self , buf : & mut Encoder ) -> Lazy < Self > {
49
45
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 ) ;
57
47
Lazy :: from_position_and_meta (
58
48
NonZeroUsize :: new ( pos as usize ) . unwrap ( ) ,
59
- ( self . positions [ 0 ] . len ( ) + self . positions [ 1 ] . len ( ) ) / 4 + 1 ,
49
+ self . bytes . len ( ) ,
60
50
)
61
51
}
62
52
}
@@ -65,30 +55,20 @@ impl<T: LazyMeta<Meta = ()>> LazyMeta for Table<T> {
65
55
type Meta = usize ;
66
56
67
57
fn min_size ( len : usize ) -> usize {
68
- len * 4
58
+ len
69
59
}
70
60
}
71
61
72
62
impl < 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).
75
64
#[ 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 ..] ) ;
91
70
debug ! ( "Table::lookup: position={:?}" , position) ;
71
+
92
72
NonZeroUsize :: new ( position as usize ) . map ( Lazy :: from_position)
93
73
}
94
74
}
@@ -102,3 +82,64 @@ fn read_le_u32(b: &[u8]) -> u32 {
102
82
fn write_le_u32 ( b : & mut [ u8 ] , x : u32 ) {
103
83
b[ ..4 ] . copy_from_slice ( & x. to_le_bytes ( ) ) ;
104
84
}
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