@@ -379,7 +379,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
379379/* }}} */
380380
381381/* Specialization of smart_str_appendl() to avoid performance loss due to code bloat */
382- static zend_always_inline void php_json_append (smart_str * dest , const char * src , size_t len )
382+ static void php_json_append (smart_str * dest , const char * src , size_t len )
383383{
384384 /* smart_str has a minimum size of the input length,
385385 * this avoids generating initial allocation code */
@@ -542,7 +542,12 @@ typedef enum php_json_simd_result {
542542} php_json_simd_result ;
543543
544544static zend_always_inline php_json_simd_result php_json_process_simd_block (
545- smart_str * buf , const __m128i sse_escape_mask , const char * * s , size_t * pos , size_t * len , int options
545+ smart_str * buf ,
546+ const __m128i sse_escape_mask ,
547+ const char * * s ,
548+ size_t * restrict pos ,
549+ size_t * restrict len ,
550+ int options
546551)
547552{
548553 while (* len >= sizeof (__m128i )) {
@@ -584,20 +589,24 @@ static zend_always_inline php_json_simd_result php_json_process_simd_block(
584589 /* Note that we shift the input forward, so we have to shift the mask as well,
585590 * beyond the to-be-escaped character */
586591 int len = zend_ulong_ntz (mask );
587- mask >>= len + 1 ;
592+ mask >>= len ;
588593
589594 php_json_append (buf , * s , len );
590595
591- unsigned char us = (unsigned char )(* s )[len ];
592- * s += len + 1 ; /* skip 'us' too */
596+ * s += len ; /* skip 'us' too */
593597
594- bool handled = php_json_printable_ascii_escape (buf , us , options );
595- ZEND_ASSERT (handled == true);
598+ /* Mitigate long run performance */
599+ do {
600+ unsigned char us = (unsigned char )(* s )[0 ];
601+ (* s )++ ;
602+ bool handled = php_json_printable_ascii_escape (buf , us , options );
603+ ZEND_ASSERT (handled == true);
604+ } while ((mask >>= 1 ) & 1 );
596605 } while (mask != 0 );
597606
598607 * pos = sizeof (__m128i ) - (* s - s_backup );
599608 } else {
600- if (UNEXPECTED (max_shift < sizeof (__m128i ))) {
609+ if (/* UNEXPECTED*/ (max_shift < sizeof (__m128i ))) {
601610 * pos += max_shift ;
602611 * len -= max_shift ;
603612 return PHP_JSON_SLOW ;
@@ -608,7 +617,7 @@ static zend_always_inline php_json_simd_result php_json_process_simd_block(
608617 * len -= sizeof (__m128i );
609618 }
610619
611- return !* len ? PHP_JSON_STOP : PHP_JSON_SLOW ;
620+ return UNEXPECTED ( !* len ) ? PHP_JSON_STOP : PHP_JSON_SLOW ;
612621}
613622#endif
614623
@@ -660,8 +669,9 @@ zend_result php_json_escape_string(
660669 0xffffffff , 0x500080c4 , 0x10000000 , 0x00000000 ,
661670 0xffffffff , 0xffffffff , 0xffffffff , 0xffffffff };
662671
672+ php_json_simd_result result = PHP_JSON_SLOW ;
663673#ifdef JSON_USE_SIMD
664- php_json_simd_result result = php_json_process_simd_block (buf , sse_escape_mask , & s , & pos , & len , options );
674+ result = php_json_process_simd_block (buf , sse_escape_mask , & s , & pos , & len , options );
665675 if (UNEXPECTED (result == PHP_JSON_STOP )) {
666676 break ;
667677 }
@@ -721,6 +731,8 @@ zend_result php_json_escape_string(
721731 s += pos ;
722732 pos = 0 ;
723733
734+ ZEND_ASSERT (buf -> s );
735+
724736 /* From http://en.wikipedia.org/wiki/UTF16 */
725737 if (us >= 0x10000 ) {
726738 unsigned int next_us ;
0 commit comments