perf: Do not compile runtime feature detection on avx2

This feature detection may avoid inlining avx2::escape function
This commit is contained in:
Kogia-sima 2020-12-24 15:05:11 +09:00
parent 54f77cc25a
commit dca8048bd0
1 changed files with 56 additions and 46 deletions

View File

@ -2,8 +2,21 @@
//! //!
//! By default sailfish replaces the characters `&"'<>` with the equivalent html. //! By default sailfish replaces the characters `&"'<>` with the equivalent html.
#![cfg_attr(
all(
any(target_arch = "x86", target_arch = "x86_64"),
not(miri),
target_feature = "avx2"
),
allow(dead_code)
)]
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri)))]
mod avx2;
mod fallback; mod fallback;
mod naive; mod naive;
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri)))]
mod sse2;
static ESCAPE_LUT: [u8; 256] = [ static ESCAPE_LUT: [u8; 256] = [
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@ -21,20 +34,20 @@ static ESCAPE_LUT: [u8; 256] = [
const ESCAPED: [&str; 5] = ["&quot;", "&amp;", "&#039;", "&lt;", "&gt;"]; const ESCAPED: [&str; 5] = ["&quot;", "&amp;", "&#039;", "&lt;", "&gt;"];
const ESCAPED_LEN: usize = 5; const ESCAPED_LEN: usize = 5;
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri)))] use super::buffer::Buffer;
macro_rules! generate_impl {
() => {
mod avx2;
mod sse2;
use super::buffer::Buffer; /// write the escaped contents into `Buffer`
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri)))]
#[cfg_attr(feature = "perf-inline", inline)]
pub fn escape_to_buf(feed: &str, buf: &mut Buffer) {
#[cfg(not(target_feature = "avx2"))]
{
use std::sync::atomic::{AtomicPtr, Ordering}; use std::sync::atomic::{AtomicPtr, Ordering};
type FnRaw = *mut (); type FnRaw = *mut ();
static FN: AtomicPtr<()> = AtomicPtr::new(detect as FnRaw);
static FN: AtomicPtr<()> = AtomicPtr::new(escape as FnRaw); fn detect(feed: &str, buf: &mut Buffer) {
fn escape(feed: &str, buf: &mut Buffer) {
debug_assert!(feed.len() >= 16); debug_assert!(feed.len() >= 16);
let fun = if is_x86_feature_detected!("avx2") { let fun = if is_x86_feature_detected!("avx2") {
avx2::escape avx2::escape
@ -48,51 +61,48 @@ macro_rules! generate_impl {
unsafe { fun(feed, buf) }; unsafe { fun(feed, buf) };
} }
/// write the escaped contents into `Buffer` unsafe {
#[cfg_attr(feature = "perf-inline", inline)] if feed.len() < 16 {
pub fn escape_to_buf(feed: &str, buf: &mut Buffer) { buf.reserve_small(feed.len() * 6);
unsafe { let l = naive::escape_small(feed, buf.as_mut_ptr().add(buf.len()));
if feed.len() < 16 { buf.advance(l);
buf.reserve_small(feed.len() * 6); } else {
let l = naive::escape_small(feed, buf.as_mut_ptr().add(buf.len())); let fun = FN.load(Ordering::Relaxed);
buf.advance(l); std::mem::transmute::<FnRaw, fn(&str, &mut Buffer)>(fun)(feed, buf);
} else if cfg!(target_feature = "avx2") {
avx2::escape(feed, buf);
} else {
let fun = FN.load(Ordering::Relaxed);
std::mem::transmute::<FnRaw, fn(&str, &mut Buffer)>(fun)(feed, buf);
}
} }
} }
}; }
#[cfg(target_feature = "avx2")]
unsafe {
if feed.len() < 16 {
buf.reserve_small(feed.len() * 6);
let l = naive::escape_small(feed, buf.as_mut_ptr().add(buf.len()));
buf.advance(l);
} else if cfg!(target_feature = "avx2") {
avx2::escape(feed, buf);
}
}
} }
/// write the escaped contents into `Buffer`
#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri))))] #[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri))))]
macro_rules! generate_impl { #[cfg_attr(feature = "perf-inline", inline)]
() => { pub fn escape_to_buf(feed: &str, buf: &mut Buffer) {
use super::buffer::Buffer; unsafe {
if cfg!(miri) {
/// write the escaped contents into `Buffer` let bp = feed.as_ptr();
#[cfg_attr(feature = "perf-inline", inline)] naive::escape(buf, bp, bp, bp.add(feed.len()))
pub fn escape_to_buf(feed: &str, buf: &mut Buffer) { } else if feed.len() < 16 {
unsafe { buf.reserve_small(feed.len() * 6);
if cfg!(miri) { let l = naive::escape_small(feed, buf.as_mut_ptr().add(buf.len()));
let bp = feed.as_ptr(); buf.advance(l);
naive::escape(buf, bp, bp, bp.add(feed.len())) } else {
} else if feed.len() < 16 { fallback::escape(feed, buf)
buf.reserve_small(feed.len() * 6);
let l = naive::escape_small(feed, buf.as_mut_ptr().add(buf.len()));
buf.advance(l);
} else {
fallback::escape(feed, buf)
}
}
} }
}; }
} }
generate_impl!();
/// write the escaped contents into `String` /// write the escaped contents into `String`
/// ///
/// # Examples /// # Examples