31
31
#include "zend_lazy_objects.h"
32
32
#include "zend_bitset.h"
33
33
34
- #ifdef ZEND_INTRIN_SSE4_2_NATIVE
34
+ #if defined( ZEND_INTRIN_SSE4_2_NATIVE ) || defined( ZEND_INTRIN_SSE4_2_FUNC_PROTO )
35
35
# include <nmmintrin.h>
36
36
#endif
37
+ #ifdef ZEND_INTRIN_SSE4_2_FUNC_PROTO
38
+ # include "zend_cpuinfo.h"
39
+ #endif
37
40
38
41
static const char digits [] = "0123456789abcdef" ;
39
42
@@ -433,7 +436,7 @@ static zend_always_inline bool php_json_printable_ascii_escape(smart_str *buf, u
433
436
return true;
434
437
}
435
438
436
- #ifdef ZEND_INTRIN_SSE4_2_NATIVE
439
+ #if defined( ZEND_INTRIN_SSE4_2_NATIVE ) || defined( ZEND_INTRIN_SSE4_2_FUNC_PROTO )
437
440
static zend_always_inline __m128i php_json_create_sse_escape_mask (int options )
438
441
{
439
442
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)
446
449
}
447
450
#endif
448
451
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
+
449
474
zend_result php_json_escape_string (
450
475
smart_str * buf , const char * s , size_t len ,
451
476
int options , php_json_encoder * encoder ) /* {{{ */
@@ -483,7 +508,7 @@ zend_result php_json_escape_string(
483
508
484
509
pos = 0 ;
485
510
486
- #ifdef ZEND_INTRIN_SSE4_2_NATIVE
511
+ #if defined( ZEND_INTRIN_SSE4_2_NATIVE ) || defined( ZEND_INTRIN_SSE4_2_FUNC_PROTO )
487
512
const __m128i sse_escape_mask = php_json_create_sse_escape_mask (options );
488
513
#endif
489
514
@@ -504,9 +529,10 @@ zend_result php_json_escape_string(
504
529
max_shift = zend_ulong_ntz (input_range_mask );
505
530
}
506
531
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 );
510
536
#else
511
537
const __m128i result_34 = _mm_cmpeq_epi8 (input , _mm_set1_epi8 ('"' ));
512
538
const __m128i result_38 = _mm_cmpeq_epi8 (input , _mm_set1_epi8 ('&' ));
0 commit comments