From 3727e2645652b61d47fbae987675032eff7d398f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 25 Nov 2014 14:17:21 +0300 Subject: [PATCH] Improved zend_hash_clean() and added new optimized zend_symtable_clean() --- Zend/zend_execute.c | 4 +-- Zend/zend_hash.c | 66 +++++++++++++++++++++++++++++++++++++------ Zend/zend_hash.h | 1 + Zend/zend_variables.c | 2 +- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 9ef06d25c1..5274f100e1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1421,12 +1421,12 @@ ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_val ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table TSRMLS_DC) /* {{{ */ { if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) { - zend_hash_destroy(&symbol_table->ht); + zend_array_destroy(&symbol_table->ht TSRMLS_CC); efree_size(symbol_table, sizeof(zend_array)); } else { /* clean before putting into the cache, since clean could call dtors, which could use cached hash */ - zend_hash_clean(&symbol_table->ht); + zend_symtable_clean(&symbol_table->ht TSRMLS_CC); *(++EG(symtable_cache_ptr)) = symbol_table; } } diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 2a7cb5a4b8..0f77ca6048 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -989,21 +989,71 @@ ZEND_API void zend_array_destroy(HashTable *ht TSRMLS_DC) ZEND_API void zend_hash_clean(HashTable *ht) { - uint32_t idx; - Bucket *p; + Bucket *p, *end; IS_CONSISTENT(ht); - for (idx = 0; idx < ht->nNumUsed; idx++) { - p = ht->arData + idx; - if (Z_TYPE(p->val) == IS_UNDEF) continue; + if (ht->nNumUsed) { + p = ht->arData; + end = p + ht->nNumUsed; if (ht->pDestructor) { - ht->pDestructor(&p->val); + if (ht->u.flags & HASH_FLAG_PACKED) { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + ht->pDestructor(&p->val); + } + } while (++p != end); + } else { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + ht->pDestructor(&p->val); + if (EXPECTED(p->key)) { + zend_string_release(p->key); + } + } + } while (++p != end); + } + } else { + if (!(ht->u.flags & HASH_FLAG_PACKED)) { + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + if (EXPECTED(p->key)) { + zend_string_release(p->key); + } + } + } while (++p != end); + } } - if (p->key) { - zend_string_release(p->key); + } + ht->nNumUsed = 0; + ht->nNumOfElements = 0; + ht->nNextFreeElement = 0; + ht->nInternalPointer = INVALID_IDX; + if (ht->nTableMask) { + if (!(ht->u.flags & HASH_FLAG_PACKED)) { + memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t)); } } +} + +ZEND_API void zend_symtable_clean(HashTable *ht TSRMLS_DC) +{ + Bucket *p, *end; + + IS_CONSISTENT(ht); + + if (ht->nNumUsed) { + p = ht->arData; + end = p + ht->nNumUsed; + do { + if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) { + i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC TSRMLS_CC); + if (EXPECTED(p->key)) { + zend_string_release(p->key); + } + } + } while (++p != end); + } ht->nNumUsed = 0; ht->nNumOfElements = 0; ht->nNextFreeElement = 0; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 435e92494c..8f12b0e66e 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -217,6 +217,7 @@ ZEND_API int zend_hash_rehash(HashTable *ht); ZEND_API void zend_array_dup(HashTable *target, HashTable *source); ZEND_API void zend_array_destroy(HashTable *ht TSRMLS_DC); +ZEND_API void zend_symtable_clean(HashTable *ht TSRMLS_DC); #if ZEND_DEBUG /* debug */ diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 1d3c0d2dcb..548d191cfd 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -298,7 +298,7 @@ ZEND_API void _zval_ptr_dtor_wrapper(zval *zval_ptr) { TSRMLS_FETCH(); - i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_RELAY_CC TSRMLS_CC); + i_zval_ptr_dtor(zval_ptr ZEND_FILE_LINE_CC TSRMLS_CC); } -- 2.40.0