]> granicus.if.org Git - php/commitdiff
Extend zend_string API to avoid reallocation in zend_string_init_interned()
authorDmitry Stogov <dmitry@zend.com>
Wed, 18 Oct 2017 21:02:56 +0000 (00:02 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 18 Oct 2017 21:02:56 +0000 (00:02 +0300)
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_string.c
Zend/zend_string.h
ext/mysqlnd/mysqlnd_wireprotocol.c
ext/opcache/ZendAccelerator.c

index b9467da710b02170157ba2b5ffb1932d77008ee7..fd1705149b96342c33f127f18bd5f2a6e5082950 100644 (file)
@@ -2177,7 +2177,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
        while (ptr->fname) {
                fname_len = strlen(ptr->fname);
                internal_function->handler = ptr->handler;
-               internal_function->function_name = zend_new_interned_string(zend_string_init(ptr->fname, fname_len, 1));
+               internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
                internal_function->scope = scope;
                internal_function->prototype = NULL;
                if (ptr->flags) {
@@ -2307,7 +2307,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
                                                class_name++;
                                                allow_null = 1;
                                        }
-                                       str = zend_new_interned_string(zend_string_init(class_name, strlen(class_name), 1));
+                                       str = zend_string_init_interned(class_name, strlen(class_name), 1);
                                        new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null);
                                }
                        }
