diff options
Diffstat (limited to 'Zend/zend_string.h')
-rw-r--r-- | Zend/zend_string.h | 87 |
1 files changed, 71 insertions, 16 deletions
diff --git a/Zend/zend_string.h b/Zend/zend_string.h index c95578d4a5..b4a0ddef95 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -39,7 +39,6 @@ ZEND_API void zend_interned_strings_dtor(void); ZEND_API void zend_interned_strings_activate(void); ZEND_API void zend_interned_strings_deactivate(void); ZEND_API void zend_interned_strings_set_request_storage_handlers(zend_new_interned_string_func_t handler, zend_string_init_interned_func_t init_handler); -ZEND_API void zend_interned_strings_set_permanent_storage_copy_handlers(zend_string_copy_storage_func_t copy_handler, zend_string_copy_storage_func_t restore_handler); ZEND_API void zend_interned_strings_switch_storage(zend_bool request); ZEND_API extern zend_string *zend_empty_string; @@ -80,7 +79,7 @@ END_EXTERN_C() (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \ GC_SET_REFCOUNT(str, 1); \ GC_TYPE_INFO(str) = IS_STRING; \ - zend_string_forget_hash_val(str); \ + ZSTR_H(str) = 0; \ ZSTR_LEN(str) = _len; \ } while (0) @@ -102,6 +101,7 @@ static zend_always_inline zend_ulong zend_string_hash_val(zend_string *s) static zend_always_inline void zend_string_forget_hash_val(zend_string *s) { ZSTR_H(s) = 0; + GC_DEL_FLAGS(s, IS_STR_VALID_UTF8); } static zend_always_inline uint32_t zend_string_refcount(const zend_string *s) @@ -134,7 +134,7 @@ static zend_always_inline zend_string *zend_string_alloc(size_t len, int persist GC_SET_REFCOUNT(ret, 1); GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << GC_FLAGS_SHIFT); - zend_string_forget_hash_val(ret); + ZSTR_H(ret) = 0; ZSTR_LEN(ret) = len; return ret; } @@ -145,7 +145,7 @@ static zend_always_inline zend_string *zend_string_safe_alloc(size_t n, size_t m GC_SET_REFCOUNT(ret, 1); GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << GC_FLAGS_SHIFT); - zend_string_forget_hash_val(ret); + ZSTR_H(ret) = 0; ZSTR_LEN(ret) = (n * m) + l; return ret; } @@ -337,7 +337,7 @@ static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_str * constants, prime or not, has never been adequately explained by * anyone. So I try an explanation: if one experimentally tests all * multipliers between 1 and 256 (as RSE did now) one detects that even - * numbers are not useable at all. The remaining 128 odd numbers + * numbers are not usable at all. The remaining 128 odd numbers * (except for the number 1) work more or less all equally well. They * all distribute in an acceptable way and this way fill a hash table * with an average percent of approx. 86%. @@ -361,6 +361,69 @@ static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size { zend_ulong hash = Z_UL(5381); +#if defined(_WIN32) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) + /* Version with multiplication works better on modern CPU */ + for (; len >= 8; len -= 8, str += 8) { +# if defined(__aarch64__) && !defined(WORDS_BIGENDIAN) + /* On some architectures it is beneficial to load 8 bytes at a + time and extract each byte with a bit field extract instr. */ + uint64_t chunk; + + memcpy(&chunk, str, sizeof(chunk)); + hash = + hash * 33 * 33 * 33 * 33 + + ((chunk >> (8 * 0)) & 0xff) * 33 * 33 * 33 + + ((chunk >> (8 * 1)) & 0xff) * 33 * 33 + + ((chunk >> (8 * 2)) & 0xff) * 33 + + ((chunk >> (8 * 3)) & 0xff); + hash = + hash * 33 * 33 * 33 * 33 + + ((chunk >> (8 * 4)) & 0xff) * 33 * 33 * 33 + + ((chunk >> (8 * 5)) & 0xff) * 33 * 33 + + ((chunk >> (8 * 6)) & 0xff) * 33 + + ((chunk >> (8 * 7)) & 0xff); +# else + hash = + hash * 33 * 33 * 33 * 33 + + str[0] * 33 * 33 * 33 + + str[1] * 33 * 33 + + str[2] * 33 + + str[3]; + hash = + hash * 33 * 33 * 33 * 33 + + str[4] * 33 * 33 * 33 + + str[5] * 33 * 33 + + str[6] * 33 + + str[7]; +# endif + } + if (len >= 4) { + hash = + hash * 33 * 33 * 33 * 33 + + str[0] * 33 * 33 * 33 + + str[1] * 33 * 33 + + str[2] * 33 + + str[3]; + len -= 4; + str += 4; + } + if (len >= 2) { + if (len > 2) { + hash = + hash * 33 * 33 * 33 + + str[0] * 33 * 33 + + str[1] * 33 + + str[2]; + } else { + hash = + hash * 33 * 33 + + str[0] * 33 + + str[1]; + } + } else if (len != 0) { + hash = hash * 33 + *str; + } +#else /* variant with the hash unrolled eight times */ for (; len >= 8; len -= 8) { hash = ((hash << 5) + hash) + *str++; @@ -383,6 +446,7 @@ static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size case 0: break; EMPTY_SWITCH_DEFAULT_CASE() } +#endif /* Hash value can't be zero, so we always set the high bit */ #if SIZEOF_ZEND_LONG == 8 @@ -442,6 +506,7 @@ EMPTY_SWITCH_DEFAULT_CASE() _(ZEND_STR_NAME, "name") \ _(ZEND_STR_ARGV, "argv") \ _(ZEND_STR_ARGC, "argc") \ + _(ZEND_STR_ARRAY_CAPITALIZED, "Array") \ typedef enum _zend_known_string_id { @@ -452,13 +517,3 @@ ZEND_KNOWN_STRINGS(_ZEND_STR_ID) } zend_known_string_id; #endif /* ZEND_STRING_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ |