Skip to content

Commit db54e3f

Browse files
committed
preliminary resolver support (needs more work)
1 parent 326b982 commit db54e3f

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

ext/json/json_encoder.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
#include "zend_lazy_objects.h"
3232
#include "zend_bitset.h"
3333

34-
#ifdef ZEND_INTRIN_SSE4_2_NATIVE
34+
#if defined(ZEND_INTRIN_SSE4_2_NATIVE) || defined(ZEND_INTRIN_SSE4_2_FUNC_PROTO)
3535
# include <nmmintrin.h>
3636
#endif
37+
#ifdef ZEND_INTRIN_SSE4_2_FUNC_PROTO
38+
# include "zend_cpuinfo.h"
39+
#endif
3740

3841
static const char digits[] = "0123456789abcdef";
3942

@@ -433,7 +436,7 @@ static zend_always_inline bool php_json_printable_ascii_escape(smart_str *buf, u
433436
return true;
434437
}
435438

436-
#ifdef ZEND_INTRIN_SSE4_2_NATIVE
439+
#if defined(ZEND_INTRIN_SSE4_2_NATIVE) || defined(ZEND_INTRIN_SSE4_2_FUNC_PROTO)
437440
static zend_always_inline __m128i php_json_create_sse_escape_mask(int options)
438441
{
439442
const char sentinel = 1; /* outside of the printable range, so no false matches are possible */
@@ -446,6 +449,28 @@ static zend_always_inline __m128i php_json_create_sse_escape_mask(int options)
446449
}
447450
#endif
448451

452+
#ifdef ZEND_INTRIN_SSE4_2_FUNC_PROTO
453+
static int php_json_sse42_compute_escape_intersection(const __m128i mask, const __m128i input) __attribute__((ifunc("resolve_json_escape_intersection")));
454+
455+
typedef int (*php_json_compute_escape_intersection_t)(const __m128i mask, const __m128i input);
456+
457+
ZEND_INTRIN_SSE4_2_FUNC_DECL(int php_json_sse42_compute_escape_intersection_real(const __m128i mask, const __m128i input));
458+
zend_always_inline int php_json_sse42_compute_escape_intersection_real(const __m128i mask, const __m128i input)
459+
{
460+
const __m128i result_individual_bytes = _mm_cmpistrm(mask, input, _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK);
461+
return _mm_cvtsi128_si32(result_individual_bytes);
462+
}
463+
464+
ZEND_NO_SANITIZE_ADDRESS
465+
ZEND_ATTRIBUTE_UNUSED /* clang mistakenly warns about this */
466+
static php_json_compute_escape_intersection_t resolve_json_escape_intersection(void) {
467+
if (zend_cpu_supports_sse42()) {
468+
return php_json_sse42_compute_escape_intersection_real;
469+
}
470+
return NULL/*php_json_sse42_compute_escape_intersection_fallback*/; // TODO: implement this fallback
471+
}
472+
#endif
473+
449474
zend_result php_json_escape_string(
450475
smart_str *buf, const char *s, size_t len,
451476
int options, php_json_encoder *encoder) /* {{{ */
@@ -483,7 +508,7 @@ zend_result php_json_escape_string(
483508

484509
pos = 0;
485510

486-
#ifdef ZEND_INTRIN_SSE4_2_NATIVE
511+
#if defined(ZEND_INTRIN_SSE4_2_NATIVE) || defined(ZEND_INTRIN_SSE4_2_FUNC_PROTO)
487512
const __m128i sse_escape_mask = php_json_create_sse_escape_mask(options);
488513
#endif
489514

@@ -504,9 +529,10 @@ zend_result php_json_escape_string(
504529
max_shift = zend_ulong_ntz(input_range_mask);
505530
}
506531

507-
#ifdef ZEND_INTRIN_SSE4_2_NATIVE /* TODO: resolver support */
508-
const __m128i result_individual_bytes = _mm_cmpistrm(sse_escape_mask, input, _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK);
509-
int mask = _mm_cvtsi128_si32(result_individual_bytes);
532+
#ifdef ZEND_INTRIN_SSE4_2_NATIVE
533+
int mask = php_json_sse42_compute_escape_intersection_real(sse_escape_mask, input);
534+
#elif defined(ZEND_INTRIN_SSE4_2_FUNC_PROTO)
535+
int mask = php_json_sse42_compute_escape_intersection(sse_escape_mask, input);
510536
#else
511537
const __m128i result_34 = _mm_cmpeq_epi8(input, _mm_set1_epi8('"'));
512538
const __m128i result_38 = _mm_cmpeq_epi8(input, _mm_set1_epi8('&'));

0 commit comments

Comments
 (0)