From 8305a73483e854f314b8afa2d65dbcb0e7fae1b9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 4 Dec 2017 23:40:54 +0300 Subject: [PATCH] Implemented x86 and x86_64 assembler functions for zend_string equality check. They take into account zend_string layout (value alignment and trailing padding) and perform comparison by double or quad words. --- Zend/zend_string.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ Zend/zend_string.h | 11 ++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/Zend/zend_string.c b/Zend/zend_string.c index bceb328f7f..5c280ce0f4 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -309,6 +309,78 @@ ZEND_API void zend_interned_strings_switch_storage(zend_bool request) } } +#if defined(__GNUC__) && defined(__i386__) +ZEND_API zend_bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2) +{ + zend_ulong ret; + + __asm__ ( + "subl %1, %2\n\t" + "ll0%=:\n\t" + "movl (%1,%2), %0\n\t" + "xorl (%1), %0\n\t" + "jne ll1%=\n\t" + "addl $0x4, %1\n\t" + "subl $0x4, %3\n\t" + "jg ll0%=\n\t" + "movl $0x1, %0\n\t" + "jmp ll3%=\n\t" + "ll1%=:\n\t" + "cmpl $0x4,%3\n\t" + "jl ll2%=\n\t" + "xorl %0, %0\n\t" + "jmp ll3%=\n\t" + "ll2%=:\n\t" + "negl %3\n\t" + "lea 0x1c(,%3,8), %3\n\t" + "shll %b3, %0\n\t" + "sete %b0\n\t" + "andl $0x1, %0\n\t" + "ll3%=:\n" + : "=&a"(ret) + : "d"(ZSTR_VAL(s2)), + "r"(ZSTR_VAL(s1)), + "c"(ZSTR_LEN(s1)) + : "cc"); + return ret; +} +#elif defined(__GNUC__) && defined(__x86_64__) +ZEND_API zend_bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2) +{ + zend_ulong ret; + + __asm__ ( + "subq %1, %2\n\t" + "ll0%=:\n\t" + "movq (%1,%2), %0\n\t" + "xorq (%1), %0\n\t" + "jne ll1%=\n\t" + "addq $0x8, %1\n\t" + "subq $0x8, %3\n\t" + "jg ll0%=\n\t" + "movq $0x1, %0\n\t" + "jmp ll3%=\n\t" + "ll1%=:\n\t" + "cmpq $0x8,%3\n\t" + "jl ll2%=\n\t" + "xorq %0, %0\n\t" + "jmp ll3%=\n\t" + "ll2%=:\n\t" + "negq %3\n\t" + "lea 0x3c(,%3,8), %3\n\t" + "shlq %b3, %0\n\t" + "sete %b0\n\t" + "andq $0x1, %0\n\t" + "ll3%=:\n" + : "=&a"(ret) + : "r"(ZSTR_VAL(s2)), + "r"(ZSTR_VAL(s1)), + "c"(ZSTR_LEN(s1)) + : "cc"); + return ret; +} +#endif + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 686895d817..2bbcdb80a8 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -288,9 +288,18 @@ static zend_always_inline void zend_string_release(zend_string *s) } } +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +ZEND_API zend_bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2); +#else +static zend_always_inline zend_bool zend_string_equal_val(zend_string *s1, zend_string *s2) +{ + return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)); +} +#endif + static zend_always_inline zend_bool zend_string_equal_content(zend_string *s1, zend_string *s2) { - return ZSTR_LEN(s1) == ZSTR_LEN(s2) && !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)); + return ZSTR_LEN(s1) == ZSTR_LEN(s2) && zend_string_equal_val(s1, s2); } static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_string *s2) -- 2.50.1