Skip to content

Commit 55a0b0e

Browse files
committed
dynamic mask
1 parent 6a01058 commit 55a0b0e

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

ext/json/json_encoder.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,20 @@ static zend_always_inline bool php_json_printable_ascii_escape(smart_str *buf, u
432432
return true;
433433
}
434434

435+
#ifdef __SSE2__
436+
// TODO: may be unused
437+
static zend_always_inline __m128i php_json_create_sse_escape_mask(int options)
438+
{
439+
const char sentinel = 1; /* outside of the printable range, so no false matches are possible */
440+
const char amp = (options & PHP_JSON_HEX_AMP) ? '&' : sentinel;
441+
const char apos = (options & PHP_JSON_HEX_APOS) ? '\'' : sentinel;
442+
const char slash = !(options & PHP_JSON_UNESCAPED_SLASHES) ? '/' : sentinel;
443+
const char tag1 = (options & PHP_JSON_HEX_TAG) ? '<' : sentinel;
444+
const char tag2 = (options & PHP_JSON_HEX_TAG) ? '>' : sentinel;
445+
return _mm_setr_epi8('"', amp, apos, slash, tag1, tag2, '\\', 0, 0, 0, 0, 0, 0, 0, 0, 0);
446+
}
447+
#endif
448+
435449
zend_result php_json_escape_string(
436450
smart_str *buf, const char *s, size_t len,
437451
int options, php_json_encoder *encoder) /* {{{ */
@@ -469,6 +483,11 @@ zend_result php_json_escape_string(
469483

470484
pos = 0;
471485

486+
#ifdef __SSE2__
487+
const __m128i sse_escape_mask = php_json_create_sse_escape_mask(options);
488+
(void) sse_escape_mask;
489+
#endif
490+
472491
do {
473492
static const uint32_t charmap[8] = {
474493
0xffffffff, 0x500080c4, 0x10000000, 0x00000000,
@@ -487,7 +506,7 @@ zend_result php_json_escape_string(
487506
break;
488507
}
489508

490-
#if 1
509+
#if 0
491510
const __m128i result_34 = _mm_cmpeq_epi8(input, _mm_set1_epi8('"'));
492511
const __m128i result_38 = _mm_cmpeq_epi8(input, _mm_set1_epi8('&'));
493512
const __m128i result_39 = _mm_cmpeq_epi8(input, _mm_set1_epi8('\''));
@@ -506,7 +525,7 @@ zend_result php_json_escape_string(
506525
const __m128i result_individual_bytes = _mm_or_si128(result_34_38_39_47, result_60_62_92);
507526
int mask = _mm_movemask_epi8(result_individual_bytes);
508527
#else
509-
const __m128i result_individual_bytes = _mm_cmpistrm(_mm_setr_epi8('"', '&', '\'', '/', '<', '>', '\\', 0, 0, 0, 0, 0, 0, 0, 0, 0), input, _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK);
528+
const __m128i result_individual_bytes = _mm_cmpistrm(sse_escape_mask, input, _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK);
510529
int mask = _mm_cvtsi128_si32(result_individual_bytes);
511530
#endif
512531
if (mask != 0) {

0 commit comments

Comments
 (0)