Skip to content

Commit a6bf055

Browse files
committed
Reapply "simd: split cursor advancing from value matching (#156)"
This reverts commit 140faf3.
1 parent 896f1c1 commit a6bf055

File tree

7 files changed

+227
-232
lines changed

7 files changed

+227
-232
lines changed

src/lib.rs

+19-14
Original file line numberDiff line numberDiff line change
@@ -953,18 +953,20 @@ fn parse_token<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
953953
#[allow(missing_docs)]
954954
// WARNING: Exported for internal benchmarks, not fit for public consumption
955955
pub fn parse_uri<'a>(bytes: &mut Bytes<'a>) -> Result<&'a str> {
956-
let start = bytes.pos();
957-
simd::match_uri_vectored(bytes);
958956
// URI must have at least one char
959-
if bytes.pos() == start {
957+
let uri_len = simd::match_uri_vectored(bytes.as_ref());
958+
if uri_len == 0 {
960959
return Err(Error::Token);
961960
}
961+
// SAFETY: these bytes have just been matched here above.
962+
unsafe { bytes.advance(uri_len) };
963+
let uri_slice = bytes.slice();
962964

963-
if next!(bytes) == b' ' {
964-
return Ok(Status::Complete(
965-
// SAFETY: all bytes up till `i` must have been `is_token` and therefore also utf-8.
966-
unsafe { str::from_utf8_unchecked(bytes.slice_skip(1)) },
967-
));
965+
let space_delim = next!(bytes);
966+
if space_delim == b' ' {
967+
// SAFETY: all bytes within `uri_slice` must have been `is_token` and therefore also utf-8.
968+
let uri = unsafe { str::from_utf8_unchecked(uri_slice) };
969+
Ok(Status::Complete(uri))
968970
} else {
969971
Err(Error::Token)
970972
}
@@ -1179,15 +1181,15 @@ fn parse_headers_iter_uninit<'a>(
11791181
#[allow(clippy::never_loop)]
11801182
// parse header name until colon
11811183
let header_name: &str = 'name: loop {
1182-
simd::match_header_name_vectored(bytes);
1183-
let mut b = next!(bytes);
1184-
1185-
// SAFETY: previously bumped by 1 with next! -> always safe.
1186-
let bslice = unsafe { bytes.slice_skip(1) };
1184+
let len = simd::match_header_name_vectored(bytes.as_ref());
1185+
// SAFETY: these bytes have just been matched here above.
1186+
unsafe { bytes.advance(len) };
1187+
let bslice = bytes.slice();
11871188
// SAFETY: previous call to match_header_name_vectored ensured all bytes are valid
11881189
// header name chars, and as such also valid utf-8.
11891190
let name = unsafe { str::from_utf8_unchecked(bslice) };
11901191

1192+
let mut b = next!(bytes);
11911193
if b == b':' {
11921194
break 'name name;
11931195
}
@@ -1213,6 +1215,7 @@ fn parse_headers_iter_uninit<'a>(
12131215
// eat white space between colon and value
12141216
'whitespace_after_colon: loop {
12151217
b = next!(bytes);
1218+
12161219
if b == b' ' || b == b'\t' {
12171220
bytes.slice();
12181221
continue 'whitespace_after_colon;
@@ -1239,7 +1242,9 @@ fn parse_headers_iter_uninit<'a>(
12391242
'value_lines: loop {
12401243
// parse value till EOL
12411244

1242-
simd::match_header_value_vectored(bytes);
1245+
let len = simd::match_header_value_vectored(bytes.as_ref());
1246+
// SAFETY: these bytes have just been matched here above.
1247+
unsafe { bytes.advance(len) };
12431248
let b = next!(bytes);
12441249

12451250
//found_ctl

src/simd/avx2.rs

+25-19
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
use crate::iter::Bytes;
2-
31
#[inline]
42
#[target_feature(enable = "avx2", enable = "sse4.2")]
5-
pub unsafe fn match_uri_vectored(bytes: &mut Bytes) {
6-
while bytes.as_ref().len() >= 32 {
7-
let advance = match_url_char_32_avx(bytes.as_ref());
8-
bytes.advance(advance);
3+
pub(crate) unsafe fn match_uri_vectored(bytes: &[u8]) -> usize {
4+
let mut len = 0usize;
5+
let mut remaining = bytes;
6+
while remaining.len() >= 32 {
7+
let advance = match_url_char_32_avx(remaining);
8+
len = len.saturating_add(advance);
9+
remaining = &bytes[len..];
910

1011
if advance != 32 {
11-
return;
12+
return len;
1213
}
1314
}
1415
// do both, since avx2 only works when bytes.len() >= 32
15-
super::sse42::match_uri_vectored(bytes)
16+
let advance = super::sse42::match_uri_vectored(remaining);
17+
len = len.saturating_add(advance);
18+
len
1619
}
1720

1821
#[inline(always)]
@@ -57,17 +60,22 @@ unsafe fn match_url_char_32_avx(buf: &[u8]) -> usize {
5760
}
5861

5962
#[target_feature(enable = "avx2", enable = "sse4.2")]
60-
pub unsafe fn match_header_value_vectored(bytes: &mut Bytes) {
61-
while bytes.as_ref().len() >= 32 {
62-
let advance = match_header_value_char_32_avx(bytes.as_ref());
63-
bytes.advance(advance);
63+
pub(crate) unsafe fn match_header_value_vectored(bytes: &[u8]) -> usize {
64+
let mut len = 0usize;
65+
let mut remaining = bytes;
66+
while remaining.len() >= 32 {
67+
let advance = match_header_value_char_32_avx(remaining);
68+
len = len.saturating_add(advance);
69+
remaining = &bytes[len..];
6470

6571
if advance != 32 {
66-
return;
72+
return len;
6773
}
6874
}
6975
// do both, since avx2 only works when bytes.len() >= 32
70-
super::sse42::match_header_value_vectored(bytes)
76+
let advance = super::sse42::match_header_value_vectored(remaining);
77+
len = len.saturating_add(advance);
78+
len
7179
}
7280

7381
#[inline(always)]
@@ -138,7 +146,7 @@ fn avx2_code_matches_header_value_chars_table() {
138146
}
139147

140148
#[cfg(test)]
141-
unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>)) -> bool {
149+
unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &[u8]) -> usize) -> bool {
142150
let slice = [
143151
b'_', b'_', b'_', b'_',
144152
b'_', b'_', b'_', b'_',
@@ -149,11 +157,9 @@ unsafe fn byte_is_allowed(byte: u8, f: unsafe fn(bytes: &mut Bytes<'_>)) -> bool
149157
b'_', b'_', byte, b'_',
150158
b'_', b'_', b'_', b'_',
151159
];
152-
let mut bytes = Bytes::new(&slice);
153-
154-
f(&mut bytes);
155160

156-
match bytes.pos() {
161+
let pos = f(&slice);
162+
match pos {
157163
32 => true,
158164
26 => false,
159165
_ => unreachable!(),

src/simd/mod.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod swar;
1111
)
1212
),
1313
)))]
14-
pub use self::swar::*;
14+
pub(crate) use self::swar::*;
1515

1616
#[cfg(all(
1717
httparse_simd,
@@ -59,7 +59,7 @@ mod runtime;
5959
target_arch = "x86_64",
6060
),
6161
))]
62-
pub use self::runtime::*;
62+
pub(crate) use self::runtime::*;
6363

