From: Nikita Popov Date: Thu, 20 Mar 2014 22:50:04 +0000 (+0100) Subject: Rename+move zend_hash_apply_deleter and reuse it X-Git-Tag: PRE_PHPNG_MERGE~453^2~1^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e7e301dda2fa081c1310279b027a2350c05801e;p=php Rename+move zend_hash_apply_deleter and reuse it The interruption handling was normalized to wrap the entire deletion operation (instead of leaving out the destructor call and/or the deallocation) per the recommendation of somebody (don't remember who) familiar with zend signals. There is an always-inlined variant of the function for use in the main deletion function, to ensure there is no performance impact. --- diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index ab8601c2eb..aa3587c675 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -156,6 +156,51 @@ static inline void zend_hash_bucket_update( } } +static zend_always_inline void i_zend_hash_bucket_delete(HashTable *ht, Bucket *p) +{ +#ifdef ZEND_SIGNALS + TSRMLS_FETCH(); +#endif + + HANDLE_BLOCK_INTERRUPTIONS(); + if (p->pLast) { + p->pLast->pNext = p->pNext; + } else { + ht->arBuckets[p->h & ht->nTableMask] = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + /* Deleting the tail of the list */ + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + ht->nNumOfElements--; + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (p->pData != &p->pDataPtr) { + pefree(p->pData, ht->persistent); + } + pefree(p, ht->persistent); + HANDLE_UNBLOCK_INTERRUPTIONS(); +} + +static void zend_hash_bucket_delete(HashTable *ht, Bucket *p) { + i_zend_hash_bucket_delete(ht, p); +} + ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) { uint i = 3; @@ -427,9 +472,6 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n { uint nIndex; Bucket *p; -#ifdef ZEND_SIGNALS - TSRMLS_FETCH(); -#endif IS_CONSISTENT(ht); @@ -444,38 +486,7 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n && (p->nKeyLength == nKeyLength) && ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */ || !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */ - HANDLE_BLOCK_INTERRUPTIONS(); - if (p == ht->arBuckets[nIndex]) { - ht->arBuckets[nIndex] = p->pNext; - } else { - p->pLast->pNext = p->pNext; - } - if (p->pNext) { - p->pNext->pLast = p->pLast; - } - if (p->pListLast != NULL) { - p->pListLast->pListNext = p->pListNext; - } else { - /* Deleting the head of the list */ - ht->pListHead = p->pListNext; - } - if (p->pListNext != NULL) { - p->pListNext->pListLast = p->pListLast; - } else { - ht->pListTail = p->pListLast; - } - if (ht->pInternalPointer == p) { - ht->pInternalPointer = p->pListNext; - } - ht->nNumOfElements--; - if (ht->pDestructor) { - ht->pDestructor(p->pData); - } - if (p->pData != &p->pDataPtr) { - pefree(p->pData, ht->persistent); - } - pefree(p, ht->persistent); - HANDLE_UNBLOCK_INTERRUPTIONS(); + i_zend_hash_bucket_delete(ht, p); return SUCCESS; } p = p->pNext; @@ -542,63 +553,12 @@ ZEND_API void zend_hash_clean(HashTable *ht) } } -/* This function is used by the various apply() functions. - * It deletes the passed bucket. - */ -static void zend_hash_apply_deleter(HashTable *ht, Bucket *p) -{ -#ifdef ZEND_SIGNALS - TSRMLS_FETCH(); -#endif - - HANDLE_BLOCK_INTERRUPTIONS(); - if (p->pLast) { - p->pLast->pNext = p->pNext; - } else { - uint nIndex; - - nIndex = p->h & ht->nTableMask; - ht->arBuckets[nIndex] = p->pNext; - } - if (p->pNext) { - p->pNext->pLast = p->pLast; - } else { - /* Nothing to do as this list doesn't have a tail */ - } - - if (p->pListLast != NULL) { - p->pListLast->pListNext = p->pListNext; - } else { - /* Deleting the head of the list */ - ht->pListHead = p->pListNext; - } - if (p->pListNext != NULL) { - p->pListNext->pListLast = p->pListLast; - } else { - ht->pListTail = p->pListLast; - } - if (ht->pInternalPointer == p) { - ht->pInternalPointer = p->pListNext; - } - ht->nNumOfElements--; - HANDLE_UNBLOCK_INTERRUPTIONS(); - - if (ht->pDestructor) { - ht->pDestructor(p->pData); - } - if (p->pData != &p->pDataPtr) { - pefree(p->pData, ht->persistent); - } - pefree(p, ht->persistent); -} - - ZEND_API void zend_hash_graceful_destroy(HashTable *ht) { IS_CONSISTENT(ht); while (ht->pListHead != NULL) { - zend_hash_apply_deleter(ht, ht->pListHead); + zend_hash_bucket_delete(ht, ht->pListHead); } if (ht->nTableMask) { @@ -613,7 +573,7 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht) IS_CONSISTENT(ht); while (ht->pListTail != NULL) { - zend_hash_apply_deleter(ht, ht->pListTail); + zend_hash_bucket_delete(ht, ht->pListTail); } if (ht->nTableMask) { @@ -645,7 +605,7 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC) Bucket *p_next = p->pListNext; if (result & ZEND_HASH_APPLY_REMOVE) { - zend_hash_apply_deleter(ht, p); + zend_hash_bucket_delete(ht, p); } p = p_next; @@ -670,7 +630,7 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t appl Bucket *p_next = p->pListNext; if (result & ZEND_HASH_APPLY_REMOVE) { - zend_hash_apply_deleter(ht, p); + zend_hash_bucket_delete(ht, p); } p = p_next; @@ -703,7 +663,7 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func Bucket *p_next = p->pListNext; if (result & ZEND_HASH_APPLY_REMOVE) { - zend_hash_apply_deleter(ht, p); + zend_hash_bucket_delete(ht, p); } p = p_next; @@ -731,7 +691,7 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR Bucket *p_last = p->pListLast; if (result & ZEND_HASH_APPLY_REMOVE) { - zend_hash_apply_deleter(ht, p); + zend_hash_bucket_delete(ht, p); } p = p_last; @@ -1204,8 +1164,6 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const return FAILURE; } - HANDLE_BLOCK_INTERRUPTIONS(); - if (q) { if (mode != HASH_UPDATE_KEY_ANYWAY) { Bucket *r = p->pListLast; @@ -1220,73 +1178,17 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const } if (mode & found) { /* delete current bucket */ - if (p == ht->arBuckets[p->h & ht->nTableMask]) { - ht->arBuckets[p->h & ht->nTableMask] = p->pNext; - } else { - p->pLast->pNext = p->pNext; - } - if (p->pNext) { - p->pNext->pLast = p->pLast; - } - if (p->pListLast != NULL) { - p->pListLast->pListNext = p->pListNext; - } else { - /* Deleting the head of the list */ - ht->pListHead = p->pListNext; - } - if (p->pListNext != NULL) { - p->pListNext->pListLast = p->pListLast; - } else { - ht->pListTail = p->pListLast; - } - if (ht->pInternalPointer == p) { - ht->pInternalPointer = p->pListNext; - } - ht->nNumOfElements--; - if (ht->pDestructor) { - ht->pDestructor(p->pData); - } - if (p->pData != &p->pDataPtr) { - pefree(p->pData, ht->persistent); - } - pefree(p, ht->persistent); - HANDLE_UNBLOCK_INTERRUPTIONS(); + zend_hash_bucket_delete(ht, p); return FAILURE; } } + /* delete another bucket with the same key */ - if (q == ht->arBuckets[q->h & ht->nTableMask]) { - ht->arBuckets[q->h & ht->nTableMask] = q->pNext; - } else { - q->pLast->pNext = q->pNext; - } - if (q->pNext) { - q->pNext->pLast = q->pLast; - } - if (q->pListLast != NULL) { - q->pListLast->pListNext = q->pListNext; - } else { - /* Deleting the head of the list */ - ht->pListHead = q->pListNext; - } - if (q->pListNext != NULL) { - q->pListNext->pListLast = q->pListLast; - } else { - ht->pListTail = q->pListLast; - } - if (ht->pInternalPointer == q) { - ht->pInternalPointer = q->pListNext; - } - ht->nNumOfElements--; - if (ht->pDestructor) { - ht->pDestructor(q->pData); - } - if (q->pData != &q->pDataPtr) { - pefree(q->pData, ht->persistent); - } - pefree(q, ht->persistent); + zend_hash_bucket_delete(ht, q); } + HANDLE_BLOCK_INTERRUPTIONS(); + if (p->pNext) { p->pNext->pLast = p->pLast; }