]> granicus.if.org Git - php/commitdiff
Improved zend_hash_str_add/update functions
authorDmitry Stogov <dmitry@zend.com>
Tue, 31 Oct 2017 07:35:28 +0000 (10:35 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 31 Oct 2017 07:35:28 +0000 (10:35 +0300)
Zend/zend_hash.c

index 123f2c0884baa988aefcc535768bde0316bdea4a..c14cca78bb0253d48225d3a8c3bf5cf1992bd89d 100644 (file)
@@ -609,6 +609,77 @@ add_to_hash:
        return &p->val;
 }
 
+static zend_always_inline zval *_zend_hash_str_add_or_update_i(HashTable *ht, const char *str, size_t len, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
+{
+       zend_string *key;
+       uint32_t nIndex;
+       uint32_t idx;
+       Bucket *p;
+
+       IS_CONSISTENT(ht);
+       HT_ASSERT_RC1(ht);
+
+       if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
+               CHECK_INIT(ht, 0);
+               goto add_to_hash;
+       } else if (ht->u.flags & HASH_FLAG_PACKED) {
+               zend_hash_packed_to_hash(ht);
+       } else if ((flag & HASH_ADD_NEW) == 0) {
+               p = zend_hash_str_find_bucket(ht, str, len, h);
+
+               if (p) {
+                       zval *data;
+
+                       if (flag & HASH_ADD) {
+                               if (!(flag & HASH_UPDATE_INDIRECT)) {
+                                       return NULL;
+                               }
+                               ZEND_ASSERT(&p->val != pData);
+                               data = &p->val;
+                               if (Z_TYPE_P(data) == IS_INDIRECT) {
+                                       data = Z_INDIRECT_P(data);
+                                       if (Z_TYPE_P(data) != IS_UNDEF) {
+                                               return NULL;
+                                       }
+                               } else {
+                                       return NULL;
+                               }
+                       } else {
+                               ZEND_ASSERT(&p->val != pData);
+                               data = &p->val;
+                               if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
+                                       data = Z_INDIRECT_P(data);
+                               }
+                       }
+                       if (ht->pDestructor) {
+                               ht->pDestructor(data);
+                       }
+                       ZVAL_COPY_VALUE(data, pData);
+                       return data;
+               }
+       }
+
+       ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
+
+add_to_hash:
+       idx = ht->nNumUsed++;
+       ht->nNumOfElements++;
+       if (ht->nInternalPointer == HT_INVALID_IDX) {
+               ht->nInternalPointer = idx;
+       }
+       zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
+       p = ht->arData + idx;
+       p->key = key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
+       p->h = ZSTR_H(key) = h;
+       ht->u.flags &= ~HASH_FLAG_STATIC_KEYS;
+       ZVAL_COPY_VALUE(&p->val, pData);
+       nIndex = h | ht->nTableMask;
+       Z_NEXT(p->val) = HT_HASH(ht, nIndex);
+       HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
+
+       return &p->val;
+}
+
 ZEND_API zval* ZEND_FASTCALL _zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
 {
        return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
@@ -636,42 +707,37 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_add_new(HashTable *ht, zend_string *key,
 
 ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
 {
-       zend_string *key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
-       zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
-       zend_string_release(key);
-       return ret;
+       zend_ulong h = zend_hash_func(str, len);
+
+       return _zend_hash_str_add_or_update_i(ht, str, len, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
 }
 
 ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
 {
-       zend_string *key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
-       zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
-       zend_string_release(key);
-       return ret;
+       zend_ulong h = zend_hash_func(str, len);
+
+       return _zend_hash_str_add_or_update_i(ht, str, len, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
 }
 
 ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
 {
-       zend_string *key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
-       zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
-       zend_string_release(key);
-       return ret;
+       zend_ulong h = zend_hash_func(str, len);
+
+       return _zend_hash_str_add_or_update_i(ht, str, len, h, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
 }
 
 ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
 {
-       zend_string *key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
-       zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
-       zend_string_release(key);
-       return ret;
+       zend_ulong h = zend_hash_func(str, len);
+
+       return _zend_hash_str_add_or_update_i(ht, str, len, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
 }
 
 ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
 {
-       zend_string *key = zend_string_init(str, len, GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
-       zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
-       zend_string_delref(key);
-       return ret;
+       zend_ulong h = zend_hash_func(str, len);
+
+       return _zend_hash_str_add_or_update_i(ht, str, len, h, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
 }
 
 ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)