Created
January 13, 2018 11:24
-
-
Save laruence/ddc916122cbf26faffeace0942a71d71 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/standard/string.c b/ext/standard/string.c | |
index 97a20fb..d6b039f 100644 | |
--- a/ext/standard/string.c | |
+++ b/ext/standard/string.c | |
@@ -34,6 +34,12 @@ | |
#ifdef HAVE_MONETARY_H | |
# include <monetary.h> | |
#endif | |
+ | |
+#ifdef __SSE4_2__ | |
+#include <nmmintrin.h> | |
+#include "Zend/zend_bitset.h" | |
+#endif | |
+ | |
/* | |
* This define is here because some versions of libintl redefine setlocale | |
* to point to libintl_setlocale. That's a ridiculous thing to do as far | |
@@ -3872,6 +3878,11 @@ PHPAPI zend_string *php_addslashes(zend_string *str, int should_free) | |
char *end; | |
size_t offset; | |
zend_string *new_str; | |
+#ifdef __SSE4_2__ | |
+ uint32_t r = 0; | |
+ static const char ctrs[16] = "\'\"\\\0"; | |
+ __m128i w, s; | |
+#endif | |
if (!str) { | |
return ZSTR_EMPTY_ALLOC(); | |
@@ -3880,6 +3891,37 @@ PHPAPI zend_string *php_addslashes(zend_string *str, int should_free) | |
source = ZSTR_VAL(str); | |
end = source + ZSTR_LEN(str); | |
+#ifdef __SSE4_2__ | |
+ if (ZSTR_LEN(str) > 15) { | |
+ char *align = (char*)(((uintptr_t)source + 15) & ~15); | |
+ w = _mm_load_si128((__m128i *)&ctrs[0]); | |
+ | |
+ if (UNEXPECTED(source != align)) { | |
+ do { | |
+ switch (*source) { | |
+ case '\0': | |
+ case '\'': | |
+ case '\"': | |
+ case '\\': | |
+ goto do_escape; | |
+ default: | |
+ source++; | |
+ break; | |
+ } | |
+ } while (source < align); | |
+ } | |
+ | |
+ for (;end - source > 15; source += 16) { | |
+ s = _mm_load_si128((__m128i *)source); | |
+ int r = _mm_cvtsi128_si32( | |
+ _mm_cmpestrm(w, 4, s, 16, _SIDD_UBYTE_OPS|_SIDD_CMP_EQUAL_ANY|_SIDD_BIT_MASK)); | |
+ if (r) { | |
+ goto do_escape; | |
+ } | |
+ } | |
+ } | |
+#endif | |
+ | |
while (source < end) { | |
switch (*source) { | |
case '\0': | |
@@ -3905,6 +3947,79 @@ do_escape: | |
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset); | |
target = ZSTR_VAL(new_str) + offset; | |
+#ifdef __SSE4_2__ | |
+ if (r) { | |
+ int pos = 0; | |
+ do { | |
+ int i, n = zend_ulong_ntz(r); | |
+ for (i = 0; i < n; i++) { | |
+ *target++ = source[pos + i]; | |
+ } | |
+ pos += n; | |
+ *target++ = '\\'; | |
+ if (source[pos] == '\0') { | |
+ *target++ = '0'; | |
+ } else { | |
+ *target++ = source[pos]; | |
+ } | |
+ pos++; | |
+ r = r >> (n + 1); | |
+ } while (r); | |
+ | |
+ for (; pos < 16; pos++) { | |
+ *target++ = source[pos]; | |
+ } | |
+ } else if (end - source > 15) { | |
+ char *align = (char*)(((zend_uintptr_t)source + 15) & ~15); | |
+ w = _mm_load_si128((__m128i *)&ctrs[0]); | |
+ | |
+ if (source != align) { | |
+ do { | |
+ switch (*source) { | |
+ case '\0': | |
+ *target++ = '\\'; | |
+ *target++ = '0'; | |
+ break; | |
+ case '\'': | |
+ case '\"': | |
+ case '\\': | |
+ *target++ = '\\'; | |
+ /* break is missing *intentionally* */ | |
+ default: | |
+ *target++ = *source; | |
+ break; | |
+ } | |
+ source++; | |
+ } while (source < align); | |
+ } | |
+ } | |
+ | |
+ for (; end - source > 15; source += 16) { | |
+ s = _mm_load_si128((__m128i *)source); | |
+ int r = _mm_cvtsi128_si32( | |
+ _mm_cmpestrm(w, 4, s, 16, _SIDD_UBYTE_OPS|_SIDD_CMP_EQUAL_ANY|_SIDD_BIT_MASK)); | |
+ int pos = 0; | |
+ while (r) { | |
+ int i, n = zend_ulong_ntz(r); | |
+ r = r >> (n + 1); | |
+ for (i = 0; i < n; i++) { | |
+ *target++ = source[pos + i]; | |
+ } | |
+ pos += n; | |
+ *target++ = '\\'; | |
+ if (source[pos] == '\0') { | |
+ *target++ = '0'; | |
+ } else { | |
+ *target++ = source[pos]; | |
+ } | |
+ pos++; | |
+ } | |
+ for (; pos < 16; pos++) { | |
+ *target++ = source[pos]; | |
+ } | |
+ } | |
+ | |
+#endif | |
while (source < end) { | |
switch (*source) { | |
case '\0': | |
@@ -3920,11 +4035,10 @@ do_escape: | |
*target++ = *source; | |
break; | |
} | |
- | |
source++; | |
} | |
- *target = 0; | |
+ *target = '\0'; | |
if (should_free) { | |
zend_string_release(str); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment