Skip to content

Commit ef72f33

Browse files
committed
Reduce overhead of worst case to 1.5x
1 parent 2b11554 commit ef72f33

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

ext/json/json_encoder.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ zend_result php_json_escape_string(
520520
#ifdef __SSE2__
521521
while (len >= sizeof(__m128i)) {
522522
const __m128i input = _mm_loadu_si128((__m128i *) (s + pos));
523+
/* signed compare, so checks for unsigned ASCII >= 0x80 as well */
523524
const __m128i input_range = _mm_cmplt_epi8(input, _mm_set1_epi8(32));
524525

525526
int max_shift = 16;
@@ -559,25 +560,26 @@ zend_result php_json_escape_string(
559560
len -= MIN(max_shift, shift);
560561
break;
561562
}
563+
562564
int shift = zend_ulong_nlz(mask) - 16 - (SIZEOF_ZEND_LONG == 8 ? 32 : 0); /* skips over everything */
565+
smart_str_appendl(buf, s, pos);
566+
s += pos;
567+
pos = shift;
568+
563569
do {
564570
/* Note that we shift the input forward, so we have to shift the mask as well,
565571
* beyond the to-be-escaped character */
566572
int len = zend_ulong_ntz(mask);
567573
mask >>= len + 1;
568574

569-
smart_str_appendl(buf, s, len + pos);
575+
smart_str_appendl(buf, s, len);
570576

571-
pos += len;
572-
us = (unsigned char)s[pos];
573-
s += pos + 1; /* skip 'us' too */
574-
pos = 0;
577+
us = (unsigned char)s[len];
578+
s += len + 1; /* skip 'us' too */
575579

576580
bool handled = php_json_printable_ascii_escape(buf, us, options);
577581
ZEND_ASSERT(handled == true);
578582
} while (mask != 0);
579-
580-
pos += shift;
581583
} else {
582584
if (max_shift < 16) {
583585
pos += max_shift;

0 commit comments

Comments
 (0)