From ebf900a9ebde4db89802009444e23bf2920f073c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Jan 2018 14:14:35 +0300 Subject: [PATCH] Introduce mcros to access HashTable iterators counter --- Zend/zend_hash.c | 30 +++++++++++++++--------------- Zend/zend_hash.h | 13 ++++++++++++- ext/standard/array.c | 10 +++++----- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 85e7004966..129898c88c 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -319,8 +319,8 @@ ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPositi HashTableIterator *end = iter + EG(ht_iterators_count); uint32_t idx; - if (EXPECTED(ht->u.v.nIteratorsCount != 255)) { - ht->u.v.nIteratorsCount++; + if (EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { + HT_INC_ITERATORS_COUNT(ht); } while (iter != end) { if (iter->ht == NULL) { @@ -359,11 +359,11 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTab return HT_INVALID_IDX; } else if (UNEXPECTED(iter->ht != ht)) { if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR) - && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { - iter->ht->u.v.nIteratorsCount--; + && EXPECTED(!HT_ITERATORS_OVERFLOW(iter->ht))) { + HT_DEC_ITERATORS_COUNT(iter->ht); } - if (EXPECTED(ht->u.v.nIteratorsCount != 255)) { - ht->u.v.nIteratorsCount++; + if (EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { + HT_INC_ITERATORS_COUNT(ht); } iter->ht = ht; iter->pos = ht->nInternalPointer; @@ -381,13 +381,13 @@ ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval return HT_INVALID_IDX; } else if (UNEXPECTED(iter->ht != ht)) { if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR) - && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { - iter->ht->u.v.nIteratorsCount--; + && EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { + HT_DEC_ITERATORS_COUNT(iter->ht); } SEPARATE_ARRAY(array); ht = Z_ARRVAL_P(array); - if (EXPECTED(ht->u.v.nIteratorsCount != 255)) { - ht->u.v.nIteratorsCount++; + if (EXPECTED(!HT_ITERATORS_OVERFLOW(ht))) { + HT_INC_ITERATORS_COUNT(ht); } iter->ht = ht; iter->pos = ht->nInternalPointer; @@ -402,8 +402,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx) ZEND_ASSERT(idx != (uint32_t)-1); if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR) - && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) { - iter->ht->u.v.nIteratorsCount--; + && EXPECTED(!HT_ITERATORS_OVERFLOW(iter->ht))) { + HT_DEC_ITERATORS_COUNT(iter->ht); } iter->ht = NULL; @@ -430,7 +430,7 @@ static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTabl static zend_always_inline void zend_hash_iterators_remove(HashTable *ht) { - if (UNEXPECTED(ht->u.v.nIteratorsCount)) { + if (UNEXPECTED(HT_HAS_ITERATORS(ht))) { _zend_hash_iterators_remove(ht); } } @@ -978,7 +978,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) uint32_t j = i; Bucket *q = p; - if (EXPECTED(ht->u.v.nIteratorsCount == 0)) { + if (EXPECTED(!HT_HAS_ITERATORS(ht))) { while (++i < ht->nNumUsed) { p++; if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) { @@ -1046,7 +1046,7 @@ static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, } while (ht->nNumUsed > 0 && (UNEXPECTED(Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF))); } ht->nNumOfElements--; - if (HT_IDX_TO_HASH(ht->nInternalPointer) == idx || UNEXPECTED(ht->u.v.nIteratorsCount)) { + if (HT_IDX_TO_HASH(ht->nInternalPointer) == idx || UNEXPECTED(HT_HAS_ITERATORS(ht))) { uint32_t new_idx; new_idx = idx = HT_HASH_TO_IDX(idx); diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 7e0fb61ae6..d48e47f0e2 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -58,6 +58,17 @@ # define HT_ALLOW_COW_VIOLATION(ht) #endif +#define HT_ITERATORS_COUNT(ht) (ht)->u.v.nIteratorsCount +#define HT_ITERATORS_OVERFLOW(ht) (HT_ITERATORS_COUNT(ht) == 0xff) +#define HT_HAS_ITERATORS(ht) (HT_ITERATORS_COUNT(ht) != 0) + +#define HT_SET_ITERATORS_COUNT(ht, iters) \ + do { HT_ITERATORS_COUNT(ht) = (iters); } while (0) +#define HT_INC_ITERATORS_COUNT(ht) \ + HT_SET_ITERATORS_COUNT(ht, HT_ITERATORS_COUNT(ht) + 1) +#define HT_DEC_ITERATORS_COUNT(ht) \ + HT_SET_ITERATORS_COUNT(ht, HT_ITERATORS_COUNT(ht) - 1) + extern ZEND_API const HashTable zend_empty_array; #define ZVAL_EMPTY_ARRAY(z) do { \ @@ -295,7 +306,7 @@ ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, H static zend_always_inline void zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to) { - if (UNEXPECTED(ht->u.v.nIteratorsCount)) { + if (UNEXPECTED(HT_HAS_ITERATORS(ht))) { _zend_hash_iterators_update(ht, from, to); } } diff --git a/ext/standard/array.c b/ext/standard/array.c index d6832856b8..3ebf073d11 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -2989,7 +2989,7 @@ static void php_array_data_shuffle(zval *array) /* {{{ */ hash = Z_ARRVAL_P(array); n_left = n_elems; - if (EXPECTED(hash->u.v.nIteratorsCount == 0)) { + if (EXPECTED(!HT_HAS_ITERATORS(hash))) { if (hash->nNumUsed != hash->nNumOfElements) { for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) { p = hash->arData + idx; @@ -3190,7 +3190,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H } /* replace HashTable data */ - in_hash->u.v.nIteratorsCount = 0; + HT_SET_ITERATORS_COUNT(in_hash, 0); in_hash->pDestructor = NULL; zend_hash_destroy(in_hash); @@ -3345,7 +3345,7 @@ PHP_FUNCTION(array_shift) if (HT_FLAGS(Z_ARRVAL_P(stack)) & HASH_FLAG_PACKED) { uint32_t k = 0; - if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) { + if (EXPECTED(!HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) { for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) { p = Z_ARRVAL_P(stack)->arData + idx; if (Z_TYPE(p->val) == IS_UNDEF) continue; @@ -3428,7 +3428,7 @@ PHP_FUNCTION(array_unshift) Z_TRY_ADDREF(args[i]); zend_hash_next_index_insert_new(&new_hash, &args[i]); } - if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) { + if (EXPECTED(!HT_HAS_ITERATORS(Z_ARRVAL_P(stack)))) { ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) { if (key) { zend_hash_add_new(&new_hash, key, value); @@ -3457,7 +3457,7 @@ PHP_FUNCTION(array_unshift) } /* replace HashTable data */ - Z_ARRVAL_P(stack)->u.v.nIteratorsCount = 0; + HT_SET_ITERATORS_COUNT(Z_ARRVAL_P(stack), 0); Z_ARRVAL_P(stack)->pDestructor = NULL; zend_hash_destroy(Z_ARRVAL_P(stack)); -- 2.50.1