mirror of
https://github.com/openharmony/third_party_rust_httparse.git
synced 2026-07-01 20:44:00 -04:00
Add 2 tests to check SIMD code against URI_CHARS
This commit is contained in:
committed by
Sean McArthur
parent
9643c936be
commit
c394735ec4
@@ -117,3 +117,45 @@ unsafe fn match_header_value_char_32_avx(buf: &[u8]) -> usize {
|
||||
unsafe fn match_header_value_char_32_avx(_: &[u8]) -> usize {
|
||||
unreachable!("AVX2 detection should be disabled for x86");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn avx2_code_matches_uri_chars_table() {
|
||||
match super::detect() {
|
||||
super::AVX_2 | super::AVX_2_AND_SSE_42 => {},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert!(byte_is_allowed(b'_'));
|
||||
|
||||
for (b, allowed) in ::URI_MAP.iter().cloned().enumerate() {
|
||||
assert_eq!(
|
||||
byte_is_allowed(b as u8), allowed,
|
||||
"byte_is_allowed({:?}) should be {:?}", b, allowed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
unsafe fn byte_is_allowed(byte: u8) -> bool {
|
||||
let slice = [
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', byte, b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
|
||||
parse_uri_batch_32(&mut bytes);
|
||||
|
||||
match bytes.pos() {
|
||||
32 => true,
|
||||
26 => false,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
+70
-24
@@ -38,6 +38,38 @@ mod sse42;
|
||||
))]
|
||||
mod avx2;
|
||||
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub const SSE_42: usize = 1;
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(not(httparse_simd_target_feature_sse42), httparse_simd_target_feature_avx2),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub const AVX_2: usize = 2;
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
any(
|
||||
not(httparse_simd_target_feature_sse42),
|
||||
httparse_simd_target_feature_avx2,
|
||||
test,
|
||||
),
|
||||
any(
|
||||
target_arch = "x86",
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
))]
|
||||
pub const AVX_2_AND_SSE_42: usize = 3;
|
||||
#[cfg(httparse_simd)]
|
||||
const NONE: usize = ::core::usize::MAX;
|
||||
#[cfg(all(
|
||||
httparse_simd,
|
||||
not(any(
|
||||
@@ -62,27 +94,23 @@ mod runtime {
|
||||
static FEATURE: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
const INIT: usize = 0;
|
||||
const SSE_42: usize = 1;
|
||||
const AVX_2: usize = 2;
|
||||
const AVX_2_AND_SSE_42: usize = 3;
|
||||
const NONE: usize = ::core::usize::MAX;
|
||||
|
||||
fn detect() -> usize {
|
||||
pub fn detect() -> usize {
|
||||
let feat = FEATURE.load(Ordering::Relaxed);
|
||||
if feat == INIT {
|
||||
if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") {
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
FEATURE.store(AVX_2_AND_SSE_42, Ordering::Relaxed);
|
||||
return AVX_2_AND_SSE_42;
|
||||
FEATURE.store(super::AVX_2_AND_SSE_42, Ordering::Relaxed);
|
||||
return super::AVX_2_AND_SSE_42;
|
||||
} else {
|
||||
FEATURE.store(AVX_2, Ordering::Relaxed);
|
||||
return AVX_2;
|
||||
FEATURE.store(super::AVX_2, Ordering::Relaxed);
|
||||
return super::AVX_2;
|
||||
}
|
||||
} else if is_x86_feature_detected!("sse4.2") {
|
||||
FEATURE.store(SSE_42, Ordering::Relaxed);
|
||||
return SSE_42;
|
||||
FEATURE.store(super::SSE_42, Ordering::Relaxed);
|
||||
return super::SSE_42;
|
||||
} else {
|
||||
FEATURE.store(NONE, Ordering::Relaxed);
|
||||
FEATURE.store(super::NONE, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
feat
|
||||
@@ -91,9 +119,9 @@ mod runtime {
|
||||
pub fn match_uri_vectored(bytes: &mut ::Bytes) {
|
||||
unsafe {
|
||||
match detect() {
|
||||
SSE_42 => super::sse42::parse_uri_batch_16(bytes),
|
||||
AVX_2 => { super::avx2::parse_uri_batch_32(bytes); },
|
||||
AVX_2_AND_SSE_42 => {
|
||||
super::SSE_42 => super::sse42::parse_uri_batch_16(bytes),
|
||||
super::AVX_2 => { super::avx2::parse_uri_batch_32(bytes); },
|
||||
super::AVX_2_AND_SSE_42 => {
|
||||
if let super::avx2::Scan::Found = super::avx2::parse_uri_batch_32(bytes) {
|
||||
return;
|
||||
}
|
||||
@@ -109,9 +137,9 @@ mod runtime {
|
||||
pub fn match_header_value_vectored(bytes: &mut ::Bytes) {
|
||||
unsafe {
|
||||
match detect() {
|
||||
SSE_42 => super::sse42::match_header_value_batch_16(bytes),
|
||||
AVX_2 => { super::avx2::match_header_value_batch_32(bytes); },
|
||||
AVX_2_AND_SSE_42 => {
|
||||
super::SSE_42 => super::sse42::match_header_value_batch_16(bytes),
|
||||
super::AVX_2 => { super::avx2::match_header_value_batch_32(bytes); },
|
||||
super::AVX_2_AND_SSE_42 => {
|
||||
if let super::avx2::Scan::Found = super::avx2::match_header_value_batch_32(bytes) {
|
||||
return;
|
||||
}
|
||||
@@ -149,7 +177,7 @@ pub use self::runtime::*;
|
||||
))]
|
||||
mod sse42_compile_time {
|
||||
pub fn match_uri_vectored(bytes: &mut ::Bytes) {
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::parse_uri_batch_16(bytes);
|
||||
}
|
||||
@@ -159,7 +187,7 @@ mod sse42_compile_time {
|
||||
}
|
||||
|
||||
pub fn match_header_value_vectored(bytes: &mut ::Bytes) {
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::match_header_value_batch_16(bytes);
|
||||
}
|
||||
@@ -167,6 +195,14 @@ mod sse42_compile_time {
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn detect() -> usize {
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
super::SSE_42
|
||||
} else {
|
||||
super::NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
@@ -191,13 +227,13 @@ pub use self::sse42_compile_time::*;
|
||||
mod avx2_compile_time {
|
||||
pub fn match_uri_vectored(bytes: &mut ::Bytes) {
|
||||
// do both, since avx2 only works when bytes.len() >= 32
|
||||
if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") {
|
||||
if detect() == super::AVX_2_AND_SSE_42 {
|
||||
unsafe {
|
||||
super::avx2::parse_uri_batch_32(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::parse_uri_batch_16(bytes);
|
||||
}
|
||||
@@ -208,7 +244,7 @@ mod avx2_compile_time {
|
||||
|
||||
pub fn match_header_value_vectored(bytes: &mut ::Bytes) {
|
||||
// do both, since avx2 only works when bytes.len() >= 32
|
||||
if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") {
|
||||
if detect() == super::AVX_2_AND_SSE_42 {
|
||||
let scanned = unsafe {
|
||||
super::avx2::match_header_value_batch_32(bytes)
|
||||
};
|
||||
@@ -217,7 +253,7 @@ mod avx2_compile_time {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if is_x86_feature_detected!("sse4.2") {
|
||||
if detect() == super::SSE_42 {
|
||||
unsafe {
|
||||
super::sse42::match_header_value_batch_16(bytes);
|
||||
}
|
||||
@@ -225,6 +261,16 @@ mod avx2_compile_time {
|
||||
|
||||
// else do nothing
|
||||
}
|
||||
|
||||
pub fn detect() -> usize {
|
||||
if cfg!(target_arch = "x86_64") && is_x86_feature_detected!("avx2") {
|
||||
super::AVX_2_AND_SSE_42
|
||||
} else if is_x86_feature_detected!("sse4.2") {
|
||||
super::SSE_42
|
||||
} else {
|
||||
super::NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
|
||||
@@ -97,3 +97,41 @@ unsafe fn match_header_value_char_16_sse(buf: &[u8]) -> usize {
|
||||
|
||||
_tzcnt_u32(res) as usize
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sse_code_matches_uri_chars_table() {
|
||||
match super::detect() {
|
||||
super::SSE_42 | super::AVX_2_AND_SSE_42 => {},
|
||||
_ => return,
|
||||
}
|
||||
|
||||
unsafe {
|
||||
assert!(byte_is_allowed(b'_'));
|
||||
|
||||
for (b, allowed) in ::URI_MAP.iter().cloned().enumerate() {
|
||||
assert_eq!(
|
||||
byte_is_allowed(b as u8), allowed,
|
||||
"byte_is_allowed({:?}) should be {:?}", b, allowed,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
unsafe fn byte_is_allowed(byte: u8) -> bool {
|
||||
let slice = [
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
b'_', b'_', byte, b'_',
|
||||
b'_', b'_', b'_', b'_',
|
||||
];
|
||||
let mut bytes = Bytes::new(&slice);
|
||||
|
||||
parse_uri_batch_16(&mut bytes);
|
||||
|
||||
match bytes.pos() {
|
||||
16 => true,
|
||||
10 => false,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user