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) {
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;
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;
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;
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);
}
}
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)) {
} 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);
# 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 { \
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);
}
}
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;
}
/* 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);
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;
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);
}
/* 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));