6464
#[cfg(all(
6565
httparse_simd,
@@ -72,18 +72,18 @@ pub use self::runtime::*;
7272
))]
7373
mod sse42_compile_time {
7474
#[inline(always)]
75-
pub fn match_header_name_vectored(b: &mut crate::iter::Bytes<'_>) {
76-
super::swar::match_header_name_vectored(b);
75+
pub(crate) fn match_header_name_vectored(b: &[u8]) -> usize {
76+
super::swar::match_header_name_vectored(b)
7777
}
7878

7979
#[inline(always)]
80-
pub fn match_uri_vectored(b: &mut crate::iter::Bytes<'_>) {
80+
pub(crate) fn match_uri_vectored(b: &[u8]) -> usize {
8181
// SAFETY: calls are guarded by a compile time feature check
8282
unsafe { crate::simd::sse42::match_uri_vectored(b) }
8383
}
84-
84+
8585
#[inline(always)]
86-
pub fn match_header_value_vectored(b: &mut crate::iter::Bytes<'_>) {
86+
pub(crate) fn match_header_value_vectored(b: &[u8]) -> usize {
8787
// SAFETY: calls are guarded by a compile time feature check
8888
unsafe { crate::simd::sse42::match_header_value_vectored(b) }
8989
}
@@ -98,7 +98,7 @@ mod sse42_compile_time {
9898
target_arch = "x86_64",
9999
),
100100
))]
101-
pub use self::sse42_compile_time::*;
101+
pub(crate) use self::sse42_compile_time::*;
102102

103103
#[cfg(all(
104104
httparse_simd,
@@ -110,18 +110,18 @@ pub use self::sse42_compile_time::*;
110110
))]
111111
mod avx2_compile_time {
112112
#[inline(always)]
113-
pub fn match_header_name_vectored(b: &mut crate::iter::Bytes<'_>) {
114-
super::swar::match_header_name_vectored(b);
113+
pub(crate) fn match_header_name_vectored(b: &[u8]) -> usize {
114+
super::swar::match_header_name_vectored(b)
115115
}
116116

117117
#[inline(always)]
118-
pub fn match_uri_vectored(b: &mut crate::iter::Bytes<'_>) {
118+
pub(crate) fn match_uri_vectored(b: &[u8]) -> usize {
119119
// SAFETY: calls are guarded by a compile time feature check
120120
unsafe { crate::simd::avx2::match_uri_vectored(b) }
121121
}
122-
122+
123123
#[inline(always)]
124-
pub fn match_header_value_vectored(b: &mut crate::iter::Bytes<'_>) {
124+
pub(crate) fn match_header_value_vectored(b: &[u8]) -> usize {
125125
// SAFETY: calls are guarded by a compile time feature check
126126
unsafe { crate::simd::avx2::match_header_value_vectored(b) }
127127
}
@@ -135,7 +135,7 @@ mod avx2_compile_time {
135135
target_arch = "x86_64",
136136
),
137137
))]
138-
pub use self::avx2_compile_time::*;
138+
pub(crate) use self::avx2_compile_time::*;
139139

140140
#[cfg(all(
141141
httparse_simd,
@@ -149,4 +149,4 @@ mod neon;
149149
target_arch = "aarch64",
150150
httparse_simd_neon_intrinsics,
151151
))]
152-
pub use self::neon::*;
152+
pub(crate) use self::neon::*;

0 commit comments

Comments
 (0)