Skip to content

Commit d8877cd

Browse files
committed
Peel the first two iterations, outline the rest
1 parent 69f33e5 commit d8877cd

File tree

1 file changed

+29
-22
lines changed

1 file changed

+29
-22
lines changed

compiler/rustc_serialize/src/leb128.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,35 +51,42 @@ macro_rules! impl_read_unsigned_leb128 {
5151
($fn_name:ident, $int_ty:ty) => {
5252
#[inline]
5353
pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty {
54+
#[inline(never)]
55+
fn slow_path(slice: &[u8], position: &mut usize) -> Option<$int_ty> {
56+
let mut result = 0;
57+
let mut shift = 0;
58+
for consumed in 0..20 {
59+
let byte = slice[*position + consumed];
60+
result |= ((byte & 0x7F) as $int_ty) << shift;
61+
if (byte & 0x80) == 0 {
62+
*position += consumed + 1;
63+
return Some(result);
64+
}
65+
shift += 7;
66+
}
67+
None
68+
}
69+
5470
#[inline]
55-
fn inner(slice: &[u8], position: &mut usize) -> Option<$int_ty> {
56-
let mut pos = *position;
71+
fn fast_path(slice: &[u8], position: &mut usize) -> Option<$int_ty> {
72+
let pos = *position;
5773
// The first iteration of this loop is unpeeled. This is a
5874
// performance win because this code is hot and integer values less
5975
// than 128 are very common, typically occurring 50-80% or more of
6076
// the time, even for u64 and u128.
61-
let byte = *slice.get(pos)?;
62-
pos += 1;
63-
if (byte & 0x80) == 0 {
64-
*position = pos;
65-
return Some(byte as $int_ty);
66-
}
67-
let mut result = (byte & 0x7F) as $int_ty;
68-
let mut shift = 7;
69-
loop {
70-
let byte = *slice.get(pos)?;
71-
pos += 1;
72-
if (byte & 0x80) == 0 {
73-
result |= (byte as $int_ty) << shift;
74-
*position = pos;
75-
return Some(result);
76-
} else {
77-
result |= ((byte & 0x7F) as $int_ty) << shift;
78-
}
79-
shift += 7;
77+
if *slice.get(pos)? & 0x80 == 0 {
78+
*position += 1;
79+
Some(slice[pos] as $int_ty)
80+
} else if *slice.get(pos + 1)? & 0x80 == 0 {
81+
*position += 2;
82+
Some(((slice[pos] & 0x7F) as $int_ty) | (slice[pos + 1] as $int_ty << 7))
83+
84+
} else {
85+
slow_path(slice, position)
8086
}
8187
}
82-
inner(slice, position).unwrap()
88+
89+
fast_path(slice, position).unwrap()
8390
}
8491
};
8592
}

0 commit comments

Comments
 (0)