Skip to content

Commit 2dbe20a

Browse files
committed
libstd: Micro-optimize vuint_at
1 parent 4c29b4c commit 2dbe20a

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

src/libstd/ebml.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ pub mod reader {
5959
use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc};
6060
use serialize;
6161

62+
use core::cast::transmute;
6263
use core::int;
6364
use core::io;
6465
use core::prelude::*;
66+
use core::ptr::offset;
6567
use core::str;
68+
use core::unstable::intrinsics::bswap32;
6669
use core::vec;
6770

6871
// ebml reading
@@ -78,7 +81,8 @@ pub mod reader {
7881
next: uint
7982
}
8083

81-
fn vuint_at(data: &[u8], start: uint) -> Res {
84+
#[inline(never)]
85+
fn vuint_at_slow(data: &[u8], start: uint) -> Res {
8286
let a = data[start];
8387
if a & 0x80u8 != 0u8 {
8488
return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
@@ -87,18 +91,63 @@ pub mod reader {
8791
return Res {val: ((a & 0x3fu8) as uint) << 8u |
8892
(data[start + 1u] as uint),
8993
next: start + 2u};
90-
} else if a & 0x20u8 != 0u8 {
94+
}
95+
if a & 0x20u8 != 0u8 {
9196
return Res {val: ((a & 0x1fu8) as uint) << 16u |
9297
(data[start + 1u] as uint) << 8u |
9398
(data[start + 2u] as uint),
9499
next: start + 3u};
95-
} else if a & 0x10u8 != 0u8 {
100+
}
101+
if a & 0x10u8 != 0u8 {
96102
return Res {val: ((a & 0x0fu8) as uint) << 24u |
97103
(data[start + 1u] as uint) << 16u |
98104
(data[start + 2u] as uint) << 8u |
99105
(data[start + 3u] as uint),
100106
next: start + 4u};
101-
} else { error!("vint too big"); fail!(); }
107+
}
108+
fail!(~"vint too big");
109+
}
110+
111+
#[cfg(target_arch = "x86")]
112+
#[cfg(target_arch = "x86_64")]
113+
pub fn vuint_at(data: &[u8], start: uint) -> Res {
114+
if data.len() - start < 4 {
115+
return vuint_at_slow(data, start);
116+
}
117+
118+
unsafe {
119+
let (ptr, _): (*u8, uint) = transmute(data);
120+
let ptr = offset(ptr, start);
121+
let ptr: *i32 = transmute(ptr);
122+
let val = bswap32(*ptr);
123+
let val: u32 = transmute(val);
124+
if (val & 0x80000000) != 0 {
125+
Res {
126+
val: ((val >> 24) & 0x7f) as uint,
127+
next: start + 1
128+
}
129+
} else if (val & 0x40000000) != 0 {
130+
Res {
131+
val: ((val >> 16) & 0x3fff) as uint,
132+
next: start + 2
133+
}
134+
} else if (val & 0x20000000) != 0 {
135+
Res {
136+
val: ((val >> 8) & 0x1fffff) as uint,
137+
next: start + 3
138+
}
139+
} else {
140+
Res {
141+
val: (val & 0x0fffffff) as uint,
142+
next: start + 4
143+
}
144+
}
145+
}
146+
}
147+
148+
#[cfg(target_arch = "arm")]
149+
pub fn vuint_at(data: &[u8], start: uint) -> Res {
150+
vuint_at_slow(data, start)
102151
}
103152
104153
pub fn Doc(data: @~[u8]) -> Doc {

0 commit comments

Comments
 (0)