PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_hash.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1105 1235 89.5 %
Date: 2016-09-18 Functions: 73 81 90.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      18             :    +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #include "zend.h"
      24             : #include "zend_globals.h"
      25             : #include "zend_variables.h"
      26             : 
      27             : #define HT_DEBUG 0
      28             : #if HT_DEBUG
      29             : # define HT_ASSERT(c) ZEND_ASSERT(c)
      30             : #else
      31             : # define HT_ASSERT(c)
      32             : #endif
      33             : 
      34             : #define HT_POISONED_PTR ((HashTable *) (intptr_t) -1)
      35             : 
      36             : #if ZEND_DEBUG
      37             : /*
      38             : #define HASH_MASK_CONSISTENCY   0xc0
      39             : */
      40             : #define HT_OK                                   0x00
      41             : #define HT_IS_DESTROYING                0x40
      42             : #define HT_DESTROYED                    0x80
      43             : #define HT_CLEANING                             0xc0
      44             : 
      45             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      46             : {
      47             :         if ((ht->u.flags & HASH_MASK_CONSISTENCY) == HT_OK) {
      48             :                 return;
      49             :         }
      50             :         switch ((ht->u.flags & HASH_MASK_CONSISTENCY)) {
      51             :                 case HT_IS_DESTROYING:
      52             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      53             :                         break;
      54             :                 case HT_DESTROYED:
      55             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      56             :                         break;
      57             :                 case HT_CLEANING:
      58             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      59             :                         break;
      60             :                 default:
      61             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      62             :                         break;
      63             :         }
      64             :         zend_bailout();
      65             : }
      66             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      67             : #define SET_INCONSISTENT(n) do { \
      68             :                 (ht)->u.flags |= n; \
      69             :         } while (0)
      70             : #else
      71             : #define IS_CONSISTENT(a)
      72             : #define SET_INCONSISTENT(n)
      73             : #endif
      74             : 
      75             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      76             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      77             :                 if (((ht)->u.flags & ZEND_HASH_APPLY_COUNT_MASK) >= (3 << 8)) {                                                                                         \
      78             :                         zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");\
      79             :                 }                                                                                                                                                               \
      80             :                 ZEND_HASH_INC_APPLY_COUNT(ht);                                                                                                  \
      81             :         }
      82             : 
      83             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      84             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      85             :                 ZEND_HASH_DEC_APPLY_COUNT(ht);                                                                                                  \
      86             :         }
      87             : 
      88             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
      89             :         if ((ht)->nNumUsed >= (ht)->nTableSize) {              \
      90             :                 zend_hash_do_resize(ht);                                        \
      91             :         }
      92             : 
      93             : static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht);
      94             : 
      95             : static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize)
      96             : {
      97             : #if defined(ZEND_WIN32)
      98             :         unsigned long index;
      99             : #endif
     100             : 
     101             :         /* Use big enough power of 2 */
     102             :         /* size should be between HT_MIN_SIZE and HT_MAX_SIZE */
     103    23064504 :         if (nSize < HT_MIN_SIZE) {
     104     6380976 :                 nSize = HT_MIN_SIZE;
     105    16683528 :         } else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
     106           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
     107             :         }
     108             : 
     109             : #if defined(ZEND_WIN32)
     110             :         if (BitScanReverse(&index, nSize - 1)) {
     111             :                 return 0x2 << ((31 - index) ^ 0x1f);
     112             :         } else {
     113             :                 /* nSize is ensured to be in the valid range, fall back to it
     114             :                    rather than using an undefined bis scan result. */
     115             :                 return nSize;
     116             :         }
     117             : #elif (defined(__GNUC__) || __has_builtin(__builtin_clz))  && defined(PHP_HAVE_BUILTIN_CLZ)
     118    23064504 :         return 0x2 << (__builtin_clz(nSize - 1) ^ 0x1f);
     119             : #else
     120             :         nSize -= 1;
     121             :         nSize |= (nSize >> 1);
     122             :         nSize |= (nSize >> 2);
     123             :         nSize |= (nSize >> 4);
     124             :         nSize |= (nSize >> 8);
     125             :         nSize |= (nSize >> 16);
     126             :         return nSize + 1;
     127             : #endif
     128             : }
     129             : 
     130             : static zend_always_inline void zend_hash_real_init_ex(HashTable *ht, int packed)
     131             : {
     132             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     133             :         ZEND_ASSERT(!((ht)->u.flags & HASH_FLAG_INITIALIZED));
     134    11464681 :         if (packed) {
     135     2185650 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     136     2185650 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED;
     137     2185650 :                 HT_HASH_RESET_PACKED(ht);
     138             :         } else {
     139     9279031 :                 (ht)->nTableMask = -(ht)->nTableSize;
     140     9279031 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     141     9279031 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED;
     142     9279031 :                 if (EXPECTED(ht->nTableMask == (uint32_t)-8)) {
     143     8079820 :                         Bucket *arData = ht->arData;
     144             : 
     145     8079820 :                         HT_HASH_EX(arData, -8) = -1;
     146     8079820 :                         HT_HASH_EX(arData, -7) = -1;
     147     8079820 :                         HT_HASH_EX(arData, -6) = -1;
     148     8079820 :                         HT_HASH_EX(arData, -5) = -1;
     149     8079820 :                         HT_HASH_EX(arData, -4) = -1;
     150     8079820 :                         HT_HASH_EX(arData, -3) = -1;
     151     8079820 :                         HT_HASH_EX(arData, -2) = -1;
     152     8079820 :                         HT_HASH_EX(arData, -1) = -1;
     153             :                 } else {
     154     1199211 :                         HT_HASH_RESET(ht);
     155             :                 }
     156             :         }
     157             : }
     158             : 
     159             : static zend_always_inline void zend_hash_check_init(HashTable *ht, int packed)
     160             : {
     161             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     162    11276465 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     163             :                 zend_hash_real_init_ex(ht, packed);
     164             :         }
     165             : }
     166             : 
     167             : #define CHECK_INIT(ht, packed) \
     168             :         zend_hash_check_init(ht, packed)
     169             : 
     170             : static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
     171             :         {HT_INVALID_IDX, HT_INVALID_IDX};
     172             : 
     173    21171486 : ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     174             : {
     175    21171486 :         GC_REFCOUNT(ht) = 1;
     176    21171486 :         GC_TYPE_INFO(ht) = IS_ARRAY;
     177    21171486 :         ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
     178    21171486 :         ht->nTableSize = zend_hash_check_size(nSize);
     179    21171486 :         ht->nTableMask = HT_MIN_MASK;
     180    21171486 :         HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
     181    21171486 :         ht->nNumUsed = 0;
     182    21171486 :         ht->nNumOfElements = 0;
     183    21171486 :         ht->nInternalPointer = HT_INVALID_IDX;
     184    21171486 :         ht->nNextFreeElement = 0;
     185    21171486 :         ht->pDestructor = pDestructor;
     186    21171486 : }
     187             : 
     188       40727 : static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
     189             : {
     190             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     191       40727 :         if (ht->nTableSize >= HT_MAX_SIZE) {
     192           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
     193             :         }
     194       40727 :         ht->nTableSize += ht->nTableSize;
     195       40727 :         HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
     196       40727 : }
     197             : 
     198      188216 : ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, zend_bool packed)
     199             : {
     200             :         IS_CONSISTENT(ht);
     201             : 
     202             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     203      188216 :         zend_hash_real_init_ex(ht, packed);
     204      188216 : }
     205             : 
     206       26876 : ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
     207             : {
     208       26876 :         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     209       26876 :         Bucket *old_buckets = ht->arData;
     210             : 
     211             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     212       26876 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     213       26876 :         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, -ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT);
     214       26876 :         ht->nTableMask = -ht->nTableSize;
     215       26876 :         HT_SET_DATA_ADDR(ht, new_data);
     216       26876 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     217       26876 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     218       26876 :         zend_hash_rehash(ht);
     219       26876 : }
     220             : 
     221          15 : ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
     222             : {
     223          15 :         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     224          15 :         Bucket *old_buckets = ht->arData;
     225             : 
     226             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     227          15 :         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (ht)->u.flags & HASH_FLAG_PERSISTENT);
     228          15 :         ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
     229          15 :         ht->nTableMask = HT_MIN_MASK;
     230          15 :         HT_SET_DATA_ADDR(ht, new_data);
     231          15 :         HT_HASH_RESET_PACKED(ht);
     232          15 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     233          15 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     234          15 : }
     235             : 
     236    14234488 : ZEND_API void ZEND_FASTCALL _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
     237             : {
     238    14234488 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
     239    14234488 :         if (!bApplyProtection) {
     240    14234488 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     241             :         }
     242    14234488 : }
     243             : 
     244     3137727 : ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, zend_bool packed)
     245             : {
     246             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     247     3137727 :         if (nSize == 0) return;
     248     2995540 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     249     1844590 :                 if (nSize > ht->nTableSize) {
     250      886857 :                         ht->nTableSize = zend_hash_check_size(nSize);
     251             :                 }
     252     1844590 :                 zend_hash_check_init(ht, packed);
     253             :         } else {
     254     1150950 :                 if (packed) {
     255             :                         ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED);
     256          98 :                         if (nSize > ht->nTableSize) {
     257          59 :                                 ht->nTableSize = zend_hash_check_size(nSize);
     258          59 :                                 HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
     259             :                         }
     260             :                 } else {
     261             :                         ZEND_ASSERT(!(ht->u.flags & HASH_FLAG_PACKED));
     262     1150852 :                         if (nSize > ht->nTableSize) {
     263     1006102 :                                 void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     264     1006102 :                                 Bucket *old_buckets = ht->arData;
     265     1006102 :                                 nSize = zend_hash_check_size(nSize);
     266     1006102 :                                 new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT);
     267     1006102 :                                 ht->nTableSize = nSize;
     268     1006102 :                                 ht->nTableMask = -ht->nTableSize;
     269     1006102 :                                 HT_SET_DATA_ADDR(ht, new_data);
     270     1006102 :                                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     271     1006102 :                                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     272     1006102 :                                 zend_hash_rehash(ht);
     273             :                         }
     274             :                 }
     275             :         }
     276             : }
     277             : 
     278          43 : static uint32_t zend_array_recalc_elements(HashTable *ht)
     279             : {
     280             :        zval *val;
     281          43 :        uint32_t num = ht->nNumOfElements;
     282             : 
     283         357 :            ZEND_HASH_FOREACH_VAL(ht, val) {
     284         157 :                    if (Z_TYPE_P(val) == IS_UNDEF) continue;
     285         157 :                    if (Z_TYPE_P(val) == IS_INDIRECT) {
     286         228 :                            if (UNEXPECTED(Z_TYPE_P(Z_INDIRECT_P(val)) == IS_UNDEF)) {
     287          51 :                                    num--;
     288             :                            }
     289             :                    }
     290             :        } ZEND_HASH_FOREACH_END();
     291          43 :        return num;
     292             : }
     293             : /* }}} */
     294             : 
     295      264499 : ZEND_API uint32_t zend_array_count(HashTable *ht)
     296             : {
     297             :         uint32_t num;
     298      264499 :         if (UNEXPECTED(ht->u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) {
     299          40 :                 num = zend_array_recalc_elements(ht);
     300          40 :                 if (UNEXPECTED(ht->nNumOfElements == num)) {
     301           0 :                         ht->u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND;
     302             :                 }
     303      264459 :         } else if (UNEXPECTED(ht == &EG(symbol_table))) {
     304           3 :                 num = zend_array_recalc_elements(ht);
     305             :         } else {
     306      264456 :                 num = zend_hash_num_elements(ht);
     307             :         }
     308      264499 :         return num;
     309             : }
     310             : /* }}} */
     311             : 
     312           0 : ZEND_API void ZEND_FASTCALL zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     313             : {
     314           0 :         if (bApplyProtection) {
     315           0 :                 ht->u.flags |= HASH_FLAG_APPLY_PROTECTION;
     316             :         } else {
     317           0 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     318             :         }
     319           0 : }
     320             : 
     321      200984 : ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPosition pos)
     322             : {
     323      200984 :         HashTableIterator *iter = EG(ht_iterators);
     324      200984 :         HashTableIterator *end  = iter + EG(ht_iterators_count);
     325             :         uint32_t idx;
     326             : 
     327      200984 :         if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     328      200984 :                 ht->u.v.nIteratorsCount++;
     329             :         }
     330      402681 :         while (iter != end) {
     331      201697 :                 if (iter->ht == NULL) {
     332      200984 :                         iter->ht = ht;
     333      200984 :                         iter->pos = pos;
     334      200984 :                         idx = iter - EG(ht_iterators);
     335      200984 :                         if (idx + 1 > EG(ht_iterators_used)) {
     336      200981 :                                 EG(ht_iterators_used) = idx + 1;
     337             :                         }
     338      200984 :                         return idx;
     339             :                 }
     340         713 :                 iter++;
     341             :         }
     342           0 :         if (EG(ht_iterators) == EG(ht_iterators_slots)) {
     343           0 :                 EG(ht_iterators) = emalloc(sizeof(HashTableIterator) * (EG(ht_iterators_count) + 8));
     344           0 :                 memcpy(EG(ht_iterators), EG(ht_iterators_slots), sizeof(HashTableIterator) * EG(ht_iterators_count));
     345             :         } else {
     346           0 :                 EG(ht_iterators) = erealloc(EG(ht_iterators), sizeof(HashTableIterator) * (EG(ht_iterators_count) + 8));
     347             :         }
     348           0 :         iter = EG(ht_iterators) + EG(ht_iterators_count);
     349           0 :         EG(ht_iterators_count) += 8;
     350           0 :         iter->ht = ht;
     351           0 :         iter->pos = pos;
     352           0 :         memset(iter + 1, 0, sizeof(HashTableIterator) * 7);
     353           0 :         idx = iter - EG(ht_iterators);
     354           0 :         EG(ht_iterators_used) = idx + 1;
     355           0 :         return idx;
     356             : }
     357             : 
     358         381 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTable *ht)
     359             : {
     360         381 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     361             : 
     362             :         ZEND_ASSERT(idx != (uint32_t)-1);
     363         381 :         if (iter->pos == HT_INVALID_IDX) {
     364          72 :                 return HT_INVALID_IDX;
     365         309 :         } else if (UNEXPECTED(iter->ht != ht)) {
     366           0 :                 if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR)
     367           0 :                                 && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     368           0 :                         iter->ht->u.v.nIteratorsCount--;
     369             :                 }
     370           0 :                 if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     371           0 :                         ht->u.v.nIteratorsCount++;
     372             :                 }
     373           0 :                 iter->ht = ht;
     374           0 :                 iter->pos = ht->nInternalPointer;
     375             :         }
     376         309 :         return iter->pos;
     377             : }
     378             : 
     379        2064 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval *array)
     380             : {
     381        2064 :         HashTable *ht = Z_ARRVAL_P(array);
     382        2064 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     383             : 
     384             :         ZEND_ASSERT(idx != (uint32_t)-1);
     385        2064 :         if (iter->pos == HT_INVALID_IDX) {
     386         362 :                 return HT_INVALID_IDX;
     387        1702 :         } else if (UNEXPECTED(iter->ht != ht)) {
     388           6 :                 if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR)
     389           3 :                                 && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     390           0 :                         iter->ht->u.v.nIteratorsCount--;
     391             :                 }
     392           3 :                 SEPARATE_ARRAY(array);
     393           3 :                 ht = Z_ARRVAL_P(array);
     394           3 :                 if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     395           3 :                         ht->u.v.nIteratorsCount++;
     396             :                 }
     397           3 :                 iter->ht = ht;
     398           3 :                 iter->pos = ht->nInternalPointer;
     399             :         }
     400        1702 :         return iter->pos;
     401             : }
     402             : 
     403      200982 : ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
     404             : {
     405      200982 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     406             : 
     407             :         ZEND_ASSERT(idx != (uint32_t)-1);
     408             : 
     409      602941 :         if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR)
     410      401959 :                         && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     411      200977 :                 iter->ht->u.v.nIteratorsCount--;
     412             :         }
     413      200982 :         iter->ht = NULL;
     414             : 
     415      200982 :         if (idx == EG(ht_iterators_used) - 1) {
     416      401930 :                 while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) {
     417          28 :                         idx--;
     418             :                 }
     419      200951 :                 EG(ht_iterators_used) = idx;
     420             :         }
     421      200982 : }
     422             : 
     423          28 : static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTable *ht)
     424             : {
     425          28 :         HashTableIterator *iter = EG(ht_iterators);
     426          28 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     427             : 
     428          71 :         while (iter != end) {
     429          15 :                 if (iter->ht == ht) {
     430           8 :                         iter->ht = HT_POISONED_PTR;
     431             :                 }
     432          15 :                 iter++;
     433             :         }
     434          28 : }
     435             : 
     436             : static zend_always_inline void zend_hash_iterators_remove(HashTable *ht)
     437             : {
     438    12222610 :         if (UNEXPECTED(ht->u.v.nIteratorsCount)) {
     439          28 :                 _zend_hash_iterators_remove(ht);
     440             :         }
     441             : }
     442             : 
     443         203 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterators_lower_pos(HashTable *ht, HashPosition start)
     444             : {
     445         203 :         HashTableIterator *iter = EG(ht_iterators);
     446         203 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     447         203 :         HashPosition res = HT_INVALID_IDX;
     448             : 
     449         499 :         while (iter != end) {
     450          93 :                 if (iter->ht == ht) {
     451          93 :                         if (iter->pos >= start && iter->pos < res) {
     452          51 :                                 res = iter->pos;
     453             :                         }
     454             :                 }
     455          93 :                 iter++;
     456             :         }
     457         203 :         return res;
     458             : }
     459             : 
     460         251 : ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to)
     461             : {
     462         251 :         HashTableIterator *iter = EG(ht_iterators);
     463         251 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     464             : 
     465         784 :         while (iter != end) {
     466         282 :                 if (iter->ht == ht && iter->pos == from) {
     467          84 :                         iter->pos = to;
     468             :                 }
     469         282 :                 iter++;
     470             :         }
     471         251 : }
     472             : 
     473             : static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
     474             : {
     475             :         zend_ulong h;
     476             :         uint32_t nIndex;
     477             :         uint32_t idx;
     478             :         Bucket *p, *arData;
     479             : 
     480   286282208 :         h = zend_string_hash_val(key);
     481   286282208 :         arData = ht->arData;
     482   286282208 :         nIndex = h | ht->nTableMask;
     483   286282208 :         idx = HT_HASH_EX(arData, nIndex);
     484   452185751 :         while (EXPECTED(idx != HT_INVALID_IDX)) {
     485   181584629 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     486   181584629 :                 if (EXPECTED(p->key == key)) { /* check for the same interned string */
     487    10268097 :                         return p;
     488   187561973 :                 } else if (EXPECTED(p->h == h) &&
     489     5415147 :                      EXPECTED(p->key) &&
     490     5415147 :                      EXPECTED(ZSTR_LEN(p->key) == ZSTR_LEN(key)) &&
     491     5415147 :                      EXPECTED(memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
     492     5412989 :                         return p;
     493             :                 }
     494   165903543 :                 idx = Z_NEXT(p->val);
     495             :         }
     496   270601122 :         return NULL;
     497             : }
     498             : 
     499             : static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
     500             : {
     501             :         uint32_t nIndex;
     502             :         uint32_t idx;
     503             :         Bucket *p, *arData;
     504             : 
     505     3496786 :         arData = ht->arData;
     506     3496786 :         nIndex = h | ht->nTableMask;
     507     3496786 :         idx = HT_HASH_EX(arData, nIndex);
     508     4207308 :         while (idx != HT_INVALID_IDX) {
     509             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     510     3331906 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     511    11196109 :                 if ((p->h == h)
     512             :                          && p->key
     513     5242802 :                          && (ZSTR_LEN(p->key) == len)
     514     2621401 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
     515     2621384 :                         return p;
     516             :                 }
     517      710522 :                 idx = Z_NEXT(p->val);
     518             :         }
     519      875402 :         return NULL;
     520             : }
     521             : 
     522             : static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
     523             : {
     524             :         uint32_t nIndex;
     525             :         uint32_t idx;
     526             :         Bucket *p, *arData;
     527             : 
     528     4669631 :         arData = ht->arData;
     529     4669631 :         nIndex = h | ht->nTableMask;
     530     4669631 :         idx = HT_HASH_EX(arData, nIndex);
     531     6272369 :         while (idx != HT_INVALID_IDX) {
     532             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     533     2661849 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     534     2661849 :                 if (p->h == h && !p->key) {
     535     1059111 :                         return p;
     536             :                 }
     537     1602738 :                 idx = Z_NEXT(p->val);
     538             :         }
     539     3610520 :         return NULL;
     540             : }
     541             : 
     542             : static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     543             : {
     544             :         zend_ulong h;
     545             :         uint32_t nIndex;
     546             :         uint32_t idx;
     547             :         Bucket *p;
     548             : 
     549             :         IS_CONSISTENT(ht);
     550             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     551             : 
     552   229699176 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     553             :                 CHECK_INIT(ht, 0);
     554             :                 goto add_to_hash;
     555   222452785 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     556       25008 :                 zend_hash_packed_to_hash(ht);
     557   222427777 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     558   219592307 :                 p = zend_hash_find_bucket(ht, key);
     559             : 
     560   219592307 :                 if (p) {
     561             :                         zval *data;
     562             : 
     563      593748 :                         if (flag & HASH_ADD) {
     564      299206 :                                 if (!(flag & HASH_UPDATE_INDIRECT)) {
     565      298603 :                                         return NULL;
     566             :                                 }
     567             :                                 ZEND_ASSERT(&p->val != pData);
     568         603 :                                 data = &p->val;
     569         603 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
     570           1 :                                         data = Z_INDIRECT_P(data);
     571           1 :                                         if (Z_TYPE_P(data) != IS_UNDEF) {
     572           0 :                                                 return NULL;
     573             :                                         }
     574             :                                 } else {
     575         602 :                                         return NULL;
     576             :                                 }
     577             :                         } else {
     578             :                                 ZEND_ASSERT(&p->val != pData);
     579      294542 :                                 data = &p->val;
     580      356353 :                                 if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     581         305 :                                         data = Z_INDIRECT_P(data);
     582             :                                 }
     583             :                         }
     584      294543 :                         if (ht->pDestructor) {
     585      246294 :                                 ht->pDestructor(data);
     586             :                         }
     587      294543 :                         ZVAL_COPY_VALUE(data, pData);
     588      294543 :                         return data;
     589             :                 }
     590             :         }
     591             : 
     592   221859037 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     593             : 
     594             : add_to_hash:
     595   229105428 :         idx = ht->nNumUsed++;
     596   229105428 :         ht->nNumOfElements++;
     597   229105428 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     598     7446272 :                 ht->nInternalPointer = idx;
     599             :         }
     600             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     601   229105428 :         p = ht->arData + idx;
     602   229105428 :         p->key = key;
     603   229105428 :         if (!ZSTR_IS_INTERNED(key)) {
     604             :                 zend_string_addref(key);
     605   123170443 :                 ht->u.flags &= ~HASH_FLAG_STATIC_KEYS;
     606             :                 zend_string_hash_val(key);
     607             :         }
     608   229105428 :         p->h = h = ZSTR_H(key);
     609   229105428 :         ZVAL_COPY_VALUE(&p->val, pData);
     610   229105428 :         nIndex = h | ht->nTableMask;
     611   229105428 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     612   229105428 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     613             : 
     614   229105428 :         return &p->val;
     615             : }
     616             : 
     617           0 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     618             : {
     619           0 :         return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     620             : }
     621             : 
     622   195285831 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     623             : {
     624   195285831 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     625             : }
     626             : 
     627     9277156 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     628             : {
     629     9277156 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     630             : }
     631             : 
     632         987 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     633             : {
     634         987 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     635             : }
     636             : 
     637     3295383 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     638             : {
     639     3295383 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     640             : }
     641             : 
     642           0 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     643             : {
     644           0 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     645           0 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     646             :         zend_string_release(key);
     647           0 :         return ret;
     648             : }
     649             : 
     650     1504037 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     651             : {
     652     3008074 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     653     1504037 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     654             :         zend_string_release(key);
     655     1504037 :         return ret;
     656             : }
     657             : 
     658     1541194 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     659             : {
     660     3082388 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     661     1541194 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     662             :         zend_string_release(key);
     663     1541194 :         return ret;
     664             : }
     665             : 
     666    15300383 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     667             : {
     668    30600766 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     669    15300383 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     670             :         zend_string_release(key);
     671    15300383 :         return ret;
     672             : }
     673             : 
     674          47 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     675             : {
     676          94 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     677          47 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     678             :         zend_string_delref(key);
     679          47 :         return ret;
     680             : }
     681             : 
     682          79 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     683             : {
     684             :         zval dummy;
     685             : 
     686          79 :         ZVAL_NULL(&dummy);
     687          79 :         return zend_hash_index_add(ht, h, &dummy);
     688             : }
     689             : 
     690       57213 : ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     691             : {
     692             :         zval dummy;
     693             : 
     694       57213 :         ZVAL_NULL(&dummy);
     695       57213 :         return zend_hash_add(ht, key, &dummy);
     696             : }
     697             : 
     698      609549 : ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
     699             : {
     700             :         zval dummy;
     701             : 
     702      609549 :         ZVAL_NULL(&dummy);
     703      609549 :         return zend_hash_str_add(ht, str, len, &dummy);
     704             : }
     705             : 
     706             : static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     707             : {
     708             :         uint32_t nIndex;
     709             :         uint32_t idx;
     710             :         Bucket *p;
     711             : 
     712             :         IS_CONSISTENT(ht);
     713             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     714             : 
     715     8985400 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     716     2185484 :                 CHECK_INIT(ht, h < ht->nTableSize);
     717     2185484 :                 if (h < ht->nTableSize) {
     718     2080911 :                         p = ht->arData + h;
     719             :                         goto add_to_packed;
     720             :                 }
     721             :                 goto add_to_hash;
     722     6799916 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     723     4003801 :                 if (h < ht->nNumUsed) {
     724        3812 :                         p = ht->arData + h;
     725        7624 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     726        3649 :                                 if (flag & HASH_ADD) {
     727          24 :                                         return NULL;
     728             :                                 }
     729        3625 :                                 if (ht->pDestructor) {
     730        3625 :                                         ht->pDestructor(&p->val);
     731             :                                 }
     732        3625 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     733        3625 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     734           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     735             :                                 }
     736        3625 :                                 return &p->val;
     737             :                         } else { /* we have to keep the order :( */
     738             :                                 goto convert_to_hash;
     739             :                         }
     740     3999989 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     741     3957804 :                         p = ht->arData + h;
     742       84292 :                 } else if ((h >> 1) < ht->nTableSize &&
     743       42107 :                            (ht->nTableSize >> 1) < ht->nNumOfElements) {
     744       40727 :                         zend_hash_packed_grow(ht);
     745       40727 :                         p = ht->arData + h;
     746             :                 } else {
     747             :                         goto convert_to_hash;
     748             :                 }
     749             : 
     750             : add_to_packed:
     751             :                 /* incremental initialization of empty Buckets */
     752     6079442 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     753     1256130 :                         ht->nNumUsed = h + 1;
     754     4823312 :                 } else if (h >= ht->nNumUsed) {
     755     4823312 :                         if (h > ht->nNumUsed) {
     756      908880 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     757     1826662 :                                 while (q != p) {
     758      917782 :                                         ZVAL_UNDEF(&q->val);
     759      917782 :                                         q++;
     760             :                                 }
     761             :                         }
     762     4823312 :                         ht->nNumUsed = h + 1;
     763             :                 }
     764     6079442 :                 ht->nNumOfElements++;
     765     6079442 :                 if (ht->nInternalPointer == HT_INVALID_IDX) {
     766     2133197 :                         ht->nInternalPointer = h;
     767             :                 }
     768     6079442 :                 zend_hash_iterators_update(ht, HT_INVALID_IDX, h);
     769     6079442 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     770     6027261 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     771             :                 }
     772     6079442 :                 p->h = h;
     773     6079442 :                 p->key = NULL;
     774     6079442 :                 ZVAL_COPY_VALUE(&p->val, pData);
     775             : 
     776     6079442 :                 return &p->val;
     777             : 
     778             : convert_to_hash:
     779        1621 :                 zend_hash_packed_to_hash(ht);
     780     2796115 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     781     1695216 :                 p = zend_hash_index_find_bucket(ht, h);
     782     1695216 :                 if (p) {
     783       13718 :                         if (flag & HASH_ADD) {
     784        3466 :                                 return NULL;
     785             :                         }
     786             :                         ZEND_ASSERT(&p->val != pData);
     787       10252 :                         if (ht->pDestructor) {
     788       10207 :                                 ht->pDestructor(&p->val);
     789             :                         }
     790       10252 :                         ZVAL_COPY_VALUE(&p->val, pData);
     791       10252 :                         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     792           1 :                                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     793             :                         }
     794       10252 :                         return &p->val;
     795             :                 }
     796             :         }
     797             : 
     798     2784018 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     799             : 
     800             : add_to_hash:
     801     2888591 :         idx = ht->nNumUsed++;
     802     2888591 :         ht->nNumOfElements++;
     803     2888591 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     804      263343 :                 ht->nInternalPointer = idx;
     805             :         }
     806             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     807     2888591 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     808     1225452 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     809             :         }
     810     2888591 :         p = ht->arData + idx;
     811     2888591 :         p->h = h;
     812     2888591 :         p->key = NULL;
     813     2888591 :         nIndex = h | ht->nTableMask;
     814     2888591 :         ZVAL_COPY_VALUE(&p->val, pData);
     815     2888591 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     816     2888591 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     817             : 
     818     2888591 :         return &p->val;
     819             : }
     820             : 
     821           0 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add_or_update(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     822             : {
     823           0 :         return _zend_hash_index_add_or_update_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
     824             : }
     825             : 
     826        5325 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     827             : {
     828        5325 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     829             : }
     830             : 
     831     1551985 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     832             : {
     833     1551985 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     834             : }
     835             : 
     836     2860238 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     837             : {
     838     2860238 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     839             : }
     840             : 
     841     3311184 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     842             : {
     843     6622368 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     844             : }
     845             : 
     846     1256668 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     847             : {
     848     2513336 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     849             : }
     850             : 
     851     5365403 : static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
     852             : {
     853             : 
     854             :         IS_CONSISTENT(ht);
     855             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     856             : 
     857     5365403 :         if (ht->nNumUsed > ht->nNumOfElements + (ht->nNumOfElements >> 5)) { /* additional term is there to amortize the cost of compaction */
     858      126927 :                 zend_hash_rehash(ht);
     859     5238476 :         } else if (ht->nTableSize < HT_MAX_SIZE) {        /* Let's double the table size */
     860     5238476 :                 void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     861     5238476 :                 uint32_t nSize = ht->nTableSize + ht->nTableSize;
     862     5238476 :                 Bucket *old_buckets = ht->arData;
     863             : 
     864     5238476 :                 new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT);
     865     5238476 :                 ht->nTableSize = nSize;
     866     5238476 :                 ht->nTableMask = -ht->nTableSize;
     867     5238476 :                 HT_SET_DATA_ADDR(ht, new_data);
     868     5238476 :                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     869     5238476 :                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     870     5238476 :                 zend_hash_rehash(ht);
     871             :         } else {
     872           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%u * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
     873             :         }
     874     5365403 : }
     875             : 
     876     6495027 : ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
     877             : {
     878             :         Bucket *p;
     879             :         uint32_t nIndex, i;
     880             : 
     881             :         IS_CONSISTENT(ht);
     882             : 
     883     6495027 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     884           5 :                 if (ht->u.flags & HASH_FLAG_INITIALIZED) {
     885           2 :                         ht->nNumUsed = 0;
     886           2 :                         HT_HASH_RESET(ht);
     887             :                 }
     888           5 :                 return SUCCESS;
     889             :         }
     890             : 
     891     6495022 :         HT_HASH_RESET(ht);
     892     6495022 :         i = 0;
     893     6495022 :         p = ht->arData;
     894     6495022 :         if (ht->nNumUsed == ht->nNumOfElements) {
     895             :                 do {
     896   457221301 :                         nIndex = p->h | ht->nTableMask;
     897   457221301 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     898   457221301 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     899   457221301 :                         p++;
     900   457221301 :                 } while (++i < ht->nNumUsed);
     901             :         } else {
     902             :                 do {
     903     1551334 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) {
     904      129104 :                                 uint32_t j = i;
     905      129104 :                                 Bucket *q = p;
     906             : 
     907      129104 :                                 if (EXPECTED(ht->u.v.nIteratorsCount == 0)) {
     908      969082 :                                         while (++i < ht->nNumUsed) {
     909      710880 :                                                 p++;
     910      710880 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     911      528047 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     912      528047 :                                                         q->h = p->h;
     913      528047 :                                                         nIndex = q->h | ht->nTableMask;
     914      528047 :                                                         q->key = p->key;
     915      528047 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     916      528047 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     917      528047 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     918       26210 :                                                                 ht->nInternalPointer = j;
     919             :                                                         }
     920      528047 :                                                         q++;
     921      528047 :                                                         j++;
     922             :                                                 }
     923             :                                         }
     924             :                                 } else {
     925           3 :                                         uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, 0);
     926             : 
     927          27 :                                         while (++i < ht->nNumUsed) {
     928          21 :                                                 p++;
     929          21 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     930          12 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     931          12 :                                                         q->h = p->h;
     932          12 :                                                         nIndex = q->h | ht->nTableMask;
     933          12 :                                                         q->key = p->key;
     934          12 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     935          12 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     936          12 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     937           3 :                                                                 ht->nInternalPointer = j;
     938             :                                                         }
     939          12 :                                                         if (UNEXPECTED(i == iter_pos)) {
     940             :                                                                 zend_hash_iterators_update(ht, i, j);
     941           5 :                                                                 iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1);
     942             :                                                         }
     943          12 :                                                         q++;
     944          12 :                                                         j++;
     945             :                                                 }
     946             :                                         }
     947             :                                 }
     948      129104 :                                 ht->nNumUsed = j;
     949      129104 :                                 break;
     950             :                         }
     951      646563 :                         nIndex = p->h | ht->nTableMask;
     952      646563 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     953      646563 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     954      646563 :                         p++;
     955      646563 :                 } while (++i < ht->nNumUsed);
     956             :         }
     957     6495022 :         return SUCCESS;
     958             : }
     959             : 
     960             : static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
     961             : {
     962    64994376 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     963    64774433 :                 if (prev) {
     964     3865202 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     965             :                 } else {
     966    60909231 :                         HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val);
     967             :                 }
     968             :         }
     969    64994376 :         if (HT_IDX_TO_HASH(ht->nNumUsed - 1) == idx) {
     970             :                 do {
     971     5126486 :                         ht->nNumUsed--;
     972     9912976 :                 } while (ht->nNumUsed > 0 && (UNEXPECTED(Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF)));
     973             :         }
     974    64994376 :         ht->nNumOfElements--;
     975    64994376 :         if (HT_IDX_TO_HASH(ht->nInternalPointer) == idx || UNEXPECTED(ht->u.v.nIteratorsCount)) {
     976             :                 uint32_t new_idx;
     977             : 
     978     3986415 :                 new_idx = idx = HT_HASH_TO_IDX(idx);
     979             :                 while (1) {
     980    57200833 :                         new_idx++;
     981    57200833 :                         if (new_idx >= ht->nNumUsed) {
     982      292170 :                                 new_idx = HT_INVALID_IDX;
     983             :                                 break;
     984   113817326 :                         } else if (Z_TYPE(ht->arData[new_idx].val) != IS_UNDEF) {
     985             :                                 break;
     986             :                         }
     987             :                 }
     988     3986415 :                 if (ht->nInternalPointer == idx) {
     989     3986376 :                         ht->nInternalPointer = new_idx;
     990             :                 }
     991             :                 zend_hash_iterators_update(ht, idx, new_idx);
     992             :         }
     993    64994376 :         if (p->key) {
     994    63973161 :                 zend_string_release(p->key);
     995             :         }
     996    64994376 :         if (ht->pDestructor) {
     997             :                 zval tmp;
     998    64075732 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     999    64075732 :                 ZVAL_UNDEF(&p->val);
    1000    64075732 :                 ht->pDestructor(&tmp);
    1001             :         } else {
    1002      918644 :                 ZVAL_UNDEF(&p->val);
    1003             :         }
    1004             : }
    1005             : 
    1006             : static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
    1007             : {
    1008     8849642 :         Bucket *prev = NULL;
    1009             : 
    1010     8849642 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1011     8845561 :                 uint32_t nIndex = p->h | ht->nTableMask;
    1012     8845561 :                 uint32_t i = HT_HASH(ht, nIndex);
    1013             : 
    1014     8845561 :                 if (i != idx) {
    1015      388018 :                         prev = HT_HASH_TO_BUCKET(ht, i);
    1016      459676 :                         while (Z_NEXT(prev->val) != idx) {
    1017       71658 :                                 i = Z_NEXT(prev->val);
    1018       71658 :                                 prev = HT_HASH_TO_BUCKET(ht, i);
    1019             :                         }
    1020             :                 }
    1021             :         }
    1022             : 
    1023             :         _zend_hash_del_el_ex(ht, idx, p, prev);
    1024             : }
    1025             : 
    1026          76 : ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p)
    1027             : {
    1028             :         IS_CONSISTENT(ht);
    1029             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1030          76 :         _zend_hash_del_el(ht, HT_IDX_TO_HASH(p - ht->arData), p);
    1031          76 : }
    1032             : 
    1033    55414307 : ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
    1034             : {
    1035             :         zend_ulong h;
    1036             :         uint32_t nIndex;
    1037             :         uint32_t idx;
    1038             :         Bucket *p;
    1039    55414307 :         Bucket *prev = NULL;
    1040             : 
    1041             :         IS_CONSISTENT(ht);
    1042             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1043             : 
    1044    55414307 :         h = zend_string_hash_val(key);
    1045    55414307 :         nIndex = h | ht->nTableMask;
    1046             : 
    1047    55414307 :         idx = HT_HASH(ht, nIndex);
    1048   114492889 :         while (idx != HT_INVALID_IDX) {
    1049    57978911 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1050   278766624 :                 if ((p->key == key) ||
    1051    57945100 :                         (p->h == h &&
    1052    54280871 :                      p->key &&
    1053    54280871 :                      ZSTR_LEN(p->key) == ZSTR_LEN(key) &&
    1054    54280871 :                      memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
    1055             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1056    54314636 :                         return SUCCESS;
    1057             :                 }
    1058     3664275 :                 prev = p;
    1059     3664275 :                 idx = Z_NEXT(p->val);
    1060             :         }
    1061     1099671 :         return FAILURE;
    1062             : }
    1063             : 
    1064         501 : ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key)
    1065             : {
    1066             :         zend_ulong h;
    1067             :         uint32_t nIndex;
    1068             :         uint32_t idx;
    1069             :         Bucket *p;
    1070         501 :         Bucket *prev = NULL;
    1071             : 
    1072             :         IS_CONSISTENT(ht);
    1073             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1074             : 
    1075         501 :         h = zend_string_hash_val(key);
    1076         501 :         nIndex = h | ht->nTableMask;
    1077             : 
    1078         501 :         idx = HT_HASH(ht, nIndex);
    1079        1010 :         while (idx != HT_INVALID_IDX) {
    1080         297 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1081        1305 :                 if ((p->key == key) ||
    1082         258 :                         (p->h == h &&
    1083         250 :                      p->key &&
    1084         250 :                      ZSTR_LEN(p->key) == ZSTR_LEN(key) &&
    1085         250 :                      memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
    1086         578 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
    1087          15 :                                 zval *data = Z_INDIRECT(p->val);
    1088             : 
    1089          15 :                                 if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1090           0 :                                         return FAILURE;
    1091             :                                 } else {
    1092          15 :                                         if (ht->pDestructor) {
    1093             :                                                 zval tmp;
    1094          15 :                                                 ZVAL_COPY_VALUE(&tmp, data);
    1095          15 :                                                 ZVAL_UNDEF(data);
    1096          15 :                                                 ht->pDestructor(&tmp);
    1097             :                                         } else {
    1098           0 :                                                 ZVAL_UNDEF(data);
    1099             :                                         }
    1100          15 :                                         ht->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
    1101             :                                 }
    1102             :                         } else {
    1103             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
    1104             :                         }
    1105         289 :                         return SUCCESS;
    1106             :                 }
    1107           8 :                 prev = p;
    1108           8 :                 idx = Z_NEXT(p->val);
    1109             :         }
    1110         212 :         return FAILURE;
    1111             : }
    1112             : 
    1113           0 : ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
    1114             : {
    1115             :         zend_ulong h;
    1116             :         uint32_t nIndex;
    1117             :         uint32_t idx;
    1118             :         Bucket *p;
    1119           0 :         Bucket *prev = NULL;
    1120             : 
    1121             :         IS_CONSISTENT(ht);
    1122             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1123             : 
    1124           0 :         h = zend_inline_hash_func(str, len);
    1125           0 :         nIndex = h | ht->nTableMask;
    1126             : 
    1127           0 :         idx = HT_HASH(ht, nIndex);
    1128           0 :         while (idx != HT_INVALID_IDX) {
    1129           0 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1130           0 :                 if ((p->h == h)
    1131             :                          && p->key
    1132           0 :                          && (ZSTR_LEN(p->key) == len)
    1133           0 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
    1134           0 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
    1135           0 :                                 zval *data = Z_INDIRECT(p->val);
    1136             : 
    1137           0 :                                 if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1138           0 :                                         return FAILURE;
    1139             :                                 } else {
    1140           0 :                                         if (ht->pDestructor) {
    1141           0 :                                                 ht->pDestructor(data);
    1142             :                                         }
    1143           0 :                                         ZVAL_UNDEF(data);
    1144           0 :                                         ht->u.v.flags |= HASH_FLAG_HAS_EMPTY_IND;
    1145             :                                 }
    1146             :                         } else {
    1147             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
    1148             :                         }
    1149           0 :                         return SUCCESS;
    1150             :                 }
    1151           0 :                 prev = p;
    1152           0 :                 idx = Z_NEXT(p->val);
    1153             :         }
    1154           0 :         return FAILURE;
    1155             : }
    1156             : 
    1157      842611 : ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
    1158             : {
    1159             :         zend_ulong h;
    1160             :         uint32_t nIndex;
    1161             :         uint32_t idx;
    1162             :         Bucket *p;
    1163      842611 :         Bucket *prev = NULL;
    1164             : 
    1165             :         IS_CONSISTENT(ht);
    1166             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1167             : 
    1168      842611 :         h = zend_inline_hash_func(str, len);
    1169      842611 :         nIndex = h | ht->nTableMask;
    1170             : 
    1171      842611 :         idx = HT_HASH(ht, nIndex);
    1172     1709713 :         while (idx != HT_INVALID_IDX) {
    1173      840120 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1174     3287007 :                 if ((p->h == h)
    1175             :                          && p->key
    1176     1631258 :                          && (ZSTR_LEN(p->key) == len)
    1177      815629 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
    1178             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1179      815629 :                         return SUCCESS;
    1180             :                 }
    1181       24491 :                 prev = p;
    1182       24491 :                 idx = Z_NEXT(p->val);
    1183             :         }
    1184       26982 :         return FAILURE;
    1185             : }
    1186             : 
    1187     1026890 : ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
    1188             : {
    1189             :         uint32_t nIndex;
    1190             :         uint32_t idx;
    1191             :         Bucket *p;
    1192     1026890 :         Bucket *prev = NULL;
    1193             : 
    1194             :         IS_CONSISTENT(ht);
    1195             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1196             : 
    1197     1026890 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1198      222043 :                 if (h < ht->nNumUsed) {
    1199      215873 :                         p = ht->arData + h;
    1200      431746 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1201      215862 :                                 _zend_hash_del_el_ex(ht, HT_IDX_TO_HASH(h), p, NULL);
    1202      215862 :                                 return SUCCESS;
    1203             :                         }
    1204             :                 }
    1205        6181 :                 return FAILURE;
    1206             :         }
    1207      804847 :         nIndex = h | ht->nTableMask;
    1208             : 
    1209      804847 :         idx = HT_HASH(ht, nIndex);
    1210     1611156 :         while (idx != HT_INVALID_IDX) {
    1211      799795 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1212      799795 :                 if ((p->h == h) && (p->key == NULL)) {
    1213             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1214      798333 :                         return SUCCESS;
    1215             :                 }
    1216        1462 :                 prev = p;
    1217        1462 :                 idx = Z_NEXT(p->val);
    1218             :         }
    1219        6514 :         return FAILURE;
    1220             : }
    1221             : 
    1222    12628409 : ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
    1223             : {
    1224             :         Bucket *p, *end;
    1225             : 
    1226             :         IS_CONSISTENT(ht);
    1227             :         HT_ASSERT(GC_REFCOUNT(ht) <= 1);
    1228             : 
    1229    12628409 :         if (ht->nNumUsed) {
    1230     8628942 :                 p = ht->arData;
    1231     8628942 :                 end = p + ht->nNumUsed;
    1232     8628942 :                 if (ht->pDestructor) {
    1233             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
    1234             : 
    1235     8259975 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1236     5093680 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1237             :                                         do {
    1238   186062998 :                                                 ht->pDestructor(&p->val);
    1239   186062998 :                                         } while (++p != end);
    1240             :                                 } else {
    1241             :                                         do {
    1242   111905316 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1243     1942621 :                                                         ht->pDestructor(&p->val);
    1244             :                                                 }
    1245    55952658 :                                         } while (++p != end);
    1246             :                                 }
    1247     3166295 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1248             :                                 do {
    1249   107389596 :                                         ht->pDestructor(&p->val);
    1250   107389596 :                                         if (EXPECTED(p->key)) {
    1251   107383215 :                                                 zend_string_release(p->key);
    1252             :                                         }
    1253   107389596 :                                 } while (++p != end);
    1254             :                         } else {
    1255             :                                 do {
    1256    11672700 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1257      311909 :                                                 ht->pDestructor(&p->val);
    1258      311909 :                                                 if (EXPECTED(p->key)) {
    1259      311909 :                                                         zend_string_release(p->key);
    1260             :                                                 }
    1261             :                                         }
    1262     5836350 :                                 } while (++p != end);
    1263             :                         }
    1264             : 
    1265             :                         SET_INCONSISTENT(HT_DESTROYED);
    1266             :                 } else {
    1267      368967 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1268             :                                 do {
    1269    23996744 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1270    11902517 :                                                 if (EXPECTED(p->key)) {
    1271    11901722 :                                                         zend_string_release(p->key);
    1272             :                                                 }
    1273             :                                         }
    1274    11998372 :                                 } while (++p != end);
    1275             :                         }
    1276             :                 }
    1277             :                 zend_hash_iterators_remove(ht);
    1278     3999467 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1279     3920495 :                 return;
    1280             :         }
    1281     8707914 :         pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1282             : }
    1283             : 
    1284     6327866 : ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
    1285             : {
    1286             :         Bucket *p, *end;
    1287             : 
    1288             :         IS_CONSISTENT(ht);
    1289             :         HT_ASSERT(GC_REFCOUNT(ht) <= 1);
    1290             : 
    1291             :         /* break possible cycles */
    1292     6327866 :         GC_REMOVE_FROM_BUFFER(ht);
    1293     6327866 :         GC_TYPE_INFO(ht) = IS_NULL | (GC_WHITE << 16);
    1294             : 
    1295     6327866 :         if (ht->nNumUsed) {
    1296             :                 /* In some rare cases destructors of regular arrays may be changed */
    1297     3593743 :                 if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
    1298          74 :                         zend_hash_destroy(ht);
    1299          74 :                         goto free_ht;
    1300             :                 }
    1301             : 
    1302     3593669 :                 p = ht->arData;
    1303     3593669 :                 end = p + ht->nNumUsed;
    1304             :                 SET_INCONSISTENT(HT_IS_DESTROYING);
    1305             : 
    1306     3593669 :                 if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1307             :                         do {
    1308     8149983 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1309     8149982 :                         } while (++p != end);
    1310      841495 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1311             :                         do {
    1312     5910272 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1313     5910272 :                                 if (EXPECTED(p->key)) {
    1314     5837031 :                                         zend_string_release(p->key);
    1315             :                                 }
    1316     5910272 :                         } while (++p != end);
    1317             :                 } else {
    1318             :                         do {
    1319        4542 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1320        1971 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1321        1971 :                                         if (EXPECTED(p->key)) {
    1322        1912 :                                                 zend_string_release(p->key);
    1323             :                                         }
    1324             :                                 }
    1325        2271 :                         } while (++p != end);
    1326             :                 }
    1327             :                 zend_hash_iterators_remove(ht);
    1328             :                 SET_INCONSISTENT(HT_DESTROYED);
    1329     2734123 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1330     2731528 :                 goto free_ht;
    1331             :         }
    1332     3596263 :         efree(HT_GET_DATA_ADDR(ht));
    1333             : free_ht:
    1334     6327865 :         FREE_HASHTABLE(ht);
    1335     6327865 : }
    1336             : 
    1337      105873 : ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
    1338             : {
    1339             :         Bucket *p, *end;
    1340             : 
    1341             :         IS_CONSISTENT(ht);
    1342             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1343             : 
    1344      105873 :         if (ht->nNumUsed) {
    1345        9602 :                 p = ht->arData;
    1346        9602 :                 end = p + ht->nNumUsed;
    1347        9602 :                 if (ht->pDestructor) {
    1348        4375 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1349        1206 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1350             :                                         do {
    1351      607287 :                                                 ht->pDestructor(&p->val);
    1352      607287 :                                         } while (++p != end);
    1353             :                                 } else {
    1354             :                                         do {
    1355         120 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1356          12 :                                                         ht->pDestructor(&p->val);
    1357             :                                                 }
    1358          60 :                                         } while (++p != end);
    1359             :                                 }
    1360        3169 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1361             :                                 do {
    1362     1857301 :                                         ht->pDestructor(&p->val);
    1363     1857301 :                                         if (EXPECTED(p->key)) {
    1364     1857301 :                                                 zend_string_release(p->key);
    1365             :                                         }
    1366     1857301 :                                 } while (++p != end);
    1367             :                         } else {
    1368             :                                 do {
    1369           0 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1370           0 :                                                 ht->pDestructor(&p->val);
    1371           0 :                                                 if (EXPECTED(p->key)) {
    1372           0 :                                                         zend_string_release(p->key);
    1373             :                                                 }
    1374             :                                         }
    1375           0 :                                 } while (++p != end);
    1376             :                         }
    1377             :                 } else {
    1378        5227 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1379        4603 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1380             :                                         do {
    1381       27573 :                                                 if (EXPECTED(p->key)) {
    1382       27573 :                                                         zend_string_release(p->key);
    1383             :                                                 }
    1384       27573 :                                         } while (++p != end);
    1385             :                                 } else {
    1386             :                                         do {
    1387           0 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1388           0 :                                                         if (EXPECTED(p->key)) {
    1389           0 :                                                                 zend_string_release(p->key);
    1390             :                                                         }
    1391             :                                                 }
    1392           0 :                                         } while (++p != end);
    1393             :                                 }
    1394             :                         }
    1395             :                 }
    1396        9602 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1397        9583 :                         HT_HASH_RESET(ht);
    1398             :                 }
    1399             :         }
    1400      105873 :         ht->nNumUsed = 0;
    1401      105873 :         ht->nNumOfElements = 0;
    1402      105873 :         ht->nNextFreeElement = 0;
    1403      105873 :         ht->nInternalPointer = HT_INVALID_IDX;
    1404      105873 : }
    1405             : 
    1406         440 : ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
    1407             : {
    1408             :         Bucket *p, *end;
    1409             : 
    1410             :         IS_CONSISTENT(ht);
    1411             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1412             : 
    1413         440 :         if (ht->nNumUsed) {
    1414         421 :                 p = ht->arData;
    1415         421 :                 end = p + ht->nNumUsed;
    1416         421 :                 if (ht->u.flags & HASH_FLAG_STATIC_KEYS) {
    1417             :                         do {
    1418        2131 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1419        2131 :                         } while (++p != end);
    1420          81 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1421             :                         do {
    1422         577 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1423         577 :                                 zend_string_release(p->key);
    1424         577 :                         } while (++p != end);
    1425             :                 } else {
    1426             :                         do {
    1427           0 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1428           0 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1429           0 :                                         zend_string_release(p->key);
    1430             :                                 }
    1431           0 :                         } while (++p != end);
    1432             :                 }
    1433         421 :                 HT_HASH_RESET(ht);
    1434             :         }
    1435         440 :         ht->nNumUsed = 0;
    1436         440 :         ht->nNumOfElements = 0;
    1437         440 :         ht->nNextFreeElement = 0;
    1438         440 :         ht->nInternalPointer = HT_INVALID_IDX;
    1439         440 : }
    1440             : 
    1441           0 : ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht)
    1442             : {
    1443             :         uint32_t idx;
    1444             :         Bucket *p;
    1445             : 
    1446             :         IS_CONSISTENT(ht);
    1447             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1448             : 
    1449           0 :         p = ht->arData;
    1450           0 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1451           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1452             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1453             :         }
    1454           0 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1455           0 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1456             :         }
    1457             : 
    1458             :         SET_INCONSISTENT(HT_DESTROYED);
    1459           0 : }
    1460             : 
    1461       95886 : ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht)
    1462             : {
    1463             :         uint32_t idx;
    1464             :         Bucket *p;
    1465             : 
    1466             :         IS_CONSISTENT(ht);
    1467             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1468             : 
    1469       95886 :         idx = ht->nNumUsed;
    1470       95886 :         p = ht->arData + ht->nNumUsed;
    1471     2275328 :         while (idx > 0) {
    1472     2083556 :                 idx--;
    1473     2083556 :                 p--;
    1474     4167112 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1475             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1476             :         }
    1477             : 
    1478       95886 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1479       72471 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1480             :         }
    1481             : 
    1482             :         SET_INCONSISTENT(HT_DESTROYED);
    1483       95886 : }
    1484             : 
    1485             : /* This is used to recurse elements and selectively delete certain entries
    1486             :  * from a hashtable. apply_func() receives the data and decides if the entry
    1487             :  * should be deleted or recursion should be stopped. The following three
    1488             :  * return codes are possible:
    1489             :  * ZEND_HASH_APPLY_KEEP   - continue
    1490             :  * ZEND_HASH_APPLY_STOP   - stop iteration
    1491             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
    1492             :  */
    1493             : 
    1494      358274 : ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
    1495             : {
    1496             :         uint32_t idx;
    1497             :         Bucket *p;
    1498             :         int result;
    1499             : 
    1500             :         IS_CONSISTENT(ht);
    1501             : 
    1502      358274 :         HASH_PROTECT_RECURSION(ht);
    1503     2884420 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1504     2526151 :                 p = ht->arData + idx;
    1505     5052302 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1506     2301650 :                 result = apply_func(&p->val);
    1507             : 
    1508     2301645 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1509             :                         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1510             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1511             :                 }
    1512     2301645 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1513           0 :                         break;
    1514             :                 }
    1515             :         }
    1516      358269 :         HASH_UNPROTECT_RECURSION(ht);
    1517      358269 : }
    1518             : 
    1519             : 
    1520      709607 : ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
    1521             : {
    1522             :     uint32_t idx;
    1523             :         Bucket *p;
    1524             :         int result;
    1525             : 
    1526             :         IS_CONSISTENT(ht);
    1527             : 
    1528      709607 :         HASH_PROTECT_RECURSION(ht);
    1529   165236263 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1530   164531013 :                 p = ht->arData + idx;
    1531   329062026 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1532   117040450 :                 result = apply_func(&p->val, argument);
    1533             : 
    1534   117040450 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1535             :                         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1536             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1537             :                 }
    1538   117040450 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1539        4357 :                         break;
    1540             :                 }
    1541             :         }
    1542      709607 :         HASH_UNPROTECT_RECURSION(ht);
    1543      709607 : }
    1544             : 
    1545             : 
    1546         177 : ZEND_API void ZEND_FASTCALL zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args, ...)
    1547             : {
    1548             :         uint32_t idx;
    1549             :         Bucket *p;
    1550             :         va_list args;
    1551             :         zend_hash_key hash_key;
    1552             :         int result;
    1553             : 
    1554             :         IS_CONSISTENT(ht);
    1555             : 
    1556         177 :         HASH_PROTECT_RECURSION(ht);
    1557             : 
    1558      166536 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1559      166359 :                 p = ht->arData + idx;
    1560      332718 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1561      166293 :                 va_start(args, num_args);
    1562      166293 :                 hash_key.h = p->h;
    1563      166293 :                 hash_key.key = p->key;
    1564             : 
    1565      166293 :                 result = apply_func(&p->val, num_args, args, &hash_key);
    1566             : 
    1567      166293 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1568             :                         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1569             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1570             :                 }
    1571      166293 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1572           0 :                         va_end(args);
    1573           0 :                         break;
    1574             :                 }
    1575      166293 :                 va_end(args);
    1576             :         }
    1577             : 
    1578         177 :         HASH_UNPROTECT_RECURSION(ht);
    1579         177 : }
    1580             : 
    1581             : 
    1582      125076 : ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func)
    1583             : {
    1584             :         uint32_t idx;
    1585             :         Bucket *p;
    1586             :         int result;
    1587             : 
    1588             :         IS_CONSISTENT(ht);
    1589             : 
    1590      125076 :         HASH_PROTECT_RECURSION(ht);
    1591      125076 :         idx = ht->nNumUsed;
    1592      900938 :         while (idx > 0) {
    1593      722543 :                 idx--;
    1594      722543 :                 p = ht->arData + idx;
    1595     1445086 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1596             : 
    1597      666485 :                 result = apply_func(&p->val);
    1598             : 
    1599      666485 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1600             :                         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1601             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1602             :                 }
    1603      666485 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1604       71757 :                         break;
    1605             :                 }
    1606             :         }
    1607      125076 :         HASH_UNPROTECT_RECURSION(ht);
    1608      125076 : }
    1609             : 
    1610             : 
    1611         476 : ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
    1612             : {
    1613             :     uint32_t idx;
    1614             :         Bucket *p;
    1615             :         zval *new_entry, *data;
    1616             :         zend_bool setTargetPointer;
    1617             : 
    1618             :         IS_CONSISTENT(source);
    1619             :         IS_CONSISTENT(target);
    1620             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1621             : 
    1622         476 :         setTargetPointer = (target->nInternalPointer == HT_INVALID_IDX);
    1623       12208 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1624       11732 :                 p = source->arData + idx;
    1625       23464 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1626             : 
    1627       11732 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1628         331 :                         target->nInternalPointer = HT_INVALID_IDX;
    1629             :                 }
    1630             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1631       11732 :                 data = &p->val;
    1632       11732 :                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1633         115 :                         data = Z_INDIRECT_P(data);
    1634         115 :                         if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1635           4 :                                 continue;
    1636             :                         }
    1637             :                 }
    1638       11728 :                 if (p->key) {
    1639       11636 :                         new_entry = zend_hash_update(target, p->key, data);
    1640             :                 } else {
    1641          92 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1642             :                 }
    1643       11728 :                 if (pCopyConstructor) {
    1644         275 :                         pCopyConstructor(new_entry);
    1645             :                 }
    1646             :         }
    1647         476 :         if (target->nInternalPointer == HT_INVALID_IDX && target->nNumOfElements > 0) {
    1648           0 :                 idx = 0;
    1649           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1650           0 :                         idx++;
    1651             :                 }
    1652           0 :                 target->nInternalPointer = idx;
    1653             :         }
    1654         476 : }
    1655             : 
    1656             : 
    1657             : static zend_always_inline int zend_array_dup_element(HashTable *source, HashTable *target, uint32_t idx, Bucket *p, Bucket *q, int packed, int static_keys, int with_holes)
    1658             : {
    1659     3293723 :         zval *data = &p->val;
    1660             : 
    1661     3293723 :         if (with_holes) {
    1662     2448133 :                 if (!packed && Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1663           0 :                         data = Z_INDIRECT_P(data);
    1664             :                 }
    1665     2448133 :                 if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1666      815133 :                         return 0;
    1667             :                 }
    1668      845590 :         } else if (!packed) {
    1669             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1670      786535 :                 if (Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1671       21374 :                         data = Z_INDIRECT_P(data);
    1672       21374 :                         if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1673        3145 :                                 return 0;
    1674             :                         }
    1675             :                 }
    1676             :         }
    1677             : 
    1678             :         do {
    1679     2475445 :                 if (Z_OPT_REFCOUNTED_P(data)) {
    1680     2450304 :                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1 &&
    1681          71 :                             (Z_TYPE_P(Z_REFVAL_P(data)) != IS_ARRAY ||
    1682          20 :                               Z_ARRVAL_P(Z_REFVAL_P(data)) != source)) {
    1683          68 :                                 data = Z_REFVAL_P(data);
    1684          68 :                                 if (!Z_OPT_REFCOUNTED_P(data)) {
    1685             :                                         break;
    1686             :                                 }
    1687             :                         }
    1688             :                         Z_ADDREF_P(data);
    1689             :                 }
    1690             :         } while (0);
    1691     2475445 :         ZVAL_COPY_VALUE(&q->val, data);
    1692             : 
    1693     2475445 :         q->h = p->h;
    1694     2475445 :         if (packed) {
    1695     1692051 :                 q->key = NULL;
    1696             :         } else {
    1697             :                 uint32_t nIndex;
    1698             : 
    1699      783394 :                 q->key = p->key;
    1700      783394 :                 if (!static_keys && q->key) {
    1701      779994 :                         zend_string_addref(q->key);
    1702             :                 }
    1703             : 
    1704      783394 :                 nIndex = q->h | target->nTableMask;
    1705      783394 :                 Z_NEXT(q->val) = HT_HASH(target, nIndex);
    1706      783394 :                 HT_HASH(target, nIndex) = HT_IDX_TO_HASH(idx);
    1707             :         }
    1708     2475445 :         return 1;
    1709             : }
    1710             : 
    1711             : static zend_always_inline void zend_array_dup_packed_elements(HashTable *source, HashTable *target, int with_holes)
    1712             : {
    1713      838052 :         Bucket *p = source->arData;
    1714      838052 :         Bucket *q = target->arData;
    1715      838052 :         Bucket *end = p + source->nNumUsed;
    1716             : 
    1717             :         do {
    1718     2507182 :                 if (!zend_array_dup_element(source, target, 0, p, q, 1, 1, with_holes)) {
    1719      815131 :                         if (with_holes) {
    1720      815131 :                                 ZVAL_UNDEF(&q->val);
    1721             :                         }
    1722             :                 }
    1723     2507182 :                 p++; q++;
    1724     2507182 :         } while (p != end);
    1725             : }
    1726             : 
    1727             : static zend_always_inline uint32_t zend_array_dup_elements(HashTable *source, HashTable *target, int static_keys, int with_holes)
    1728             : {
    1729       36715 :     uint32_t idx = 0;
    1730       36715 :         Bucket *p = source->arData;
    1731       36715 :         Bucket *q = target->arData;
    1732       36715 :         Bucket *end = p + source->nNumUsed;
    1733             : 
    1734             :         do {
    1735      773731 :                 if (!zend_array_dup_element(source, target, idx, p, q, 0, static_keys, with_holes)) {
    1736        2170 :                         uint32_t target_idx = idx;
    1737             : 
    1738        2170 :                         idx++; p++;
    1739       14980 :                         while (p != end) {
    1740       12810 :                                 if (zend_array_dup_element(source, target, target_idx, p, q, 0, static_keys, with_holes)) {
    1741       11833 :                                         if (source->nInternalPointer == idx) {
    1742           0 :                                                 target->nInternalPointer = target_idx;
    1743             :                                         }
    1744       11833 :                                         target_idx++; q++;
    1745             :                                 }
    1746       12810 :                                 idx++; p++;
    1747             :                         }
    1748        2170 :                         return target_idx;
    1749             :                 }
    1750      771561 :                 idx++; p++; q++;
    1751      771561 :         } while (p != end);
    1752       34545 :         return idx;
    1753             : }
    1754             : 
    1755     1386016 : ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
    1756             : {
    1757             :     uint32_t idx;
    1758             :         HashTable *target;
    1759             : 
    1760             :         IS_CONSISTENT(source);
    1761             : 
    1762     1386016 :         ALLOC_HASHTABLE(target);
    1763     1386016 :         GC_REFCOUNT(target) = 1;
    1764     1386016 :         GC_TYPE_INFO(target) = IS_ARRAY;
    1765             : 
    1766     1386016 :         target->nTableSize = source->nTableSize;
    1767     1386016 :         target->pDestructor = source->pDestructor;
    1768             : 
    1769     1386016 :         if (source->nNumUsed == 0) {
    1770      511224 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED|HASH_FLAG_PERSISTENT|ZEND_HASH_APPLY_COUNT_MASK)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
    1771      511224 :                 target->nTableMask = HT_MIN_MASK;
    1772      511224 :                 target->nNumUsed = 0;
    1773      511224 :                 target->nNumOfElements = 0;
    1774      511224 :                 target->nNextFreeElement = 0;
    1775      511224 :                 target->nInternalPointer = HT_INVALID_IDX;
    1776      511224 :                 HT_SET_DATA_ADDR(target, &uninitialized_bucket);
    1777      874792 :         } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) {
    1778          25 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1779          25 :                 target->nTableMask = source->nTableMask;
    1780          25 :                 target->nNumUsed = source->nNumUsed;
    1781          25 :                 target->nNumOfElements = source->nNumOfElements;
    1782          25 :                 target->nNextFreeElement = source->nNextFreeElement;
    1783          25 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1784          25 :                 target->nInternalPointer = source->nInternalPointer;
    1785          25 :                 memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source));
    1786          50 :                 if (target->nNumOfElements > 0 &&
    1787          25 :                     target->nInternalPointer == HT_INVALID_IDX) {
    1788           0 :                         idx = 0;
    1789           0 :                         while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1790           0 :                                 idx++;
    1791             :                         }
    1792           0 :                         target->nInternalPointer = idx;
    1793             :                 }
    1794      874767 :         } else if (source->u.flags & HASH_FLAG_PACKED) {
    1795      838052 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_PERSISTENT|ZEND_HASH_APPLY_COUNT_MASK)) | HASH_FLAG_APPLY_PROTECTION;
    1796      838052 :                 target->nTableMask = source->nTableMask;
    1797      838052 :                 target->nNumUsed = source->nNumUsed;
    1798      838052 :                 target->nNumOfElements = source->nNumOfElements;
    1799      838052 :                 target->nNextFreeElement = source->nNextFreeElement;
    1800      838052 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1801      838052 :                 target->nInternalPointer = source->nInternalPointer;
    1802      838052 :                 HT_HASH_RESET_PACKED(target);
    1803             : 
    1804      838052 :                 if (target->nNumUsed == target->nNumOfElements) {
    1805             :                         zend_array_dup_packed_elements(source, target, 0);
    1806             :                 } else {
    1807             :                         zend_array_dup_packed_elements(source, target, 1);
    1808             :                 }
    1809     1676104 :                 if (target->nNumOfElements > 0 &&
    1810      838052 :                     target->nInternalPointer == HT_INVALID_IDX) {
    1811           8 :                         idx = 0;
    1812          26 :                         while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1813           1 :                                 idx++;
    1814             :                         }
    1815           8 :                         target->nInternalPointer = idx;
    1816             :                 }
    1817             :         } else {
    1818       36715 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_PERSISTENT|ZEND_HASH_APPLY_COUNT_MASK)) | HASH_FLAG_APPLY_PROTECTION;
    1819       36715 :                 target->nTableMask = source->nTableMask;
    1820       36715 :                 target->nNextFreeElement = source->nNextFreeElement;
    1821       36715 :                 target->nInternalPointer = HT_INVALID_IDX;
    1822       36715 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1823       36715 :                 HT_HASH_RESET(target);
    1824             : 
    1825       36715 :                 if (target->u.flags & HASH_FLAG_STATIC_KEYS) {
    1826         623 :                         if (source->nNumUsed == source->nNumOfElements) {
    1827         623 :                                 idx = zend_array_dup_elements(source, target, 1, 0);
    1828             :                         } else {
    1829           0 :                                 idx = zend_array_dup_elements(source, target, 1, 1);
    1830             :                         }
    1831             :                 } else {
    1832       36092 :                         if (source->nNumUsed == source->nNumOfElements) {
    1833       36091 :                                 idx = zend_array_dup_elements(source, target, 0, 0);
    1834             :                         } else {
    1835           1 :                                 idx = zend_array_dup_elements(source, target, 0, 1);
    1836             :                         }
    1837             :                 }
    1838       36715 :                 target->nNumUsed = idx;
    1839       36715 :                 target->nNumOfElements = idx;
    1840       36715 :                 if (idx > 0 && target->nInternalPointer == HT_INVALID_IDX) {
    1841       36710 :                         target->nInternalPointer = 0;
    1842             :                 }
    1843             :         }
    1844     1386016 :         return target;
    1845             : }
    1846             : 
    1847             : 
    1848      215394 : ZEND_API void ZEND_FASTCALL _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
    1849             : {
    1850             :     uint32_t idx;
    1851             :         Bucket *p;
    1852             :         zval *t;
    1853             : 
    1854             :         IS_CONSISTENT(source);
    1855             :         IS_CONSISTENT(target);
    1856             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1857             : 
    1858      215394 :         if (overwrite) {
    1859           4 :                 for (idx = 0; idx < source->nNumUsed; idx++) {
    1860           3 :                         p = source->arData + idx;
    1861           6 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1862           6 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
    1863           0 :                             UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
    1864           0 :                             continue;
    1865             :                         }
    1866           3 :                         if (p->key) {
    1867           4 :                                 t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
    1868           2 :                                 if (t && pCopyConstructor) {
    1869           2 :                                         pCopyConstructor(t);
    1870             :                                 }
    1871             :                         } else {
    1872           1 :                                 t = zend_hash_index_update(target, p->h, &p->val);
    1873           1 :                                 if (t && pCopyConstructor) {
    1874           1 :                                         pCopyConstructor(t);
    1875             :                                 }
    1876             :                         }
    1877             :                 }
    1878             :         } else {
    1879     3709602 :                 for (idx = 0; idx < source->nNumUsed; idx++) {
    1880     3494209 :                         p = source->arData + idx;
    1881     6988418 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1882     6988418 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
    1883           0 :                             UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
    1884           0 :                             continue;
    1885             :                         }
    1886     3494209 :                         if (p->key) {
    1887     6988312 :                                 t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_ADD | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
    1888     3494156 :                                 if (t && pCopyConstructor) {
    1889     3493554 :                                         pCopyConstructor(t);
    1890             :                                 }
    1891             :                         } else {
    1892          53 :                                 t = zend_hash_index_add(target, p->h, &p->val);
    1893          53 :                                 if (t && pCopyConstructor) {
    1894          25 :                                         pCopyConstructor(t);
    1895             :                                 }
    1896             :                         }
    1897             :                 }
    1898             :         }
    1899      215394 :         if (target->nNumOfElements > 0) {
    1900      215391 :                 idx = 0;
    1901      646173 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1902           0 :                         idx++;
    1903             :                 }
    1904      215391 :                 target->nInternalPointer = idx;
    1905             :         }
    1906      215394 : }
    1907             : 
    1908             : 
    1909           0 : static zend_bool ZEND_FASTCALL zend_hash_replace_checker_wrapper(HashTable *target, zval *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func)
    1910             : {
    1911             :         zend_hash_key hash_key;
    1912             : 
    1913           0 :         hash_key.h = p->h;
    1914           0 :         hash_key.key = p->key;
    1915           0 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1916             : }
    1917             : 
    1918             : 
    1919           0 : ZEND_API void ZEND_FASTCALL zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
    1920             : {
    1921             :         uint32_t idx;
    1922             :         Bucket *p;
    1923             :         zval *t;
    1924             : 
    1925             :         IS_CONSISTENT(source);
    1926             :         IS_CONSISTENT(target);
    1927             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1928             : 
    1929           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1930           0 :                 p = source->arData + idx;
    1931           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1932           0 :                 if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
    1933           0 :                         t = zend_hash_update(target, p->key, &p->val);
    1934           0 :                         if (t && pCopyConstructor) {
    1935           0 :                                 pCopyConstructor(t);
    1936             :                         }
    1937             :                 }
    1938             :         }
    1939           0 :         if (target->nNumOfElements > 0) {
    1940           0 :                 idx = 0;
    1941           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1942           0 :                         idx++;
    1943             :                 }
    1944           0 :                 target->nInternalPointer = idx;
    1945             :         }
    1946           0 : }
    1947             : 
    1948             : 
    1949             : /* Returns the hash table data if found and NULL if not. */
    1950    66626980 : ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
    1951             : {
    1952             :         Bucket *p;
    1953             : 
    1954             :         IS_CONSISTENT(ht);
    1955             : 
    1956    66626980 :         p = zend_hash_find_bucket(ht, key);
    1957    66626980 :         return p ? &p->val : NULL;
    1958             : }
    1959             : 
    1960     2423027 : ZEND_API zval* ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
    1961             : {
    1962             :         zend_ulong h;
    1963             :         Bucket *p;
    1964             : 
    1965             :         IS_CONSISTENT(ht);
    1966             : 
    1967     2423027 :         h = zend_inline_hash_func(str, len);
    1968     2423027 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1969     2423027 :         return p ? &p->val : NULL;
    1970             : }
    1971             : 
    1972       62921 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_exists(const HashTable *ht, zend_string *key)
    1973             : {
    1974             :         Bucket *p;
    1975             : 
    1976             :         IS_CONSISTENT(ht);
    1977             : 
    1978       62921 :         p = zend_hash_find_bucket(ht, key);
    1979       62921 :         return p ? 1 : 0;
    1980             : }
    1981             : 
    1982     1073759 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
    1983             : {
    1984             :         zend_ulong h;
    1985             :         Bucket *p;
    1986             : 
    1987             :         IS_CONSISTENT(ht);
    1988             : 
    1989     1073759 :         h = zend_inline_hash_func(str, len);
    1990     1073759 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1991     1073759 :         return p ? 1 : 0;
    1992             : }
    1993             : 
    1994     2578960 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
    1995             : {
    1996             :         Bucket *p;
    1997             : 
    1998             :         IS_CONSISTENT(ht);
    1999             : 
    2000     2578960 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2001     2062413 :                 if (h < ht->nNumUsed) {
    2002     2047076 :                         p = ht->arData + h;
    2003     4094152 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    2004     2046735 :                                 return &p->val;
    2005             :                         }
    2006             :                 }
    2007       15678 :                 return NULL;
    2008             :         }
    2009             : 
    2010      516547 :         p = zend_hash_index_find_bucket(ht, h);
    2011      516547 :         return p ? &p->val : NULL;
    2012             : }
    2013             : 
    2014      682763 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_find(const HashTable *ht, zend_ulong h)
    2015             : {
    2016             :         Bucket *p;
    2017             : 
    2018             :         IS_CONSISTENT(ht);
    2019             : 
    2020      682763 :         p = zend_hash_index_find_bucket(ht, h);
    2021      682763 :         return p ? &p->val : NULL;
    2022             : }
    2023             : 
    2024     1776175 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h)
    2025             : {
    2026             :         Bucket *p;
    2027             : 
    2028             :         IS_CONSISTENT(ht);
    2029             : 
    2030     1776175 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2031        1070 :                 if (h < ht->nNumUsed) {
    2032         128 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    2033          57 :                                 return 1;
    2034             :                         }
    2035             :                 }
    2036        1013 :                 return 0;
    2037             :         }
    2038             : 
    2039     1775105 :         p = zend_hash_index_find_bucket(ht, h);
    2040     1775105 :         return p ? 1 : 0;
    2041             : }
    2042             : 
    2043             : 
    2044      237192 : ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    2045             : {
    2046             :     uint32_t idx;
    2047             : 
    2048             :         IS_CONSISTENT(ht);
    2049             :         HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
    2050             : 
    2051      238560 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    2052       76770 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2053       37017 :                         *pos = idx;
    2054       37017 :                         return;
    2055             :                 }
    2056             :         }
    2057      200175 :         *pos = HT_INVALID_IDX;
    2058             : }
    2059             : 
    2060             : 
    2061             : /* This function will be extremely optimized by remembering
    2062             :  * the end of the list
    2063             :  */
    2064          76 : ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    2065             : {
    2066             :         uint32_t idx;
    2067             : 
    2068             :         IS_CONSISTENT(ht);
    2069             :         HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
    2070             : 
    2071          76 :         idx = ht->nNumUsed;
    2072         152 :         while (idx > 0) {
    2073          74 :                 idx--;
    2074         148 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2075          74 :                         *pos = idx;
    2076          74 :                         return;
    2077             :                 }
    2078             :         }
    2079           2 :         *pos = HT_INVALID_IDX;
    2080             : }
    2081             : 
    2082             : 
    2083       89855 : ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    2084             : {
    2085       89855 :         uint32_t idx = *pos;
    2086             : 
    2087             :         IS_CONSISTENT(ht);
    2088             :         HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
    2089             : 
    2090       89855 :         if (idx != HT_INVALID_IDX) {
    2091             :                 while (1) {
    2092       89894 :                         idx++;
    2093       89894 :                         if (idx >= ht->nNumUsed) {
    2094       33763 :                                 *pos = HT_INVALID_IDX;
    2095       33763 :                                 return SUCCESS;
    2096             :                         }
    2097      112262 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2098       56058 :                                 *pos = idx;
    2099       56058 :                                 return SUCCESS;
    2100             :                         }
    2101          73 :                 }
    2102             :         } else {
    2103          34 :                 return FAILURE;
    2104             :         }
    2105             : }
    2106             : 
    2107          21 : ZEND_API int ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    2108             : {
    2109          21 :         uint32_t idx = *pos;
    2110             : 
    2111             :         IS_CONSISTENT(ht);
    2112             :         HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
    2113             : 
    2114          21 :         if (idx != HT_INVALID_IDX) {
    2115          38 :                 while (idx > 0) {
    2116          14 :                         idx--;
    2117          28 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2118          14 :                                 *pos = idx;
    2119          14 :                                 return SUCCESS;
    2120             :                         }
    2121             :                 }
    2122           5 :                 *pos = HT_INVALID_IDX;
    2123           5 :                 return SUCCESS;
    2124             :         } else {
    2125           2 :                 return FAILURE;
    2126             :         }
    2127             : }
    2128             : 
    2129             : 
    2130             : /* This function should be made binary safe  */
    2131       13423 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, HashPosition *pos)
    2132             : {
    2133       13423 :         uint32_t idx = *pos;
    2134             :         Bucket *p;
    2135             : 
    2136             :         IS_CONSISTENT(ht);
    2137       13423 :         if (idx != HT_INVALID_IDX) {
    2138       12962 :                 p = ht->arData + idx;
    2139       12962 :                 if (p->key) {
    2140       11642 :                         *str_index = p->key;
    2141       11642 :                         return HASH_KEY_IS_STRING;
    2142             :                 } else {
    2143        1320 :                         *num_index = p->h;
    2144        1320 :                         return HASH_KEY_IS_LONG;
    2145             :                 }
    2146             :         }
    2147         461 :         return HASH_KEY_NON_EXISTENT;
    2148             : }
    2149             : 
    2150       20774 : ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    2151             : {
    2152       20774 :         uint32_t idx = *pos;
    2153             :         Bucket *p;
    2154             : 
    2155             :         IS_CONSISTENT(ht);
    2156       20774 :         if (idx == HT_INVALID_IDX) {
    2157          55 :                 ZVAL_NULL(key);
    2158             :         } else {
    2159       20719 :                 p = ht->arData + idx;
    2160       20719 :                 if (p->key) {
    2161         710 :                         ZVAL_STR_COPY(key, p->key);
    2162             :                 } else {
    2163       20009 :                         ZVAL_LONG(key, p->h);
    2164             :                 }
    2165             :         }
    2166       20774 : }
    2167             : 
    2168      330372 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    2169             : {
    2170      330372 :     uint32_t idx = *pos;
    2171             :         Bucket *p;
    2172             : 
    2173             :         IS_CONSISTENT(ht);
    2174      330372 :         if (idx != HT_INVALID_IDX) {
    2175       81070 :                 p = ht->arData + idx;
    2176       81070 :                 if (p->key) {
    2177       51298 :                         return HASH_KEY_IS_STRING;
    2178             :                 } else {
    2179       29772 :                         return HASH_KEY_IS_LONG;
    2180             :                 }
    2181             :         }
    2182      249302 :         return HASH_KEY_NON_EXISTENT;
    2183             : }
    2184             : 
    2185             : 
    2186       87267 : ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    2187             : {
    2188       87267 :         uint32_t idx = *pos;
    2189             :         Bucket *p;
    2190             : 
    2191             :         IS_CONSISTENT(ht);
    2192       87267 :         if (idx != HT_INVALID_IDX) {
    2193       86383 :                 p = ht->arData + idx;
    2194       86383 :                 return &p->val;
    2195             :         } else {
    2196         884 :                 return NULL;
    2197             :         }
    2198             : }
    2199             : 
    2200      104487 : ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q)
    2201             : {
    2202             :         zval val;
    2203             :         zend_ulong h;
    2204             :         zend_string *key;
    2205             : 
    2206      104487 :         ZVAL_COPY_VALUE(&val, &p->val);
    2207      104487 :         h = p->h;
    2208      104487 :         key = p->key;
    2209             : 
    2210      104487 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2211      104487 :         p->h = q->h;
    2212      104487 :         p->key = q->key;
    2213             : 
    2214      104487 :         ZVAL_COPY_VALUE(&q->val, &val);
    2215      104487 :         q->h = h;
    2216      104487 :         q->key = key;
    2217      104487 : }
    2218             : 
    2219       78073 : ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
    2220             : {
    2221             :         zval val;
    2222             : 
    2223       78073 :         ZVAL_COPY_VALUE(&val, &p->val);
    2224       78073 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2225       78073 :         ZVAL_COPY_VALUE(&q->val, &val);
    2226       78073 : }
    2227             : 
    2228        1083 : ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q)
    2229             : {
    2230             :         zval val;
    2231             :         zend_ulong h;
    2232             : 
    2233        1083 :         ZVAL_COPY_VALUE(&val, &p->val);
    2234        1083 :         h = p->h;
    2235             : 
    2236        1083 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2237        1083 :         p->h = q->h;
    2238             : 
    2239        1083 :         ZVAL_COPY_VALUE(&q->val, &val);
    2240        1083 :         q->h = h;
    2241        1083 : }
    2242             : 
    2243       25660 : ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber)
    2244             : {
    2245             :         Bucket *p;
    2246             :         uint32_t i, j;
    2247             : 
    2248             :         IS_CONSISTENT(ht);
    2249             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    2250             : 
    2251       25660 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    2252         298 :                 return SUCCESS;
    2253             :         }
    2254             : 
    2255       25362 :         if (ht->nNumUsed == ht->nNumOfElements) {
    2256       25268 :                 i = ht->nNumUsed;
    2257             :         } else {
    2258         686 :                 for (j = 0, i = 0; j < ht->nNumUsed; j++) {
    2259         592 :                         p = ht->arData + j;
    2260        1184 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    2261         480 :                         if (i != j) {
    2262         464 :                                 ht->arData[i] = *p;
    2263             :                         }
    2264         480 :                         i++;
    2265             :                 }
    2266             :         }
    2267             : 
    2268       50421 :         sort((void *)ht->arData, i, sizeof(Bucket), compar,
    2269             :                         (swap_func_t)(renumber? zend_hash_bucket_renum_swap :
    2270       25059 :                                 ((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
    2271             : 
    2272       25362 :         ht->nNumUsed = i;
    2273       25362 :         ht->nInternalPointer = 0;
    2274             : 
    2275       25362 :         if (renumber) {
    2276       17830 :                 for (j = 0; j < i; j++) {
    2277       17527 :                         p = ht->arData + j;
    2278       17527 :                         p->h = j;
    2279       17527 :                         if (p->key) {
    2280         233 :                                 zend_string_release(p->key);
    2281         233 :                                 p->key = NULL;
    2282             :                         }
    2283             :                 }
    2284             : 
    2285         303 :                 ht->nNextFreeElement = i;
    2286             :         }
    2287       25362 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2288         504 :                 if (!renumber) {
    2289         247 :                         zend_hash_packed_to_hash(ht);
    2290             :                 }
    2291             :         } else {
    2292       24858 :                 if (renumber) {
    2293          46 :                         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
    2294          46 :                         Bucket *old_buckets = ht->arData;
    2295             : 
    2296          46 :                         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (ht->u.flags & HASH_FLAG_PERSISTENT));
    2297          46 :                         ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
    2298          46 :                         ht->nTableMask = HT_MIN_MASK;
    2299          46 :                         HT_SET_DATA_ADDR(ht, new_data);
    2300          46 :                         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
    2301          46 :                         pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT & HASH_FLAG_PERSISTENT);
    2302          46 :                         HT_HASH_RESET_PACKED(ht);
    2303             :                 } else {
    2304       24812 :                         zend_hash_rehash(ht);
    2305             :                 }
    2306             :         }
    2307             : 
    2308       25362 :         return SUCCESS;
    2309             : }
    2310             : 
    2311             : static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered) {
    2312             :         uint32_t idx1, idx2;
    2313             : 
    2314         925 :         if (ht1->nNumOfElements != ht2->nNumOfElements) {
    2315         319 :                 return ht1->nNumOfElements > ht2->nNumOfElements ? 1 : -1;
    2316             :         }
    2317             : 
    2318        4531 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    2319        4107 :                 Bucket *p1 = ht1->arData + idx1, *p2;
    2320             :                 zval *pData1, *pData2;
    2321             :                 int result;
    2322             : 
    2323        8214 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    2324        4090 :                 if (ordered) {
    2325             :                         while (1) {
    2326             :                                 ZEND_ASSERT(idx2 != ht2->nNumUsed);
    2327        1148 :                                 p2 = ht2->arData + idx2;
    2328        2296 :                                 if (Z_TYPE(p2->val) != IS_UNDEF) break;
    2329           1 :                                 idx2++;
    2330             :                         }
    2331        1147 :                         if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
    2332         364 :                                 if (p1->h != p2->h) {
    2333           2 :                                         return p1->h > p2->h ? 1 : -1;
    2334             :                                 }
    2335         783 :                         } else if (p1->key != NULL && p2->key != NULL) { /* string indices */
    2336         782 :                                 if (ZSTR_LEN(p1->key) != ZSTR_LEN(p2->key)) {
    2337           0 :                                         return ZSTR_LEN(p1->key) > ZSTR_LEN(p2->key) ? 1 : -1;
    2338             :                                 }
    2339             : 
    2340         782 :                                 result = memcmp(ZSTR_VAL(p1->key), ZSTR_VAL(p2->key), ZSTR_LEN(p1->key));
    2341         782 :                                 if (result != 0) {
    2342           0 :                                         return result;
    2343             :                                 }
    2344             :                         } else {
    2345             :                                 /* Mixed key types: A string key is considered as larger */
    2346           1 :                                 return p1->key != NULL ? 1 : -1;
    2347             :                         }
    2348        1144 :                         pData2 = &p2->val;
    2349        1144 :                         idx2++;
    2350             :                 } else {
    2351        2943 :                         if (p1->key == NULL) { /* numeric index */
    2352         488 :                                 pData2 = zend_hash_index_find(ht2, p1->h);
    2353         488 :                                 if (pData2 == NULL) {
    2354           2 :                                         return 1;
    2355             :                                 }
    2356             :                         } else { /* string index */
    2357        2455 :                                 pData2 = zend_hash_find(ht2, p1->key);
    2358        2455 :                                 if (pData2 == NULL) {
    2359          13 :                                         return 1;
    2360             :                                 }
    2361             :                         }
    2362             :                 }
    2363             : 
    2364        4072 :                 pData1 = &p1->val;
    2365        4072 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    2366         129 :                         pData1 = Z_INDIRECT_P(pData1);
    2367             :                 }
    2368        4072 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    2369         129 :                         pData2 = Z_INDIRECT_P(pData2);
    2370             :                 }
    2371             : 
    2372        4072 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    2373           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    2374           0 :                                 return -1;
    2375             :                         }
    2376        4072 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    2377           0 :                         return 1;
    2378             :                 } else {
    2379        4072 :                         result = compar(pData1, pData2);
    2380        4072 :                         if (result != 0) {
    2381         164 :                                 return result;
    2382             :                         }
    2383             :                 }
    2384             :         }
    2385             : 
    2386         424 :         return 0;
    2387             : }
    2388             : 
    2389         925 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
    2390             : {
    2391             :         int result;
    2392             :         IS_CONSISTENT(ht1);
    2393             :         IS_CONSISTENT(ht2);
    2394             : 
    2395         925 :         HASH_PROTECT_RECURSION(ht1);
    2396         925 :         HASH_PROTECT_RECURSION(ht2);
    2397        1850 :         result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
    2398         925 :         HASH_UNPROTECT_RECURSION(ht1);
    2399         925 :         HASH_UNPROTECT_RECURSION(ht2);
    2400             : 
    2401         925 :         return result;
    2402             : }
    2403             : 
    2404             : 
    2405          82 : ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
    2406             : {
    2407             :         uint32_t idx;
    2408             :         Bucket *p, *res;
    2409             : 
    2410             :         IS_CONSISTENT(ht);
    2411             : 
    2412          82 :         if (ht->nNumOfElements == 0 ) {
    2413           4 :                 return NULL;
    2414             :         }
    2415             : 
    2416          78 :         idx = 0;
    2417             :         while (1) {
    2418          78 :                 if (idx == ht->nNumUsed) {
    2419           0 :                         return NULL;
    2420             :                 }
    2421         156 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
    2422           0 :                 idx++;
    2423           0 :         }
    2424          78 :         res = ht->arData + idx;
    2425         376 :         for (; idx < ht->nNumUsed; idx++) {
    2426         298 :                 p = ht->arData + idx;
    2427         596 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    2428             : 
    2429         298 :                 if (flag) {
    2430         229 :                         if (compar(res, p) < 0) { /* max */
    2431          20 :                                 res = p;
    2432             :                         }
    2433             :                 } else {
    2434          69 :                         if (compar(res, p) > 0) { /* min */
    2435           6 :                                 res = p;
    2436             :                         }
    2437             :                 }
    2438             :         }
    2439          78 :         return &res->val;
    2440             : }
    2441             : 
    2442      384206 : ZEND_API int ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    2443             : {
    2444      384206 :         register const char *tmp = key;
    2445             : 
    2446      384206 :         const char *end = key + length;
    2447             : 
    2448      384206 :         if (*tmp == '-') {
    2449          62 :                 tmp++;
    2450             :         }
    2451             : 
    2452      748194 :         if ((*tmp == '0' && length > 1) /* numbers with leading zeros */
    2453      363988 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    2454             :          || (SIZEOF_ZEND_LONG == 4 &&
    2455             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    2456             :              *tmp > '2')) { /* overflow */
    2457       20245 :                 return 0;
    2458             :         }
    2459      363961 :         *idx = (*tmp - '0');
    2460             :         while (1) {
    2461     1447291 :                 ++tmp;
    2462     1447291 :                 if (tmp == end) {
    2463      363558 :                         if (*key == '-') {
    2464          31 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    2465           0 :                                         return 0;
    2466             :                                 }
    2467          31 :                                 *idx = 0 - *idx;
    2468      363527 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    2469           0 :                                 return 0;
    2470             :                         }
    2471      363558 :                         return 1;
    2472             :                 }
    2473     2167063 :                 if (*tmp <= '9' && *tmp >= '0') {
    2474     1083330 :                         *idx = (*idx * 10) + (*tmp - '0');
    2475             :                 } else {
    2476         403 :                         return 0;
    2477             :                 }
    2478     1083330 :         }
    2479             : }
    2480             : 
    2481             : /*
    2482             :  * Local variables:
    2483             :  * tab-width: 4
    2484             :  * c-basic-offset: 4
    2485             :  * indent-tabs-mode: t
    2486             :  * End:
    2487             :  */

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:03 +0000 (8 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.