@@ -3863,9 +3863,12 @@ ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name,
 {
        int ret;
 
-       zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+       zend_string *key;
+
        if (ce->type == ZEND_INTERNAL_CLASS) {
-               key = zend_new_interned_string(key);
+               key = zend_string_init_interned(name, name_length, 1);
+       } else {
+               key = zend_string_init(name, name_length, 0);
        }
        ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
        zend_string_release(key);
index c3220d268538b3898d3957442145fed445b4035a..df9e136e4a95045c6edd89c7f85b1dd86fa4644a 100644 (file)
@@ -193,9 +193,7 @@ typedef struct _zend_fcall_info_cache {
 
 #define INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, class_name_len, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
        {                                                                                                                       \
-               zend_string *cl_name;                                                                   \
-               cl_name = zend_string_init(class_name, class_name_len, 1);              \
-               class_container.name = zend_new_interned_string(cl_name);       \
+               class_container.name = zend_string_init_interned(class_name, class_name_len, 1); \
                INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions, handle_fcall, handle_propget, handle_propset, handle_propunset, handle_propisset) \
        }
 
index 4cfd3dedec8f72ff3b58538013a0d6144be403e9..ab8fc7f407a660c50f567081c8671543440f561a 100644 (file)
 #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;
 }
 
 /*
index 400795a9b2504563f8e15f615c8ecb738fc249e7..7f5b10838365f5bee5ac26cee078531507a320ba 100644 (file)
@@ -27,8 +27,10 @@ BEGIN_EXTERN_C()
 
 typedef void (*zend_string_copy_storage_func_t)(void);
 typedef zend_string *(*zend_new_interned_string_func_t)(zend_string *str);
+typedef zend_string *(*zend_string_init_interned_func_t)(const char *str, size_t size, int permanent);
 
 ZEND_API extern zend_new_interned_string_func_t zend_new_interned_string;
+ZEND_API extern zend_string_init_interned_func_t zend_string_init_interned;
 
 ZEND_API zend_ulong zend_hash_func(const char *str, size_t len);
 ZEND_API void zend_interned_strings_init(void);
@@ -36,7 +38,7 @@ 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 zend_string *zend_interned_string_find_permanent(zend_string *str);
-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);
 ZEND_API void zend_interned_strings_set_permanent_storage_copy_handler(zend_string_copy_storage_func_t handler);
 ZEND_API void zend_interned_strings_switch_storage(void);
 
@@ -174,13 +176,6 @@ static zend_always_inline zend_string *zend_string_init(const char *str, size_t
        return ret;
 }
 
-static zend_always_inline zend_string *zend_string_init_interned(const char *str, size_t len, int persistent)
-{
-       zend_string *ret = zend_string_init(str, len, persistent);
-
-       return zend_new_interned_string(ret);
-}
-
 static zend_always_inline zend_string *zend_string_copy(zend_string *s)
 {
        if (!ZSTR_IS_INTERNED(s)) {
index b948b8b81c4789d4b6854eb1e7f6b1f79f7601d7..ed6931ef41b9c268bc4f230d261b42b7783a383f 100644 (file)
@@ -1375,7 +1375,7 @@ php_mysqlnd_rset_field_read(void * _packet)
        meta->root_len = total_len;
 
        if (meta->name != mysqlnd_empty_string) {
-               meta->sname = zend_new_interned_string(zend_string_init(meta->name, meta->name_length, packet->persistent_alloc));
+               meta->sname = zend_string_init_interned(meta->name, meta->name_length, packet->persistent_alloc);
        } else {
                meta->sname = ZSTR_EMPTY_ALLOC();
        }
index cf1e1ce7d3b3c6047018892c9c2dba5b3baa57fd..d0edfa08a239c0683e34d430c355b0f3390e94db 100644 (file)
@@ -502,6 +502,47 @@ static zend_string *accel_new_interned_string_for_php(zend_string *str)
        return str;
 }
 
+static zend_string *accel_find_interned_string_ex(zend_ulong h, const char *str, size_t size)
+{
+       uint32_t nIndex;
+       uint32_t idx;
+       Bucket *arData, *p;
+
+       nIndex = h | ZCSG(interned_strings).nTableMask;
+
+       /* check for existing interned string */
+       idx = HT_HASH(&ZCSG(interned_strings), nIndex);
+       arData = ZCSG(interned_strings).arData;
+       while (idx != HT_INVALID_IDX) {
+               p = HT_HASH_TO_BUCKET_EX(arData, idx);
+               if ((p->h == h) && (ZSTR_LEN(p->key) == size)) {
+                       if (!memcmp(ZSTR_VAL(p->key), str, size)) {
+                               return p->key;
+                       }
+               }
+               idx = Z_NEXT(p->val);
+       }
+
+       return NULL;
+}
+
+static zend_string *accel_init_interned_string_for_php(const char *str, size_t size, int permanent)
+{
+       if (ZCG(counted)) {
+           zend_ulong h = zend_inline_hash_func(str, size);
+               zend_string *ret = accel_find_interned_string_ex(h, str, size);
+
+               if (!ret) {
+                       ret = zend_string_init(str, size, permanent);
+                       ZSTR_H(ret) = h;
+               }
+
+               return ret;
+       }
+
+       return zend_string_init(str, size, permanent);
+}
+
 /* Copy PHP interned strings from PHP process memory into the shared memory */
 static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_interned_string)
 {
@@ -2389,7 +2430,7 @@ static int zend_accel_init_shm(void)
                zend_interned_strings_set_permanent_storage_copy_handler(accel_use_shm_interned_strings);
        }
 
-       zend_interned_strings_set_request_storage_handler(accel_new_interned_string_for_php);
+       zend_interned_strings_set_request_storage_handlers(accel_new_interned_string_for_php, accel_init_interned_string_for_php);
 
        zend_reset_cache_vars();
 
@@ -2658,7 +2699,7 @@ static int accel_post_startup(void)
                                if (ZCG(accel_directives).interned_strings_buffer) {
                                        zend_interned_strings_set_permanent_storage_copy_handler(accel_use_shm_interned_strings);
                                }
-                               zend_interned_strings_set_request_storage_handler(accel_new_interned_string_for_php);
+                               zend_interned_strings_set_request_storage_handlers(accel_new_interned_string_for_php, accel_init_interned_string_for_php);
                                zend_shared_alloc_unlock();
                                break;
                        case FAILED_REATTACHED: