summaryrefslogtreecommitdiff
path: root/Zend/zend_string.h
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_string.h')
-rw-r--r--Zend/zend_string.h87
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
- */