mirror of
https://github.com/php/php-src.git
synced 2026-03-30 04:02:19 +02:00
Merge branch 'PHP-7.4'
* PHP-7.4: vectorize string-escape with NEON
This commit is contained in:
@@ -3910,6 +3910,44 @@ do_escape:
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
#ifdef __aarch64__
|
||||
typedef union {
|
||||
uint8_t mem[16];
|
||||
uint64_t dw[2];
|
||||
} quad_word;
|
||||
|
||||
static zend_always_inline quad_word aarch64_contains_slash_chars(uint8x16_t x) {
|
||||
uint8x16_t s0 = vceqq_u8(x, vdupq_n_u8('\0'));
|
||||
uint8x16_t s1 = vceqq_u8(x, vdupq_n_u8('\''));
|
||||
uint8x16_t s2 = vceqq_u8(x, vdupq_n_u8('\"'));
|
||||
uint8x16_t s3 = vceqq_u8(x, vdupq_n_u8('\\'));
|
||||
uint8x16_t s01 = vorrq_u8(s0, s1);
|
||||
uint8x16_t s23 = vorrq_u8(s2, s3);
|
||||
uint8x16_t s0123 = vorrq_u8(s01, s23);
|
||||
quad_word qw;
|
||||
vst1q_u8(qw.mem, s0123);
|
||||
return qw;
|
||||
}
|
||||
|
||||
static zend_always_inline char *aarch64_add_slashes(quad_word res, const char *source, char *target)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < 16; i++) {
|
||||
char s = source[i];
|
||||
if (res.mem[i] == 0)
|
||||
*target++ = s;
|
||||
else {
|
||||
*target++ = '\\';
|
||||
if (s == '\0')
|
||||
*target++ = '0';
|
||||
else
|
||||
*target++ = s;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
#endif /* __aarch64__ */
|
||||
|
||||
#if !ZEND_INTRIN_SSE4_2_NATIVE
|
||||
# if ZEND_INTRIN_SSE4_2_RESOLVER
|
||||
zend_string *php_addslashes_default(zend_string *str) /* {{{ */
|
||||
@@ -3930,6 +3968,19 @@ PHPAPI zend_string *php_addslashes(zend_string *str)
|
||||
source = ZSTR_VAL(str);
|
||||
end = source + ZSTR_LEN(str);
|
||||
|
||||
# ifdef __aarch64__
|
||||
quad_word res = {0};
|
||||
if (ZSTR_LEN(str) > 15) {
|
||||
do {
|
||||
res = aarch64_contains_slash_chars(vld1q_u8((uint8_t *)source));
|
||||
if (res.dw[0] | res.dw[1])
|
||||
goto do_escape;
|
||||
source += 16;
|
||||
} while ((end - source) > 15);
|
||||
}
|
||||
/* Finish the last 15 bytes or less with the scalar loop. */
|
||||
# endif /* __aarch64__ */
|
||||
|
||||
while (source < end) {
|
||||
switch (*source) {
|
||||
case '\0':
|
||||
@@ -3951,6 +4002,24 @@ do_escape:
|
||||
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
|
||||
target = ZSTR_VAL(new_str) + offset;
|
||||
|
||||
# ifdef __aarch64__
|
||||
if (res.dw[0] | res.dw[1]) {
|
||||
target = aarch64_add_slashes(res, source, target);
|
||||
source += 16;
|
||||
}
|
||||
for (; end - source > 15; source += 16) {
|
||||
uint8x16_t x = vld1q_u8((uint8_t *)source);
|
||||
res = aarch64_contains_slash_chars(x);
|
||||
if (res.dw[0] | res.dw[1]) {
|
||||
target = aarch64_add_slashes(res, source, target);
|
||||
} else {
|
||||
vst1q_u8((uint8_t*)target, x);
|
||||
target += 16;
|
||||
}
|
||||
}
|
||||
/* Finish the last 15 bytes or less with the scalar loop. */
|
||||
# endif /* __aarch64__ */
|
||||
|
||||
while (source < end) {
|
||||
switch (*source) {
|
||||
case '\0':
|
||||
@@ -3988,6 +4057,37 @@ do_escape:
|
||||
* be careful, this edits the string in-place */
|
||||
static zend_always_inline char *php_stripslashes_impl(const char *str, char *out, size_t len)
|
||||
{
|
||||
#ifdef __aarch64__
|
||||
while (len > 15) {
|
||||
uint8x16_t x = vld1q_u8((uint8_t *)str);
|
||||
quad_word q;
|
||||
vst1q_u8(q.mem, vceqq_u8(x, vdupq_n_u8('\\')));
|
||||
if (q.dw[0] | q.dw[1]) {
|
||||
int i = 0;
|
||||
for (; i < 16; i++) {
|
||||
if (q.mem[i] == 0) {
|
||||
*out++ = str[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
i++; /* skip the slash */
|
||||
char s = str[i];
|
||||
if (s == '0')
|
||||
*out++ = '\0';
|
||||
else
|
||||
*out++ = s; /* preserve the next character */
|
||||
}
|
||||
str += i;
|
||||
len -= i;
|
||||
} else {
|
||||
vst1q_u8((uint8_t*)out, x);
|
||||
out += 16;
|
||||
str += 16;
|
||||
len -= 16;
|
||||
}
|
||||
}
|
||||
/* Finish the last 15 bytes or less with the scalar loop. */
|
||||
#endif /* __aarch64__ */
|
||||
while (len > 0) {
|
||||
if (*str == '\\') {
|
||||
str++; /* skip the slash */
|
||||
|
||||
Reference in New Issue
Block a user