]> granicus.if.org Git - php/commitdiff
Implemented x86 and x86_64 assembler functions for zend_string equality check.
authorDmitry Stogov <dmitry@zend.com>
Mon, 4 Dec 2017 20:40:54 +0000 (23:40 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 4 Dec 2017 20:40:54 +0000 (23:40 +0300)
They take into account zend_string layout (value alignment and trailing padding) and perform comparison by double or quad words.

Zend/zend_string.c
Zend/zend_string.h

index bceb328f7f1206e85da306d56418001e498885ae..5c280ce0f4b7a9c34a9a2b727616ec39f5f2089d 100644 (file)
@@ -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
index 686895d81781a10ad7475b75ed0b8fffad6f038f..2bbcdb80a80e65af9c36e25453fefe893004ed38 100644 (file)
@@ -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)