summaryrefslogtreecommitdiff
path: root/Zend/zend_string.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-10-19 00:02:56 +0300
committerDmitry Stogov <dmitry@zend.com>2017-10-19 00:02:56 +0300
commit272f5a1716155f21ccce8dc625aeeabbcbe6bdaa (patch)
tree766582a23c040de9c61aca0a2a6a70e1dd2e2e4f /Zend/zend_string.c
parentea915adb483cc274a6f2a273148fabe93e5a8720 (diff)
downloadphp-git-272f5a1716155f21ccce8dc625aeeabbcbe6bdaa.tar.gz
Extend zend_string API to avoid reallocation in zend_string_init_interned()
Diffstat (limited to 'Zend/zend_string.c')
-rw-r--r--Zend/zend_string.c65
1 files changed, 58 insertions, 7 deletions
diff --git a/Zend/zend_string.c b/Zend/zend_string.c
index 4cfd3dedec..ab8fc7f407 100644
--- a/Zend/zend_string.c
+++ b/Zend/zend_string.c
@@ -22,9 +22,12 @@
#include "zend_globals.h"
ZEND_API zend_string *(*zend_new_interned_string)(zend_string *str);
+ZEND_API zend_string *(*zend_string_init_interned)(const char *str, size_t size, int permanent);
static zend_string *zend_new_interned_string_permanent(zend_string *str);
static zend_string *zend_new_interned_string_request(zend_string *str);
+static zend_string *zend_string_init_interned_permanent(const char *str, size_t size, int permanent);
+static zend_string *zend_string_init_interned_request(const char *str, size_t size, int permanent);
/* Any strings interned in the startup phase. Common to all the threads,
won't be free'd until process exit. If we want an ability to
@@ -33,6 +36,7 @@ static zend_string *zend_new_interned_string_request(zend_string *str);
static HashTable interned_strings_permanent;
static zend_new_interned_string_func_t interned_string_request_handler = zend_new_interned_string_request;
+static zend_string_init_interned_func_t interned_string_init_request_handler = zend_string_init_interned_request;
static zend_string_copy_storage_func_t interned_string_copy_storage = NULL;
ZEND_API zend_string *zend_empty_string = NULL;
@@ -72,6 +76,7 @@ ZEND_API void zend_interned_strings_init(void)
zend_init_interned_strings_ht(&interned_strings_permanent, 1);
zend_new_interned_string = zend_new_interned_string_permanent;
+ zend_string_init_interned = zend_string_init_interned_permanent;
/* interned empty string */
str = zend_string_alloc(sizeof("")-1, 1);
@@ -100,20 +105,18 @@ ZEND_API void zend_interned_strings_dtor(void)
zend_known_strings = NULL;
}
-static zend_always_inline zend_string *zend_interned_string_ht_lookup(zend_string *str, HashTable *interned_strings)
+static zend_always_inline zend_string *zend_interned_string_ht_lookup_ex(zend_ulong h, const char *str, size_t size, HashTable *interned_strings)
{
- zend_ulong h;
uint32_t nIndex;
uint32_t idx;
Bucket *p;
- h = zend_string_hash_val(str);
nIndex = h | interned_strings->nTableMask;
idx = HT_HASH(interned_strings, nIndex);
while (idx != HT_INVALID_IDX) {
p = HT_HASH_TO_BUCKET(interned_strings, idx);
- if ((p->h == h) && (ZSTR_LEN(p->key) == ZSTR_LEN(str))) {
- if (!memcmp(ZSTR_VAL(p->key), ZSTR_VAL(str), ZSTR_LEN(str))) {
+ if ((p->h == h) && (ZSTR_LEN(p->key) == size)) {
+ if (!memcmp(ZSTR_VAL(p->key), str, size)) {
return p->key;
}
}
@@ -123,6 +126,11 @@ static zend_always_inline zend_string *zend_interned_string_ht_lookup(zend_strin
return NULL;
}
+static zend_always_inline zend_string *zend_interned_string_ht_lookup(zend_string *str, HashTable *interned_strings)
+{
+ return zend_interned_string_ht_lookup_ex(ZSTR_H(str), ZSTR_VAL(str), ZSTR_LEN(str), interned_strings);
+}
+
/* This function might be not thread safe at least because it would update the
hash val in the passed string. Be sure it is called in the appropriate context. */
static zend_always_inline zend_string *zend_add_interned_string(zend_string *str, HashTable *interned_strings, uint32_t flags)
@@ -141,10 +149,10 @@ static zend_always_inline zend_string *zend_add_interned_string(zend_string *str
ZEND_API zend_string *zend_interned_string_find_permanent(zend_string *str)
{
+ zend_string_hash_val(str);
return zend_interned_string_ht_lookup(str, &interned_strings_permanent);
}
-
static zend_string *zend_new_interned_string_permanent(zend_string *str)
{
zend_string *ret;
@@ -153,6 +161,7 @@ static zend_string *zend_new_interned_string_permanent(zend_string *str)
return str;
}
+ zend_string_hash_val(str);
ret = zend_interned_string_ht_lookup(str, &interned_strings_permanent);
if (ret) {
zend_string_release(str);
@@ -170,6 +179,8 @@ static zend_string *zend_new_interned_string_request(zend_string *str)
return str;
}
+ zend_string_hash_val(str);
+
/* Check for permanent strings, the table is readonly at this point. */
ret = zend_interned_string_ht_lookup(str, &interned_strings_permanent);
if (ret) {
@@ -189,6 +200,44 @@ static zend_string *zend_new_interned_string_request(zend_string *str)
return ret;
}
+static zend_string *zend_string_init_interned_permanent(const char *str, size_t size, int permanent)
+{
+ zend_string *ret;
+ zend_long h = zend_inline_hash_func(str, size);
+
+ ret = zend_interned_string_ht_lookup_ex(h, str, size, &interned_strings_permanent);
+ if (ret) {
+ return ret;
+ }
+
+ ret = zend_string_init(str, size, permanent);
+ ZSTR_H(ret) = h;
+ return zend_add_interned_string(ret, &interned_strings_permanent, IS_STR_PERMANENT);
+}
+
+static zend_string *zend_string_init_interned_request(const char *str, size_t size, int permanent)
+{
+ zend_string *ret;
+ zend_long h = zend_inline_hash_func(str, size);
+
+ /* Check for permanent strings, the table is readonly at this point. */
+ ret = zend_interned_string_ht_lookup_ex(h, str, size, &interned_strings_permanent);
+ if (ret) {
+ return ret;
+ }
+
+ ret = zend_interned_string_ht_lookup_ex(h, str, size, &CG(interned_strings));
+ if (ret) {
+ return ret;
+ }
+
+ ret = zend_string_init(str, size, permanent);
+ ZSTR_H(ret) = h;
+
+ /* Create a short living interned, freed after the request. */
+ return zend_add_interned_string(ret, &CG(interned_strings), 0);
+}
+
ZEND_API void zend_interned_strings_activate(void)
{
zend_init_interned_strings_ht(&CG(interned_strings), 0);
@@ -199,9 +248,10 @@ ZEND_API void zend_interned_strings_deactivate(void)
zend_hash_destroy(&CG(interned_strings));
}
-ZEND_API void zend_interned_strings_set_request_storage_handler(zend_new_interned_string_func_t handler)
+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)
{
interned_string_request_handler = handler;
+ interned_string_init_request_handler = init_handler;
}
ZEND_API void zend_interned_strings_set_permanent_storage_copy_handler(zend_string_copy_storage_func_t handler)
@@ -215,6 +265,7 @@ ZEND_API void zend_interned_strings_switch_storage(void)
interned_string_copy_storage();
}
zend_new_interned_string = interned_string_request_handler;
+ zend_string_init_interned = interned_string_init_request_handler;
}
/*