@@ -130,32 +130,39 @@ pub mod reader {
130
130
return vuint_at_slow ( data, start) ;
131
131
}
132
132
133
+ // Lookup table for parsing EBML Element IDs as per http://ebml.sourceforge.net/specs/
134
+ // The Element IDs are parsed by reading a big endian u32 positioned at data[start].
135
+ // Using the four most significant bits of the u32 we lookup in the table below how the
136
+ // element ID should be derived from it.
137
+ //
138
+ // The table stores tuples (shift, mask) where shift is the number the u32 should be right
139
+ // shifted with and mask is the value the right shifted value should be masked with.
140
+ // If for example the most significant bit is set this means it's a class A ID and the u32
141
+ // should be right shifted with 24 and masked with 0x7f. Therefore we store (24, 0x7f) at
142
+ // index 0x8 - 0xF (four bit numbers where the most significant bit is set).
143
+ //
144
+ // By storing the number of shifts and masks in a table instead of checking in order if
145
+ // the most significant bit is set, the second most significant bit is set etc. we can
146
+ // replace up to three "and+branch" with a single table lookup which gives us a measured
147
+ // speedup of around 2x on x86_64.
148
+ static SHIFT_MASK_TABLE : [ ( u32 , u32 ) , ..16 ] = [
149
+ ( 0 , 0x0 ) , ( 0 , 0x0fffffff ) ,
150
+ ( 8 , 0x1fffff ) , ( 8 , 0x1fffff ) ,
151
+ ( 16 , 0x3fff ) , ( 16 , 0x3fff ) , ( 16 , 0x3fff ) , ( 16 , 0x3fff ) ,
152
+ ( 24 , 0x7f ) , ( 24 , 0x7f ) , ( 24 , 0x7f ) , ( 24 , 0x7f ) , ( 24 , 0x7f ) , ( 24 , 0x7f ) , ( 24 , 0x7f ) , ( 24 , 0x7f )
153
+ ] ;
154
+
133
155
unsafe {
134
156
let ( ptr, _) : ( * u8 , uint ) = transmute ( data) ;
135
157
let ptr = offset ( ptr, start as int ) ;
136
158
let ptr: * i32 = transmute ( ptr) ;
137
- let val = from_be32 ( * ptr) ;
138
- let val: u32 = transmute ( val) ;
139
- if ( val & 0x80000000 ) != 0 {
140
- Res {
141
- val : ( ( val >> 24 ) & 0x7f ) as uint ,
142
- next : start + 1
143
- }
144
- } else if ( val & 0x40000000 ) != 0 {
145
- Res {
146
- val : ( ( val >> 16 ) & 0x3fff ) as uint ,
147
- next : start + 2
148
- }
149
- } else if ( val & 0x20000000 ) != 0 {
150
- Res {
151
- val : ( ( val >> 8 ) & 0x1fffff ) as uint ,
152
- next : start + 3
153
- }
154
- } else {
155
- Res {
156
- val : ( val & 0x0fffffff ) as uint ,
157
- next : start + 4
158
- }
159
+ let val = from_be32 ( * ptr) as u32 ;
160
+
161
+ let i = ( val >> 28 u) as uint ;
162
+ let ( shift, mask) = SHIFT_MASK_TABLE [ i] ;
163
+ Res {
164
+ val : ( ( val >> shift) & mask) as uint ,
165
+ next : start + ( ( ( 32 - shift) >> 3 ) as uint )
159
166
}
160
167
}
161
168
}
0 commit comments