From: Xinchen Hui Date: Wed, 21 Feb 2018 02:09:11 +0000 (+0800) Subject: Optimized php_stripslash with SSSE3 instr X-Git-Tag: php-7.3.0alpha1~324 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=91635b011bdf958e07290a1f3f4030d997d76d53;p=php Optimized php_stripslash with SSSE3 instr --- diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index 6e3642c4ac..526ccbb90b 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -130,11 +130,12 @@ PHPAPI zend_string *php_string_tolower(zend_string *s); PHPAPI char *php_strtr(char *str, size_t len, const char *str_from, const char *str_to, size_t trlen); #if ZEND_INTRIN_SSE4_2_FUNC_PTR PHPAPI extern zend_string *(*php_addslashes)(zend_string *str, int should_free); +PHPAPI void (*php_stripslashes)(zend_string *str); #else PHPAPI zend_string *php_addslashes(zend_string *str, int should_free); +PHPAPI void php_stripslashes(zend_string *str); #endif PHPAPI zend_string *php_addcslashes(zend_string *str, int freeit, char *what, size_t what_len); -PHPAPI void php_stripslashes(zend_string *str); PHPAPI void php_stripcslashes(zend_string *str); PHPAPI zend_string *php_basename(const char *s, size_t len, char *suffix, size_t sufflen); PHPAPI size_t php_dirname(char *str, size_t len); diff --git a/ext/standard/string.c b/ext/standard/string.c index c3af4050c2..e45309af53 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3639,43 +3639,6 @@ PHP_FUNCTION(similar_text) } /* }}} */ -/* {{{ php_stripslashes - * - * be careful, this edits the string in-place */ -PHPAPI void php_stripslashes(zend_string *str) -{ - char *s, *t; - size_t l; - - s = ZSTR_VAL(str); - t = ZSTR_VAL(str); - l = ZSTR_LEN(str); - - while (l > 0) { - if (*t == '\\') { - t++; /* skip the slash */ - ZSTR_LEN(str)--; - l--; - if (l > 0) { - if (*t == '0') { - *s++='\0'; - t++; - } else { - *s++ = *t++; /* preserve the next character */ - } - l--; - } - } else { - *s++ = *t++; - l--; - } - } - if (s != t) { - *s = '\0'; - } -} -/* }}} */ - /* {{{ proto string addcslashes(string str, string charlist) Escapes all chars mentioned in charlist with backslash. It creates octal representations if asked to backslash characters with 8th bit set or with ASCII<32 (except '\n', '\r', '\t' etc...) */ PHP_FUNCTION(addcslashes) @@ -3887,8 +3850,12 @@ PHPAPI zend_string *php_addcslashes(zend_string *str, int should_free, char *wha ZEND_INTRIN_SSE4_2_FUNC_DECL(zend_string *php_addslashes_sse42(zend_string *str, int should_free)); zend_string *php_addslashes_default(zend_string *str, int should_free); +ZEND_INTRIN_SSE4_2_FUNC_DECL(void php_stripslashes_sse42(zend_string *str)); +void php_stripslashes_default(zend_string *str); + # if ZEND_INTRIN_SSE4_2_FUNC_PROTO PHPAPI zend_string *php_addslashes(zend_string *str, int should_free) __attribute__((ifunc("resolve_addslashes"))); +PHPAPI void php_stripslashes(zend_string *str) __attribute__((ifunc("resolve_stripslashes"))); static void *resolve_addslashes() { if (zend_cpu_supports_sse42()) { @@ -3896,9 +3863,17 @@ static void *resolve_addslashes() { } return php_addslashes_default; } + +static void *resolve_stripslashes() { + if (zend_cpu_supports_sse42()) { + return php_stripslashes_sse42; + } + return php_stripslashes_default; +} # else /* ZEND_INTRIN_SSE4_2_FUNC_PTR */ PHPAPI zend_string *(*php_addslashes)(zend_string *str, int should_free) = NULL; +PHPAPI void (*php_stripslashes)(zend_string *str) = NULL; /* {{{ PHP_MINIT_FUNCTION */ @@ -3906,8 +3881,10 @@ PHP_MINIT_FUNCTION(string_intrin) { if (zend_cpu_supports(ZEND_CPU_FEATURE_SSE42)) { php_addslashes = php_addslashes_sse42; + php_stripslashes = php_stripslashes_sse42; } else { php_addslashes = php_addslashes_default; + php_stripslashes = php_stripslashes_default; } return SUCCESS; } @@ -4144,6 +4121,108 @@ do_escape: /* }}} */ /* }}} */ +/* {{{ php_stripslashes + * + * be careful, this edits the string in-place */ +static zend_always_inline char *php_stripslashes_impl(const char *str, char *out, size_t len) +{ + while (len > 0) { + if (*str == '\\') { + str++; /* skip the slash */ + len--; + if (len > 0) { + if (*str == '0') { + *out++='\0'; + str++; + } else { + *out++ = *str++; /* preserve the next character */ + } + len--; + } + } else { + *out++ = *str++; + len--; + } + } + + return out; +} + +#if ZEND_INTRIN_SSE4_2_NATIVE || ZEND_INTRIN_SSE4_2_RESOLVER +# if ZEND_INTRIN_SSE4_2_NATIVE +PHPAPI void php_stripslashes(zend_string *str) +# elif ZEND_INTRIN_SSE4_2_RESOLVER +PHPAPI void php_stripslashes_sse42(zend_string *str) +# endif +{ + const char *s = ZSTR_VAL(str); + char *t = ZSTR_VAL(str); + size_t l = ZSTR_LEN(str); + + if (l > 15) { + const __m128i slash = _mm_set1_epi8('\\'); + + do { + __m128i in = _mm_loadu_si128((__m128i *)s); + __m128i any_slash = _mm_cmpeq_epi8(in, slash); + uint32_t res = _mm_movemask_epi8(any_slash); + + if (res) { + int i, n = zend_ulong_ntz(res); + const char *e = s + 15; + l -= n; + for (i = 0; i < n; i++) { + *t++ = *s++; + } + for (; s < e; s++) { + if (*s == '\\') { + s++; + l--; + if (*s == '0') { + *t = '\0'; + } else { + *t = *s; + } + } else { + *t = *s; + } + t++; + l--; + } + } else { + _mm_storeu_si128((__m128i *)t, in); + s += 16; + t += 16; + l -= 16; + } + } while (l > 15); + } + + t = php_stripslashes_impl(s, t, l); + if (t != (ZSTR_VAL(str) + ZSTR_LEN(str))) { + ZSTR_LEN(str) = t - ZSTR_VAL(str); + ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0'; + } +} +#endif + +#if !ZEND_INTRIN_SSE4_2_NATIVE +# if ZEND_INTRIN_SSE4_2_RESOLVER +void php_stripslashes_default(zend_string *str) /* {{{ */ +# else +PHPAPI void php_stripslashes(zend_string *str) +# endif +{ + char *t = php_stripslashes_impl(ZSTR_VAL(str), ZSTR_VAL(str), ZSTR_LEN(str)); + if (t != (ZSTR_VAL(str) + ZSTR_LEN(str))) { + ZSTR_LEN(str) = t - ZSTR_VAL(str); + ZSTR_VAL(str)[ZSTR_LEN(str)] = '\0'; + } +} +/* }}} */ +#endif +/* }}} */ + #define _HEB_BLOCK_TYPE_ENG 1 #define _HEB_BLOCK_TYPE_HEB 2 #define isheb(c) (((((unsigned char) c) >= 224) && (((unsigned char) c) <= 250)) ? 1 : 0)