ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
{
Bucket *p;
- uint32_t nIndex, i, j;
+ uint32_t nIndex, i;
IS_CONSISTENT(ht);
}
HT_HASH_RESET(ht);
- if (EXPECTED(ht->u.v.nIteratorsCount == 0)) {
- for (i = 0, j = 0; i < ht->nNumUsed; i++) {
- p = ht->arData + i;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (i != j) {
- ht->arData[j] = ht->arData[i];
- if (ht->nInternalPointer == i) {
- ht->nInternalPointer = j;
- }
- }
- nIndex = ht->arData[j].h | ht->nTableMask;
- Z_NEXT(ht->arData[j].val) = HT_HASH(ht, nIndex);
- HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
- j++;
- }
+ i = 0;
+ p = ht->arData;
+ if (ht->nNumUsed == ht->nNumOfElements) {
+ do {
+ nIndex = p->h | ht->nTableMask;
+ Z_NEXT(p->val) = HT_HASH(ht, nIndex);
+ HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
+ p++;
+ } while (++i < ht->nNumUsed);
} else {
- uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, 0);
-
- for (i = 0, j = 0; i < ht->nNumUsed; i++) {
- p = ht->arData + i;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- if (i != j) {
- ht->arData[j] = ht->arData[i];
- if (ht->nInternalPointer == i) {
- ht->nInternalPointer = j;
- }
- if (i == iter_pos) {
- zend_hash_iterators_update(ht, i, j);
- iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1);
+ do {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) {
+ uint32_t j = i;
+ Bucket *q = p;
+
+ if (EXPECTED(ht->u.v.nIteratorsCount == 0)) {
+ while (++i < ht->nNumUsed) {
+ p++;
+ if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
+ ZVAL_COPY_VALUE(&q->val, &p->val);
+ q->h = p->h;
+ nIndex = q->h | ht->nTableMask;
+ q->key = p->key;
+ Z_NEXT(q->val) = HT_HASH(ht, nIndex);
+ HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
+ if (UNEXPECTED(ht->nInternalPointer == i)) {
+ ht->nInternalPointer = j;
+ }
+ q++;
+ j++;
+ }
+ }
+ } else {
+ uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, 0);
+
+ while (++i < ht->nNumUsed) {
+ p++;
+ if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
+ ZVAL_COPY_VALUE(&q->val, &p->val);
+ q->h = p->h;
+ nIndex = q->h | ht->nTableMask;
+ q->key = p->key;
+ Z_NEXT(q->val) = HT_HASH(ht, nIndex);
+ HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
+ if (UNEXPECTED(ht->nInternalPointer == i)) {
+ ht->nInternalPointer = j;
+ }
+ if (UNEXPECTED(i == iter_pos)) {
+ zend_hash_iterators_update(ht, i, j);
+ iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1);
+ }
+ q++;
+ j++;
+ }
+ }
}
+ ht->nNumUsed = j;
+ break;
}
- nIndex = ht->arData[j].h | ht->nTableMask;
- Z_NEXT(ht->arData[j].val) = HT_HASH(ht, nIndex);
- HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
- j++;
- }
+ nIndex = p->h | ht->nTableMask;
+ Z_NEXT(p->val) = HT_HASH(ht, nIndex);
+ HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
+ p++;
+ } while (++i < ht->nNumUsed);
}
- ht->nNumUsed = j;
return SUCCESS;
}
if (HT_IDX_TO_HASH(ht->nNumUsed - 1) == idx) {
do {
ht->nNumUsed--;
- } while (ht->nNumUsed > 0 && (Z_TYPE(ht->arData[ht->nNumUsed-1].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 (Z_TYPE(p->val) == IS_INDIRECT) {
zval *data = Z_INDIRECT(p->val);
- if (Z_TYPE_P(data) == IS_UNDEF) {
+ if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
return FAILURE;
} else {
if (ht->pDestructor) {
if (Z_TYPE(p->val) == IS_INDIRECT) {
zval *data = Z_INDIRECT(p->val);
- if (Z_TYPE_P(data) == IS_UNDEF) {
+ if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
return FAILURE;
} else {
if (ht->pDestructor) {
IS_CONSISTENT(ht);
HT_ASSERT(GC_REFCOUNT(ht) == 1);
- for (idx = 0; idx < ht->nNumUsed; idx++) {
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ p = ht->arData;
+ for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
_zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
}
if (ht->u.flags & HASH_FLAG_INITIALIZED) {
HT_ASSERT(GC_REFCOUNT(ht) == 1);
idx = ht->nNumUsed;
+ p = ht->arData + ht->nNumUsed;
while (idx > 0) {
idx--;
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ p--;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
_zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
}
HT_ASSERT(GC_REFCOUNT(ht) == 1);
HASH_PROTECT_RECURSION(ht);
- for (idx = 0; idx < ht->nNumUsed; idx++) {
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
-
+ p = ht->arData;
+ for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
result = apply_func(&p->val);
if (result & ZEND_HASH_APPLY_REMOVE) {
HT_ASSERT(GC_REFCOUNT(ht) == 1);
HASH_PROTECT_RECURSION(ht);
- for (idx = 0; idx < ht->nNumUsed; idx++) {
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
-
+ p = ht->arData;
+ for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
result = apply_func(&p->val, argument);
if (result & ZEND_HASH_APPLY_REMOVE) {
HASH_PROTECT_RECURSION(ht);
- for (idx = 0; idx < ht->nNumUsed; idx++) {
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ p = ht->arData;
+ for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
va_start(args, num_args);
hash_key.h = p->h;
hash_key.key = p->key;
HASH_PROTECT_RECURSION(ht);
idx = ht->nNumUsed;
+ p = ht->arData + idx;
while (idx > 0) {
idx--;
- p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ p--;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
result = apply_func(&p->val);
setTargetPointer = (target->nInternalPointer == HT_INVALID_IDX);
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
if (setTargetPointer && source->nInternalPointer == idx) {
target->nInternalPointer = HT_INVALID_IDX;
data = &p->val;
if (Z_TYPE_P(data) == IS_INDIRECT) {
data = Z_INDIRECT_P(data);
- if (Z_TYPE_P(data) == IS_UNDEF) {
+ if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
continue;
}
}
ZVAL_UNDEF(&q->val);
continue;
}
- /* INDIRECT element may point to UNDEF-ined slots */
data = &p->val;
- if (Z_TYPE_P(data) == IS_INDIRECT) {
- data = Z_INDIRECT_P(data);
- if (Z_TYPE_P(data) == IS_UNDEF) {
- ZVAL_UNDEF(&q->val);
- continue;
- }
- }
-
q->h = p->h;
q->key = NULL;
if (Z_OPT_REFCOUNTED_P(data)) {
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
/* INDIRECT element may point to UNDEF-ined slots */
data = &p->val;
if (Z_TYPE_P(data) == IS_INDIRECT) {
data = Z_INDIRECT_P(data);
- if (Z_TYPE_P(data) == IS_UNDEF) {
+ if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
continue;
}
}
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
/* INDIRECT element may point to UNDEF-ined slots */
data = &p->val;
if (Z_TYPE_P(data) == IS_INDIRECT) {
data = Z_INDIRECT_P(data);
- if (Z_TYPE_P(data) == IS_UNDEF) {
+ if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
continue;
}
}
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
if (p->key) {
t = _zend_hash_add_or_update(target, p->key, &p->val, mode ZEND_FILE_LINE_RELAY_CC);
if (t && pCopyConstructor) {
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
t = zend_hash_update(target, p->key, &p->val);
if (t && pCopyConstructor) {
} else {
for (j = 0, i = 0; j < ht->nNumUsed; j++) {
p = ht->arData + j;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
if (i != j) {
ht->arData[i] = *p;
}
res = ht->arData + idx;
for (; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
if (flag) {
if (compar(res, p) < 0) { /* max */