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: 1102 1235 89.2 %
Date: 2016-07-26 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    22436191 :         if (nSize < HT_MIN_SIZE) {
     104     6242379 :                 nSize = HT_MIN_SIZE;
     105    16193812 :         } 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    22436191 :         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    11182101 :         if (packed) {
     135     2168705 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     136     2168705 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED;
     137     2168705 :                 HT_HASH_RESET_PACKED(ht);
     138             :         } else {
     139     9013396 :                 (ht)->nTableMask = -(ht)->nTableSize;
     140     9013396 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     141     9013396 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED;
     142     9013396 :                 if (EXPECTED(ht->nTableMask == (uint32_t)-8)) {
     143     7859766 :                         Bucket *arData = ht->arData;
     144             : 
     145     7859766 :                         HT_HASH_EX(arData, -8) = -1;
     146     7859766 :                         HT_HASH_EX(arData, -7) = -1;
     147     7859766 :                         HT_HASH_EX(arData, -6) = -1;
     148     7859766 :                         HT_HASH_EX(arData, -5) = -1;
     149     7859766 :                         HT_HASH_EX(arData, -4) = -1;
     150     7859766 :                         HT_HASH_EX(arData, -3) = -1;
     151     7859766 :                         HT_HASH_EX(arData, -2) = -1;
     152     7859766 :                         HT_HASH_EX(arData, -1) = -1;
     153             :                 } else {
     154     1153630 :                         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    10994341 :         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    20603906 : 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    20603906 :         GC_REFCOUNT(ht) = 1;
     176    20603906 :         GC_TYPE_INFO(ht) = IS_ARRAY;
     177    20603906 :         ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
     178    20603906 :         ht->nTableSize = zend_hash_check_size(nSize);
     179    20603906 :         ht->nTableMask = HT_MIN_MASK;
     180    20603906 :         HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
     181    20603906 :         ht->nNumUsed = 0;
     182    20603906 :         ht->nNumOfElements = 0;
     183    20603906 :         ht->nInternalPointer = HT_INVALID_IDX;
     184    20603906 :         ht->nNextFreeElement = 0;
     185    20603906 :         ht->pDestructor = pDestructor;
     186    20603906 : }
     187             : 
     188       39623 : static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
     189             : {
     190             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     191       39623 :         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       39623 :         ht->nTableSize += ht->nTableSize;
     195       39623 :         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       39623 : }
     197             : 
     198      187760 : 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      187760 :         zend_hash_real_init_ex(ht, packed);
     204      187760 : }
     205             : 
     206       26744 : ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
     207             : {
     208       26744 :         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     209       26744 :         Bucket *old_buckets = ht->arData;
     210             : 
     211             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     212       26744 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     213       26744 :         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, -ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT);
     214       26744 :         ht->nTableMask = -ht->nTableSize;
     215       26744 :         HT_SET_DATA_ADDR(ht, new_data);
     216       26744 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     217       26744 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     218       26744 :         zend_hash_rehash(ht);
     219       26744 : }
     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    13814772 : 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    13814772 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
     239    13814772 :         if (!bApplyProtection) {
     240    13814772 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     241             :         }
     242    13814772 : }
     243             : 
     244     3008423 : 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     3008423 :         if (nSize == 0) return;
     248     2866237 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     249     1761399 :                 if (nSize > ht->nTableSize) {
     250      845890 :                         ht->nTableSize = zend_hash_check_size(nSize);
     251             :                 }
     252     1761399 :                 zend_hash_check_init(ht, packed);
     253             :         } else {
     254     1104838 :                 if (packed) {
     255             :                         ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED);
     256           0 :                         if (nSize > ht->nTableSize) {
     257           0 :                                 ht->nTableSize = zend_hash_check_size(nSize);
     258           0 :                                 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     1104838 :                         if (nSize > ht->nTableSize) {
     263      986395 :                                 void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     264      986395 :                                 Bucket *old_buckets = ht->arData;
     265      986395 :                                 nSize = zend_hash_check_size(nSize);
     266      986395 :                                 new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT);
     267      986395 :                                 ht->nTableSize = nSize;
     268      986395 :                                 ht->nTableMask = -ht->nTableSize;
     269      986395 :                                 HT_SET_DATA_ADDR(ht, new_data);
     270      986395 :                                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     271      986395 :                                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     272      986395 :                                 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      264368 : ZEND_API uint32_t zend_array_count(HashTable *ht)
     296             : {
     297             :         uint32_t num;
     298      264368 :         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      264328 :         } else if (UNEXPECTED(ht == &EG(symbol_table))) {
     304           3 :                 num = zend_array_recalc_elements(ht);
     305             :         } else {
     306      264325 :                 num = zend_hash_num_elements(ht);
     307             :         }
     308      264368 :         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      200718 : ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPosition pos)
     322             : {
     323      200718 :         HashTableIterator *iter = EG(ht_iterators);
     324      200718 :         HashTableIterator *end  = iter + EG(ht_iterators_count);
     325             :         uint32_t idx;
     326             : 
     327      200718 :         if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     328      200718 :                 ht->u.v.nIteratorsCount++;
     329             :         }
     330      401855 :         while (iter != end) {
     331      201137 :                 if (iter->ht == NULL) {
     332      200718 :                         iter->ht = ht;
     333      200718 :                         iter->pos = pos;
     334      200718 :                         idx = iter - EG(ht_iterators);
     335      200718 :                         if (idx + 1 > EG(ht_iterators_used)) {
     336      200715 :                                 EG(ht_iterators_used) = idx + 1;
     337             :                         }
     338      200718 :                         return idx;
     339             :                 }
     340         419 :                 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          69 :                 return HT_INVALID_IDX;
     365         312 :         } 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         312 :         return iter->pos;
     377             : }
     378             : 
     379        1050 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos_ex(uint32_t idx, zval *array)
     380             : {
     381        1050 :         HashTable *ht = Z_ARRVAL_P(array);
     382        1050 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     383             : 
     384             :         ZEND_ASSERT(idx != (uint32_t)-1);
     385        1050 :         if (iter->pos == HT_INVALID_IDX) {
     386         113 :                 return HT_INVALID_IDX;
     387         937 :         } else if (UNEXPECTED(iter->ht != ht)) {
     388           2 :                 if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR)
     389           1 :                                 && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     390           0 :                         iter->ht->u.v.nIteratorsCount--;
     391             :                 }
     392           1 :                 SEPARATE_ARRAY(array);
     393           1 :                 ht = Z_ARRVAL_P(array);
     394           1 :                 if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     395           1 :                         ht->u.v.nIteratorsCount++;
     396             :                 }
     397           1 :                 iter->ht = ht;
     398           1 :                 iter->pos = ht->nInternalPointer;
     399             :         }
     400         937 :         return iter->pos;
     401             : }
     402             : 
     403      200717 : ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
     404             : {
     405      200717 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     406             : 
     407             :         ZEND_ASSERT(idx != (uint32_t)-1);
     408             : 
     409      602147 :         if (EXPECTED(iter->ht) && EXPECTED(iter->ht != HT_POISONED_PTR)
     410      401430 :                         && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     411      200713 :                 iter->ht->u.v.nIteratorsCount--;
     412             :         }
     413      200717 :         iter->ht = NULL;
     414             : 
     415      200717 :         if (idx == EG(ht_iterators_used) - 1) {
     416      401400 :                 while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) {
     417          28 :                         idx--;
     418             :                 }
     419      200686 :                 EG(ht_iterators_used) = idx;
     420             :         }
     421      200717 : }
     422             : 
     423          25 : static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTable *ht)
     424             : {
     425          25 :         HashTableIterator *iter = EG(ht_iterators);
     426          25 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     427             : 
     428          62 :         while (iter != end) {
     429          12 :                 if (iter->ht == ht) {
     430           5 :                         iter->ht = HT_POISONED_PTR;
     431             :                 }
     432          12 :                 iter++;
     433             :         }
     434          25 : }
     435             : 
     436             : static zend_always_inline void zend_hash_iterators_remove(HashTable *ht)
     437             : {
     438    11937201 :         if (UNEXPECTED(ht->u.v.nIteratorsCount)) {
     439          25 :                 _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         236 : ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to)
     461             : {
     462         236 :         HashTableIterator *iter = EG(ht_iterators);
     463         236 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     464             : 
     465         734 :         while (iter != end) {
     466         262 :                 if (iter->ht == ht && iter->pos == from) {
     467          74 :                         iter->pos = to;
     468             :                 }
     469         262 :                 iter++;
     470             :         }
     471         236 : }
     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   275041525 :         h = zend_string_hash_val(key);
     481   275041525 :         arData = ht->arData;
     482   275041525 :         nIndex = h | ht->nTableMask;
     483   275041525 :         idx = HT_HASH_EX(arData, nIndex);
     484   433758678 :         while (EXPECTED(idx != HT_INVALID_IDX)) {
     485   174125328 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     486   174125328 :                 if (EXPECTED(p->key == key)) { /* check for the same interned string */
     487    10078769 :                         return p;
     488   180041251 :                 } else if (EXPECTED(p->h == h) &&
     489     5331564 :                      EXPECTED(p->key) &&
     490     5331564 :                      EXPECTED(ZSTR_LEN(p->key) == ZSTR_LEN(key)) &&
     491     5331564 :                      EXPECTED(memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
     492     5329406 :                         return p;
     493             :                 }
     494   158717153 :                 idx = Z_NEXT(p->val);
     495             :         }
     496   259633350 :         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     3415413 :         arData = ht->arData;
     506     3415413 :         nIndex = h | ht->nTableMask;
     507     3415413 :         idx = HT_HASH_EX(arData, nIndex);
     508     4112912 :         while (idx != HT_INVALID_IDX) {
     509             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     510     3273942 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     511    11003322 :                 if ((p->h == h)
     512             :                          && p->key
     513     5152920 :                          && (ZSTR_LEN(p->key) == len)
     514     2576460 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
     515     2576443 :                         return p;
     516             :                 }
     517      697499 :                 idx = Z_NEXT(p->val);
     518             :         }
     519      838970 :         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     4597296 :         arData = ht->arData;
     529     4597296 :         nIndex = h | ht->nTableMask;
     530     4597296 :         idx = HT_HASH_EX(arData, nIndex);
     531     6170675 :         while (idx != HT_INVALID_IDX) {
     532             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     533     2622378 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     534     2622378 :                 if (p->h == h && !p->key) {
     535     1048999 :                         return p;
     536             :                 }
     537     1573379 :                 idx = Z_NEXT(p->val);
     538             :         }
     539     3548297 :         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   220241447 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     553             :                 CHECK_INIT(ht, 0);
     554             :                 goto add_to_hash;
     555   213176834 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     556       24886 :                 zend_hash_packed_to_hash(ht);
     557   213151948 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     558   210369632 :                 p = zend_hash_find_bucket(ht, key);
     559             : 
     560   210369632 :                 if (p) {
     561             :                         zval *data;
     562             : 
     563      583207 :                         if (flag & HASH_ADD) {
     564      293479 :                                 if (!(flag & HASH_UPDATE_INDIRECT)) {
     565      292896 :                                         return NULL;
     566             :                                 }
     567             :                                 ZEND_ASSERT(&p->val != pData);
     568         583 :                                 data = &p->val;
     569         583 :                                 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         582 :                                         return NULL;
     576             :                                 }
     577             :                         } else {
     578             :                                 ZEND_ASSERT(&p->val != pData);
     579      289728 :                                 data = &p->val;
     580      350525 :                                 if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     581         301 :                                         data = Z_INDIRECT_P(data);
     582             :                                 }
     583             :                         }
     584      289729 :                         if (ht->pDestructor) {
     585      242423 :                                 ht->pDestructor(data);
     586             :                         }
     587      289729 :                         ZVAL_COPY_VALUE(data, pData);
     588      289729 :                         return data;
     589             :                 }
     590             :         }
     591             : 
     592   212593627 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     593             : 
     594             : add_to_hash:
     595   219658240 :         idx = ht->nNumUsed++;
     596   219658240 :         ht->nNumOfElements++;
     597   219658240 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     598     7260735 :                 ht->nInternalPointer = idx;
     599             :         }
     600             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     601   219658240 :         p = ht->arData + idx;
     602   219658240 :         p->key = key;
     603   219658240 :         if (!ZSTR_IS_INTERNED(key)) {
     604             :                 zend_string_addref(key);
     605   120125441 :                 ht->u.flags &= ~HASH_FLAG_STATIC_KEYS;
     606             :                 zend_string_hash_val(key);
     607             :         }
     608   219658240 :         p->h = h = ZSTR_H(key);
     609   219658240 :         ZVAL_COPY_VALUE(&p->val, pData);
     610   219658240 :         nIndex = h | ht->nTableMask;
     611   219658240 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     612   219658240 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     613             : 
     614   219658240 :         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   186883955 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     623             : {
     624   186883955 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     625             : }
     626             : 
     627     8783079 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     628             : {
     629     8783079 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     630             : }
     631             : 
     632         966 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     633             : {
     634         966 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     635             : }
     636             : 
     637     3241013 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     638             : {
     639     3241013 :         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     1471072 : 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     2942144 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     653     1471072 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     654             :         zend_string_release(key);
     655     1471072 :         return ret;
     656             : }
     657             : 
     658     1511838 : 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     3023676 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     661     1511838 :         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     1511838 :         return ret;
     664             : }
     665             : 
     666    14923842 : 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    29847684 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     669    14923842 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     670             :         zend_string_release(key);
     671    14923842 :         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          84 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     683             : {
     684             :         zval dummy;
     685             : 
     686          84 :         ZVAL_NULL(&dummy);
     687          84 :         return zend_hash_index_add(ht, h, &dummy);
     688             : }
     689             : 
     690       55986 : ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     691             : {
     692             :         zval dummy;
     693             : 
     694       55986 :         ZVAL_NULL(&dummy);
     695       55986 :         return zend_hash_add(ht, key, &dummy);
     696             : }
     697             : 
     698      598293 : 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      598293 :         ZVAL_NULL(&dummy);
     703      598293 :         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     8689947 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     716     2168329 :                 CHECK_INIT(ht, h < ht->nTableSize);
     717     2168329 :                 if (h < ht->nTableSize) {
     718     2064411 :                         p = ht->arData + h;
     719             :                         goto add_to_packed;
     720             :                 }
     721             :                 goto add_to_hash;
     722     6521618 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     723     3764222 :                 if (h < ht->nNumUsed) {
     724        3807 :                         p = ht->arData + h;
     725        7614 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     726        3648 :                                 if (flag & HASH_ADD) {
     727          24 :                                         return NULL;
     728             :                                 }
     729        3624 :                                 if (ht->pDestructor) {
     730        3624 :                                         ht->pDestructor(&p->val);
     731             :                                 }
     732        3624 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     733        3624 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     734           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     735             :                                 }
     736        3624 :                                 return &p->val;
     737             :                         } else { /* we have to keep the order :( */
     738             :                                 goto convert_to_hash;
     739             :                         }
     740     3760415 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     741     3719340 :                         p = ht->arData + h;
     742       82073 :                 } else if ((h >> 1) < ht->nTableSize &&
     743       40998 :                            (ht->nTableSize >> 1) < ht->nNumOfElements) {
     744       39623 :                         zend_hash_packed_grow(ht);
     745       39623 :                         p = ht->arData + h;
     746             :                 } else {
     747             :                         goto convert_to_hash;
     748             :                 }
     749             : 
     750             : add_to_packed:
     751             :                 /* incremental initialization of empty Buckets */
     752     5823374 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     753     1263279 :                         ht->nNumUsed = h + 1;
     754     4560095 :                 } else if (h >= ht->nNumUsed) {
     755     4560095 :                         if (h > ht->nNumUsed) {
     756      903750 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     757     1816314 :                                 while (q != p) {
     758      912564 :                                         ZVAL_UNDEF(&q->val);
     759      912564 :                                         q++;
     760             :                                 }
     761             :                         }
     762     4560095 :                         ht->nNumUsed = h + 1;
     763             :                 }
     764     5823374 :                 ht->nNumOfElements++;
     765     5823374 :                 if (ht->nInternalPointer == HT_INVALID_IDX) {
     766     2116695 :                         ht->nInternalPointer = h;
     767             :                 }
     768     5823374 :                 zend_hash_iterators_update(ht, HT_INVALID_IDX, h);
     769     5823374 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     770     5771193 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     771             :                 }
     772     5823374 :                 p->h = h;
     773     5823374 :                 p->key = NULL;
     774     5823374 :                 ZVAL_COPY_VALUE(&p->val, pData);
     775             : 
     776     5823374 :                 return &p->val;
     777             : 
     778             : convert_to_hash:
     779        1611 :                 zend_hash_packed_to_hash(ht);
     780     2757396 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     781     1662089 :                 p = zend_hash_index_find_bucket(ht, h);
     782     1662089 :                 if (p) {
     783       10431 :                         if (flag & HASH_ADD) {
     784         179 :                                 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     2748576 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     799             : 
     800             : add_to_hash:
     801     2852494 :         idx = ht->nNumUsed++;
     802     2852494 :         ht->nNumOfElements++;
     803     2852494 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     804      262522 :                 ht->nInternalPointer = idx;
     805             :         }
     806             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     807     2852494 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     808     1220635 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     809             :         }
     810     2852494 :         p = ht->arData + idx;
     811     2852494 :         p->h = h;
     812     2852494 :         p->key = NULL;
     813     2852494 :         nIndex = h | ht->nTableMask;
     814     2852494 :         ZVAL_COPY_VALUE(&p->val, pData);
     815     2852494 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     816     2852494 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     817             : 
     818     2852494 :         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         709 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     827             : {
     828         709 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     829             : }
     830             : 
     831     1542690 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     832             : {
     833     1542690 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     834             : }
     835             : 
     836     2822331 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     837             : {
     838     2822331 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     839             : }
     840             : 
     841     3060400 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     842             : {
     843     6120800 :         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     1263817 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     847             : {
     848     2527634 :         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     5261926 : 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     5261926 :         if (ht->nNumUsed > ht->nNumOfElements + (ht->nNumOfElements >> 5)) { /* additional term is there to amortize the cost of compaction */
     858      126449 :                 zend_hash_rehash(ht);
     859     5135477 :         } else if (ht->nTableSize < HT_MAX_SIZE) {        /* Let's double the table size */
     860     5135477 :                 void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     861     5135477 :                 uint32_t nSize = ht->nTableSize + ht->nTableSize;
     862     5135477 :                 Bucket *old_buckets = ht->arData;
     863             : 
     864     5135477 :                 new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT);
     865     5135477 :                 ht->nTableSize = nSize;
     866     5135477 :                 ht->nTableMask = -ht->nTableSize;
     867     5135477 :                 HT_SET_DATA_ADDR(ht, new_data);
     868     5135477 :                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     869     5135477 :                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     870     5135477 :                 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     5261926 : }
     875             : 
     876     6369835 : 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     6369835 :         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     6369830 :         HT_HASH_RESET(ht);
     892     6369830 :         i = 0;
     893     6369830 :         p = ht->arData;
     894     6369830 :         if (ht->nNumUsed == ht->nNumOfElements) {
     895             :                 do {
     896   448230940 :                         nIndex = p->h | ht->nTableMask;
     897   448230940 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     898   448230940 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     899   448230940 :                         p++;
     900   448230940 :                 } while (++i < ht->nNumUsed);
     901             :         } else {
     902             :                 do {
     903     1548264 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) {
     904      128559 :                                 uint32_t j = i;
     905      128559 :                                 Bucket *q = p;
     906             : 
     907      128559 :                                 if (EXPECTED(ht->u.v.nIteratorsCount == 0)) {
     908      965055 :                                         while (++i < ht->nNumUsed) {
     909      707943 :                                                 p++;
     910      707943 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     911      525322 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     912      525322 :                                                         q->h = p->h;
     913      525322 :                                                         nIndex = q->h | ht->nTableMask;
     914      525322 :                                                         q->key = p->key;
     915      525322 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     916      525322 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     917      525322 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     918       25674 :                                                                 ht->nInternalPointer = j;
     919             :                                                         }
     920      525322 :                                                         q++;
     921      525322 :                                                         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      128559 :                                 ht->nNumUsed = j;
     949      128559 :                                 break;
     950             :                         }
     951      645573 :                         nIndex = p->h | ht->nTableMask;
     952      645573 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     953      645573 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     954      645573 :                         p++;
     955      645573 :                 } while (++i < ht->nNumUsed);
     956             :         }
     957     6369830 :         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    61240595 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     963    61022828 :                 if (prev) {
     964     3640071 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     965             :                 } else {
     966    57382757 :                         HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val);
     967             :                 }
     968             :         }
     969    61240595 :         if (HT_IDX_TO_HASH(ht->nNumUsed - 1) == idx) {
     970             :                 do {
     971     5009404 :                         ht->nNumUsed--;
     972     9682703 :                 } while (ht->nNumUsed > 0 && (UNEXPECTED(Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF)));
     973             :         }
     974    61240595 :         ht->nNumOfElements--;
     975    61240595 :         if (HT_IDX_TO_HASH(ht->nInternalPointer) == idx || UNEXPECTED(ht->u.v.nIteratorsCount)) {
     976             :                 uint32_t new_idx;
     977             : 
     978     3941416 :                 new_idx = idx = HT_HASH_TO_IDX(idx);
     979             :                 while (1) {
     980    53875773 :                         new_idx++;
     981    53875773 :                         if (new_idx >= ht->nNumUsed) {
     982      289219 :                                 new_idx = HT_INVALID_IDX;
     983             :                                 break;
     984   107173108 :                         } else if (Z_TYPE(ht->arData[new_idx].val) != IS_UNDEF) {
     985             :                                 break;
     986             :                         }
     987             :                 }
     988     3941416 :                 if (ht->nInternalPointer == idx) {
     989     3941377 :                         ht->nInternalPointer = new_idx;
     990             :                 }
     991             :                 zend_hash_iterators_update(ht, idx, new_idx);
     992             :         }
     993    61240595 :         if (p->key) {
     994    60224885 :                 zend_string_release(p->key);
     995             :         }
     996    61240595 :         if (ht->pDestructor) {
     997             :                 zval tmp;
     998    60340204 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     999    60340204 :                 ZVAL_UNDEF(&p->val);
    1000    60340204 :                 ht->pDestructor(&tmp);
    1001             :         } else {
    1002      900391 :                 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     8419306 :         Bucket *prev = NULL;
    1009             : 
    1010     8419306 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1011     8415206 :                 uint32_t nIndex = p->h | ht->nTableMask;
    1012     8415206 :                 uint32_t i = HT_HASH(ht, nIndex);
    1013             : 
    1014     8415206 :                 if (i != idx) {
    1015      380729 :                         prev = HT_HASH_TO_BUCKET(ht, i);
    1016      451430 :                         while (Z_NEXT(prev->val) != idx) {
    1017       70701 :                                 i = Z_NEXT(prev->val);
    1018       70701 :                                 prev = HT_HASH_TO_BUCKET(ht, i);
    1019             :                         }
    1020             :                 }
    1021             :         }
    1022             : 
    1023             :         _zend_hash_del_el_ex(ht, idx, p, prev);
    1024             : }
    1025             : 
    1026          24 : 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          24 :         _zend_hash_del_el(ht, HT_IDX_TO_HASH(p - ht->arData), p);
    1031          24 : }
    1032             : 
    1033    51850983 : 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    51850983 :         Bucket *prev = NULL;
    1040             : 
    1041             :         IS_CONSISTENT(ht);
    1042             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1043             : 
    1044    51850983 :         h = zend_string_hash_val(key);
    1045    51850983 :         nIndex = h | ht->nTableMask;
    1046             : 
    1047    51850983 :         idx = HT_HASH(ht, nIndex);
    1048   107145502 :         while (idx != HT_INVALID_IDX) {
    1049    54456220 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1050   261821738 :                 if ((p->key == key) ||
    1051    54423997 :                         (p->h == h &&
    1052    50980507 :                      p->key &&
    1053    50980507 :                      ZSTR_LEN(p->key) == ZSTR_LEN(key) &&
    1054    50980507 :                      memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
    1055             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1056    51012684 :                         return SUCCESS;
    1057             :                 }
    1058     3443536 :                 prev = p;
    1059     3443536 :                 idx = Z_NEXT(p->val);
    1060             :         }
    1061      838299 :         return FAILURE;
    1062             : }
    1063             : 
    1064         488 : 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         488 :         Bucket *prev = NULL;
    1071             : 
    1072             :         IS_CONSISTENT(ht);
    1073             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1074             : 
    1075         488 :         h = zend_string_hash_val(key);
    1076         488 :         nIndex = h | ht->nTableMask;
    1077             : 
    1078         488 :         idx = HT_HASH(ht, nIndex);
    1079         984 :         while (idx != HT_INVALID_IDX) {
    1080         292 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1081        1280 :                 if ((p->key == key) ||
    1082         253 :                         (p->h == h &&
    1083         245 :                      p->key &&
    1084         245 :                      ZSTR_LEN(p->key) == ZSTR_LEN(key) &&
    1085         245 :                      memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
    1086         568 :                         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         284 :                         return SUCCESS;
    1106             :                 }
    1107           8 :                 prev = p;
    1108           8 :                 idx = Z_NEXT(p->val);
    1109             :         }
    1110         204 :         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      825959 : 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      825959 :         Bucket *prev = NULL;
    1164             : 
    1165             :         IS_CONSISTENT(ht);
    1166             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1167             : 
    1168      825959 :         h = zend_inline_hash_func(str, len);
    1169      825959 :         nIndex = h | ht->nTableMask;
    1170             : 
    1171      825959 :         idx = HT_HASH(ht, nIndex);
    1172     1675933 :         while (idx != HT_INVALID_IDX) {
    1173      823477 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1174     3221863 :                 if ((p->h == h)
    1175             :                          && p->key
    1176     1598924 :                          && (ZSTR_LEN(p->key) == len)
    1177      799462 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
    1178             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1179      799462 :                         return SUCCESS;
    1180             :                 }
    1181       24015 :                 prev = p;
    1182       24015 :                 idx = Z_NEXT(p->val);
    1183             :         }
    1184       26497 :         return FAILURE;
    1185             : }
    1186             : 
    1187     1021468 : 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     1021468 :         Bucket *prev = NULL;
    1193             : 
    1194             :         IS_CONSISTENT(ht);
    1195             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1196             : 
    1197     1021468 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1198      219843 :                 if (h < ht->nNumUsed) {
    1199      213678 :                         p = ht->arData + h;
    1200      427356 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1201      213667 :                                 _zend_hash_del_el_ex(ht, HT_IDX_TO_HASH(h), p, NULL);
    1202      213667 :                                 return SUCCESS;
    1203             :                         }
    1204             :                 }
    1205        6176 :                 return FAILURE;
    1206             :         }
    1207      801625 :         nIndex = h | ht->nTableMask;
    1208             : 
    1209      801625 :         idx = HT_HASH(ht, nIndex);
    1210     1604673 :         while (idx != HT_INVALID_IDX) {
    1211      796630 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1212      796630 :                 if ((p->h == h) && (p->key == NULL)) {
    1213             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1214      795207 :                         return SUCCESS;
    1215             :                 }
    1216        1423 :                 prev = p;
    1217        1423 :                 idx = Z_NEXT(p->val);
    1218             :         }
    1219        6418 :         return FAILURE;
    1220             : }
    1221             : 
    1222    12216031 : 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    12216031 :         if (ht->nNumUsed) {
    1230     8366515 :                 p = ht->arData;
    1231     8366515 :                 end = p + ht->nNumUsed;
    1232     8366515 :                 if (ht->pDestructor) {
    1233             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
    1234             : 
    1235     8005147 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1236     4953433 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1237             :                                         do {
    1238   177872073 :                                                 ht->pDestructor(&p->val);
    1239   177872073 :                                         } while (++p != end);
    1240             :                                 } else {
    1241             :                                         do {
    1242   104841048 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1243     1694542 :                                                         ht->pDestructor(&p->val);
    1244             :                                                 }
    1245    52420524 :                                         } while (++p != end);
    1246             :                                 }
    1247     3051714 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1248             :                                 do {
    1249   103260092 :                                         ht->pDestructor(&p->val);
    1250   103260092 :                                         if (EXPECTED(p->key)) {
    1251   103253712 :                                                 zend_string_release(p->key);
    1252             :                                         }
    1253   103260092 :                                 } while (++p != end);
    1254             :                         } else {
    1255             :                                 do {
    1256    10958806 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1257      305740 :                                                 ht->pDestructor(&p->val);
    1258      305740 :                                                 if (EXPECTED(p->key)) {
    1259      305740 :                                                         zend_string_release(p->key);
    1260             :                                                 }
    1261             :                                         }
    1262     5479403 :                                 } while (++p != end);
    1263             :                         }
    1264             : 
    1265             :                         SET_INCONSISTENT(HT_DESTROYED);
    1266             :                 } else {
    1267      361368 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1268             :                                 do {
    1269    23366786 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1270    11589434 :                                                 if (EXPECTED(p->key)) {
    1271    11588801 :                                                         zend_string_release(p->key);
    1272             :                                                 }
    1273             :                                         }
    1274    11683393 :                                 } while (++p != end);
    1275             :                         }
    1276             :                 }
    1277             :                 zend_hash_iterators_remove(ht);
    1278     3849516 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1279     3772450 :                 return;
    1280             :         }
    1281     8443581 :         pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1282             : }
    1283             : 
    1284     6282915 : 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     6282915 :         GC_REMOVE_FROM_BUFFER(ht);
    1293     6282915 :         GC_TYPE_INFO(ht) = IS_NULL | (GC_WHITE << 16);
    1294             : 
    1295     6282915 :         if (ht->nNumUsed) {
    1296             :                 /* In some rare cases destructors of regular arrays may be changed */
    1297     3570760 :                 if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
    1298          73 :                         zend_hash_destroy(ht);
    1299          73 :                         goto free_ht;
    1300             :                 }
    1301             : 
    1302     3570687 :                 p = ht->arData;
    1303     3570687 :                 end = p + ht->nNumUsed;
    1304             :                 SET_INCONSISTENT(HT_IS_DESTROYING);
    1305             : 
    1306     3570687 :                 if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1307             :                         do {
    1308     8098990 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1309     8098989 :                         } while (++p != end);
    1310      838111 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1311             :                         do {
    1312     5815663 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1313     5815663 :                                 if (EXPECTED(p->key)) {
    1314     5742877 :                                         zend_string_release(p->key);
    1315             :                                 }
    1316     5815663 :                         } 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     2712155 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1330     2709659 :                 goto free_ht;
    1331             :         }
    1332     3573182 :         efree(HT_GET_DATA_ADDR(ht));
    1333             : free_ht:
    1334     6282914 :         FREE_HASHTABLE(ht);
    1335     6282914 : }
    1336             : 
    1337       56417 : 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       56417 :         if (ht->nNumUsed) {
    1345        8965 :                 p = ht->arData;
    1346        8965 :                 end = p + ht->nNumUsed;
    1347        8965 :                 if (ht->pDestructor) {
    1348        3896 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1349        1014 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1350             :                                         do {
    1351      559719 :                                                 ht->pDestructor(&p->val);
    1352      559719 :                                         } 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        2882 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1361             :                                 do {
    1362     1338433 :                                         ht->pDestructor(&p->val);
    1363     1338433 :                                         if (EXPECTED(p->key)) {
    1364     1338433 :                                                 zend_string_release(p->key);
    1365             :                                         }
    1366     1338433 :                                 } 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        5069 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1379        4595 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1380             :                                         do {
    1381       27560 :                                                 if (EXPECTED(p->key)) {
    1382       27560 :                                                         zend_string_release(p->key);
    1383             :                                                 }
    1384       27560 :                                         } 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        8965 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1397        8946 :                         HT_HASH_RESET(ht);
    1398             :                 }
    1399             :         }
    1400       56417 :         ht->nNumUsed = 0;
    1401       56417 :         ht->nNumOfElements = 0;
    1402       56417 :         ht->nNextFreeElement = 0;
    1403       56417 :         ht->nInternalPointer = HT_INVALID_IDX;
    1404       56417 : }
    1405             : 
    1406         429 : 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         429 :         if (ht->nNumUsed) {
    1414         415 :                 p = ht->arData;
    1415         415 :                 end = p + ht->nNumUsed;
    1416         415 :                 if (ht->u.flags & HASH_FLAG_STATIC_KEYS) {
    1417             :                         do {
    1418        2026 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1419        2026 :                         } while (++p != end);
    1420          80 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1421             :                         do {
    1422         569 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1423         569 :                                 zend_string_release(p->key);
    1424         569 :                         } 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         415 :                 HT_HASH_RESET(ht);
    1434             :         }
    1435         429 :         ht->nNumUsed = 0;
    1436         429 :         ht->nNumOfElements = 0;
    1437         429 :         ht->nNextFreeElement = 0;
    1438         429 :         ht->nInternalPointer = HT_INVALID_IDX;
    1439         429 : }
    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       93990 : 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       93990 :         idx = ht->nNumUsed;
    1470       93990 :         p = ht->arData + ht->nNumUsed;
    1471     2209855 :         while (idx > 0) {
    1472     2021875 :                 idx--;
    1473     2021875 :                 p--;
    1474     4043750 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1475             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1476             :         }
    1477             : 
    1478       93990 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1479       71039 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1480             :         }
    1481             : 
    1482             :         SET_INCONSISTENT(HT_DESTROYED);
    1483       93990 : }
    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      355610 : 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      355610 :         HASH_PROTECT_RECURSION(ht);
    1503     2822179 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1504     2466574 :                 p = ht->arData + idx;
    1505     4933148 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1506     2242081 :                 result = apply_func(&p->val);
    1507             : 
    1508     2242076 :                 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     2242076 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1513           0 :                         break;
    1514             :                 }
    1515             :         }
    1516      355605 :         HASH_UNPROTECT_RECURSION(ht);
    1517      355605 : }
    1518             : 
    1519             : 
    1520      671969 : 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      671969 :         HASH_PROTECT_RECURSION(ht);
    1529   149658504 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1530   148990742 :                 p = ht->arData + idx;
    1531   297981484 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1532   107702746 :                 result = apply_func(&p->val, argument);
    1533             : 
    1534   107702746 :                 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   107702746 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1539        4207 :                         break;
    1540             :                 }
    1541             :         }
    1542      671969 :         HASH_UNPROTECT_RECURSION(ht);
    1543      671969 : }
    1544             : 
    1545             : 
    1546         176 : 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         176 :         HASH_PROTECT_RECURSION(ht);
    1557             : 
    1558      162362 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1559      162186 :                 p = ht->arData + idx;
    1560      324372 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1561      162120 :                 va_start(args, num_args);
    1562      162120 :                 hash_key.h = p->h;
    1563      162120 :                 hash_key.key = p->key;
    1564             : 
    1565      162120 :                 result = apply_func(&p->val, num_args, args, &hash_key);
    1566             : 
    1567      162120 :                 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      162120 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1572           0 :                         va_end(args);
    1573           0 :                         break;
    1574             :                 }
    1575      162120 :                 va_end(args);
    1576             :         }
    1577             : 
    1578         176 :         HASH_UNPROTECT_RECURSION(ht);
    1579         176 : }
    1580             : 
    1581             : 
    1582      122651 : 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      122651 :         HASH_PROTECT_RECURSION(ht);
    1591      122651 :         idx = ht->nNumUsed;
    1592      885989 :         while (idx > 0) {
    1593      711022 :                 idx--;
    1594      711022 :                 p = ht->arData + idx;
    1595     1422044 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1596             : 
    1597      656336 :                 result = apply_func(&p->val);
    1598             : 
    1599      656336 :                 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      656336 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1604       70335 :                         break;
    1605             :                 }
    1606             :         }
    1607      122651 :         HASH_UNPROTECT_RECURSION(ht);
    1608      122651 : }
    1609             : 
    1610             : 
    1611         473 : 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         473 :         setTargetPointer = (target->nInternalPointer == HT_INVALID_IDX);
    1623       12041 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1624       11568 :                 p = source->arData + idx;
    1625       23136 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1626             : 
    1627       11568 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1628         329 :                         target->nInternalPointer = HT_INVALID_IDX;
    1629             :                 }
    1630             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1631       11568 :                 data = &p->val;
    1632       11568 :                 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       11564 :                 if (p->key) {
    1639       11473 :                         new_entry = zend_hash_update(target, p->key, data);
    1640             :                 } else {
    1641          91 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1642             :                 }
    1643       11564 :                 if (pCopyConstructor) {
    1644         274 :                         pCopyConstructor(new_entry);
    1645             :                 }
    1646             :         }
    1647         473 :         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         473 : }
    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     3267676 :         zval *data = &p->val;
    1660             : 
    1661     3267676 :         if (with_holes) {
    1662     2437552 :                 if (!packed && Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1663           0 :                         data = Z_INDIRECT_P(data);
    1664             :                 }
    1665     2437552 :                 if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1666      811686 :                         return 0;
    1667             :                 }
    1668      830124 :         } else if (!packed) {
    1669             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1670      771628 :                 if (Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1671       21372 :                         data = Z_INDIRECT_P(data);
    1672       21372 :                         if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1673        3144 :                                 return 0;
    1674             :                         }
    1675             :                 }
    1676             :         }
    1677             : 
    1678             :         do {
    1679     2452846 :                 if (Z_OPT_REFCOUNTED_P(data)) {
    1680     2427885 :                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1 &&
    1681          65 :                             (Z_TYPE_P(Z_REFVAL_P(data)) != IS_ARRAY ||
    1682          18 :                               Z_ARRVAL_P(Z_REFVAL_P(data)) != source)) {
    1683          62 :                                 data = Z_REFVAL_P(data);
    1684          62 :                                 if (!Z_OPT_REFCOUNTED_P(data)) {
    1685             :                                         break;
    1686             :                                 }
    1687             :                         }
    1688             :                         Z_ADDREF_P(data);
    1689             :                 }
    1690             :         } while (0);
    1691     2452846 :         ZVAL_COPY_VALUE(&q->val, data);
    1692             : 
    1693     2452846 :         q->h = p->h;
    1694     2452846 :         if (packed) {
    1695     1684358 :                 q->key = NULL;
    1696             :         } else {
    1697             :                 uint32_t nIndex;
    1698             : 
    1699      768488 :                 q->key = p->key;
    1700      768488 :                 if (!static_keys && q->key) {
    1701      765094 :                         zend_string_addref(q->key);
    1702             :                 }
    1703             : 
    1704      768488 :                 nIndex = q->h | target->nTableMask;
    1705      768488 :                 Z_NEXT(q->val) = HT_HASH(target, nIndex);
    1706      768488 :                 HT_HASH(target, nIndex) = HT_IDX_TO_HASH(idx);
    1707             :         }
    1708     2452846 :         return 1;
    1709             : }
    1710             : 
    1711             : static zend_always_inline void zend_array_dup_packed_elements(HashTable *source, HashTable *target, int with_holes)
    1712             : {
    1713      834592 :         Bucket *p = source->arData;
    1714      834592 :         Bucket *q = target->arData;
    1715      834592 :         Bucket *end = p + source->nNumUsed;
    1716             : 
    1717             :         do {
    1718     2496042 :                 if (!zend_array_dup_element(source, target, 0, p, q, 1, 1, with_holes)) {
    1719      811684 :                         if (with_holes) {
    1720      811684 :                                 ZVAL_UNDEF(&q->val);
    1721             :                         }
    1722             :                 }
    1723     2496042 :                 p++; q++;
    1724     2496042 :         } 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       36107 :     uint32_t idx = 0;
    1730       36107 :         Bucket *p = source->arData;
    1731       36107 :         Bucket *q = target->arData;
    1732       36107 :         Bucket *end = p + source->nNumUsed;
    1733             : 
    1734             :         do {
    1735      758824 :                 if (!zend_array_dup_element(source, target, idx, p, q, 0, static_keys, with_holes)) {
    1736        2169 :                         uint32_t target_idx = idx;
    1737             : 
    1738        2169 :                         idx++; p++;
    1739       14979 :                         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        2169 :                         return target_idx;
    1749             :                 }
    1750      756655 :                 idx++; p++; q++;
    1751      756655 :         } while (p != end);
    1752       33938 :         return idx;
    1753             : }
    1754             : 
    1755     1380815 : 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     1380815 :         ALLOC_HASHTABLE(target);
    1763     1380815 :         GC_REFCOUNT(target) = 1;
    1764     1380815 :         GC_TYPE_INFO(target) = IS_ARRAY;
    1765             : 
    1766     1380815 :         target->nTableSize = source->nTableSize;
    1767     1380815 :         target->pDestructor = source->pDestructor;
    1768             : 
    1769     1380815 :         if (source->nNumUsed == 0) {
    1770      510101 :                 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      510101 :                 target->nTableMask = HT_MIN_MASK;
    1772      510101 :                 target->nNumUsed = 0;
    1773      510101 :                 target->nNumOfElements = 0;
    1774      510101 :                 target->nNextFreeElement = 0;
    1775      510101 :                 target->nInternalPointer = HT_INVALID_IDX;
    1776      510101 :                 HT_SET_DATA_ADDR(target, &uninitialized_bucket);
    1777      870714 :         } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) {
    1778          15 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1779          15 :                 target->nTableMask = source->nTableMask;
    1780          15 :                 target->nNumUsed = source->nNumUsed;
    1781          15 :                 target->nNumOfElements = source->nNumOfElements;
    1782          15 :                 target->nNextFreeElement = source->nNextFreeElement;
    1783          15 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1784          15 :                 target->nInternalPointer = source->nInternalPointer;
    1785          15 :                 memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source));
    1786          30 :                 if (target->nNumOfElements > 0 &&
    1787          15 :                     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      870699 :         } else if (source->u.flags & HASH_FLAG_PACKED) {
    1795      834592 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_PERSISTENT|ZEND_HASH_APPLY_COUNT_MASK)) | HASH_FLAG_APPLY_PROTECTION;
    1796      834592 :                 target->nTableMask = source->nTableMask;
    1797      834592 :                 target->nNumUsed = source->nNumUsed;
    1798      834592 :                 target->nNumOfElements = source->nNumOfElements;
    1799      834592 :                 target->nNextFreeElement = source->nNextFreeElement;
    1800      834592 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1801      834592 :                 target->nInternalPointer = source->nInternalPointer;
    1802      834592 :                 HT_HASH_RESET_PACKED(target);
    1803             : 
    1804      834592 :                 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     1669184 :                 if (target->nNumOfElements > 0 &&
    1810      834592 :                     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       36107 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_PERSISTENT|ZEND_HASH_APPLY_COUNT_MASK)) | HASH_FLAG_APPLY_PROTECTION;
    1819       36107 :                 target->nTableMask = source->nTableMask;
    1820       36107 :                 target->nNextFreeElement = source->nNextFreeElement;
    1821       36107 :                 target->nInternalPointer = HT_INVALID_IDX;
    1822       36107 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1823       36107 :                 HT_HASH_RESET(target);
    1824             : 
    1825       36107 :                 if (target->u.flags & HASH_FLAG_STATIC_KEYS) {
    1826         620 :                         if (source->nNumUsed == source->nNumOfElements) {
    1827         620 :                                 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       35487 :                         if (source->nNumUsed == source->nNumOfElements) {
    1833       35486 :                                 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       36107 :                 target->nNumUsed = idx;
    1839       36107 :                 target->nNumOfElements = idx;
    1840       36107 :                 if (idx > 0 && target->nInternalPointer == HT_INVALID_IDX) {
    1841       36103 :                         target->nInternalPointer = 0;
    1842             :                 }
    1843             :         }
    1844     1380815 :         return target;
    1845             : }
    1846             : 
    1847             : 
    1848      211171 : 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      211171 :         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     3636856 :                 for (idx = 0; idx < source->nNumUsed; idx++) {
    1880     3425686 :                         p = source->arData + idx;
    1881     6851372 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1882     6851372 :                         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     3425686 :                         if (p->key) {
    1887     6851266 :                                 t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_ADD | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
    1888     3425633 :                                 if (t && pCopyConstructor) {
    1889     3425051 :                                         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      211171 :         if (target->nNumOfElements > 0) {
    1900      211168 :                 idx = 0;
    1901      633504 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1902           0 :                         idx++;
    1903             :                 }
    1904      211168 :                 target->nInternalPointer = idx;
    1905             :         }
    1906      211171 : }
    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    64610760 : 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    64610760 :         p = zend_hash_find_bucket(ht, key);
    1957    64610760 :         return p ? &p->val : NULL;
    1958             : }
    1959             : 
    1960     2356971 : 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     2356971 :         h = zend_inline_hash_func(str, len);
    1968     2356971 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1969     2356971 :         return p ? &p->val : NULL;
    1970             : }
    1971             : 
    1972       61133 : 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       61133 :         p = zend_hash_find_bucket(ht, key);
    1979       61133 :         return p ? 1 : 0;
    1980             : }
    1981             : 
    1982     1058442 : 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     1058442 :         h = zend_inline_hash_func(str, len);
    1990     1058442 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1991     1058442 :         return p ? 1 : 0;
    1992             : }
    1993             : 
    1994     2566843 : 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     2566843 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2001     2054364 :                 if (h < ht->nNumUsed) {
    2002     2038987 :                         p = ht->arData + h;
    2003     4077974 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    2004     2038652 :                                 return &p->val;
    2005             :                         }
    2006             :                 }
    2007       15712 :                 return NULL;
    2008             :         }
    2009             : 
    2010      512479 :         p = zend_hash_index_find_bucket(ht, h);
    2011      512479 :         return p ? &p->val : NULL;
    2012             : }
    2013             : 
    2014      682329 : 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      682329 :         p = zend_hash_index_find_bucket(ht, h);
    2021      682329 :         return p ? &p->val : NULL;
    2022             : }
    2023             : 
    2024     1741473 : 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     1741473 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2031        1074 :                 if (h < ht->nNumUsed) {
    2032         136 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    2033          61 :                                 return 1;
    2034             :                         }
    2035             :                 }
    2036        1013 :                 return 0;
    2037             :         }
    2038             : 
    2039     1740399 :         p = zend_hash_index_find_bucket(ht, h);
    2040     1740399 :         return p ? 1 : 0;
    2041             : }
    2042             : 
    2043             : 
    2044      219402 : 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      220024 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    2052       39702 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2053       19229 :                         *pos = idx;
    2054       19229 :                         return;
    2055             :                 }
    2056             :         }
    2057      200173 :         *pos = HT_INVALID_IDX;
    2058             : }
    2059             : 
    2060             : 
    2061             : /* This function will be extremely optimized by remembering
    2062             :  * the end of the list
    2063             :  */
    2064          75 : 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          75 :         idx = ht->nNumUsed;
    2072         150 :         while (idx > 0) {
    2073          73 :                 idx--;
    2074         146 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2075          73 :                         *pos = idx;
    2076          73 :                         return;
    2077             :                 }
    2078             :         }
    2079           2 :         *pos = HT_INVALID_IDX;
    2080             : }
    2081             : 
    2082             : 
    2083       68846 : ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    2084             : {
    2085       68846 :         uint32_t idx = *pos;
    2086             : 
    2087             :         IS_CONSISTENT(ht);
    2088             :         HT_ASSERT(&ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
    2089             : 
    2090       68846 :         if (idx != HT_INVALID_IDX) {
    2091             :                 while (1) {
    2092       68884 :                         idx++;
    2093       68884 :                         if (idx >= ht->nNumUsed) {
    2094       16347 :                                 *pos = HT_INVALID_IDX;
    2095       16347 :                                 return SUCCESS;
    2096             :                         }
    2097      105074 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2098       52464 :                                 *pos = idx;
    2099       52464 :                                 return SUCCESS;
    2100             :                         }
    2101          73 :                 }
    2102             :         } else {
    2103          35 :                 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       13235 : 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       13235 :         uint32_t idx = *pos;
    2134             :         Bucket *p;
    2135             : 
    2136             :         IS_CONSISTENT(ht);
    2137       13235 :         if (idx != HT_INVALID_IDX) {
    2138       12778 :                 p = ht->arData + idx;
    2139       12778 :                 if (p->key) {
    2140       11454 :                         *str_index = p->key;
    2141       11454 :                         return HASH_KEY_IS_STRING;
    2142             :                 } else {
    2143        1324 :                         *num_index = p->h;
    2144        1324 :                         return HASH_KEY_IS_LONG;
    2145             :                 }
    2146             :         }
    2147         457 :         return HASH_KEY_NON_EXISTENT;
    2148             : }
    2149             : 
    2150        3494 : ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    2151             : {
    2152        3494 :         uint32_t idx = *pos;
    2153             :         Bucket *p;
    2154             : 
    2155             :         IS_CONSISTENT(ht);
    2156        3494 :         if (idx == HT_INVALID_IDX) {
    2157          53 :                 ZVAL_NULL(key);
    2158             :         } else {
    2159        3441 :                 p = ht->arData + idx;
    2160        3441 :                 if (p->key) {
    2161         680 :                         ZVAL_STR_COPY(key, p->key);
    2162             :                 } else {
    2163        2761 :                         ZVAL_LONG(key, p->h);
    2164             :                 }
    2165             :         }
    2166        3494 : }
    2167             : 
    2168      279119 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    2169             : {
    2170      279119 :     uint32_t idx = *pos;
    2171             :         Bucket *p;
    2172             : 
    2173             :         IS_CONSISTENT(ht);
    2174      279119 :         if (idx != HT_INVALID_IDX) {
    2175       63845 :                 p = ht->arData + idx;
    2176       63845 :                 if (p->key) {
    2177       51078 :                         return HASH_KEY_IS_STRING;
    2178             :                 } else {
    2179       12767 :                         return HASH_KEY_IS_LONG;
    2180             :                 }
    2181             :         }
    2182      215274 :         return HASH_KEY_NON_EXISTENT;
    2183             : }
    2184             : 
    2185             : 
    2186       66274 : ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    2187             : {
    2188       66274 :         uint32_t idx = *pos;
    2189             :         Bucket *p;
    2190             : 
    2191             :         IS_CONSISTENT(ht);
    2192       66274 :         if (idx != HT_INVALID_IDX) {
    2193       65414 :                 p = ht->arData + idx;
    2194       65414 :                 return &p->val;
    2195             :         } else {
    2196         860 :                 return NULL;
    2197             :         }
    2198             : }
    2199             : 
    2200       96488 : 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       96488 :         ZVAL_COPY_VALUE(&val, &p->val);
    2207       96488 :         h = p->h;
    2208       96488 :         key = p->key;
    2209             : 
    2210       96488 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2211       96488 :         p->h = q->h;
    2212       96488 :         p->key = q->key;
    2213             : 
    2214       96488 :         ZVAL_COPY_VALUE(&q->val, &val);
    2215       96488 :         q->h = h;
    2216       96488 :         q->key = key;
    2217       96488 : }
    2218             : 
    2219       76907 : ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
    2220             : {
    2221             :         zval val;
    2222             : 
    2223       76907 :         ZVAL_COPY_VALUE(&val, &p->val);
    2224       76907 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2225       76907 :         ZVAL_COPY_VALUE(&q->val, &val);
    2226       76907 : }
    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       25197 : 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       25197 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    2252         298 :                 return SUCCESS;
    2253             :         }
    2254             : 
    2255       24899 :         if (ht->nNumUsed == ht->nNumOfElements) {
    2256       24805 :                 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       49489 :         sort((void *)ht->arData, i, sizeof(Bucket), compar,
    2269             :                         (swap_func_t)(renumber? zend_hash_bucket_renum_swap :
    2270       24590 :                                 ((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
    2271             : 
    2272       24899 :         ht->nNumUsed = i;
    2273       24899 :         ht->nInternalPointer = 0;
    2274             : 
    2275       24899 :         if (renumber) {
    2276       17568 :                 for (j = 0; j < i; j++) {
    2277       17259 :                         p = ht->arData + j;
    2278       17259 :                         p->h = j;
    2279       17259 :                         if (p->key) {
    2280         232 :                                 zend_string_release(p->key);
    2281         232 :                                 p->key = NULL;
    2282             :                         }
    2283             :                 }
    2284             : 
    2285         309 :                 ht->nNextFreeElement = i;
    2286             :         }
    2287       24899 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2288         510 :                 if (!renumber) {
    2289         247 :                         zend_hash_packed_to_hash(ht);
    2290             :                 }
    2291             :         } else {
    2292       24389 :                 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       24343 :                         zend_hash_rehash(ht);
    2305             :                 }
    2306             :         }
    2307             : 
    2308       24899 :         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         918 :         if (ht1->nNumOfElements != ht2->nNumOfElements) {
    2315         326 :                 return ht1->nNumOfElements > ht2->nNumOfElements ? 1 : -1;
    2316             :         }
    2317             : 
    2318        4335 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    2319        3925 :                 Bucket *p1 = ht1->arData + idx1, *p2;
    2320             :                 zval *pData1, *pData2;
    2321             :                 int result;
    2322             : 
    2323        7850 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    2324        3908 :                 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        2761 :                         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        2273 :                                 pData2 = zend_hash_find(ht2, p1->key);
    2358        2273 :                                 if (pData2 == NULL) {
    2359          13 :                                         return 1;
    2360             :                                 }
    2361             :                         }
    2362             :                 }
    2363             : 
    2364        3890 :                 pData1 = &p1->val;
    2365        3890 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    2366         129 :                         pData1 = Z_INDIRECT_P(pData1);
    2367             :                 }
    2368        3890 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    2369         129 :                         pData2 = Z_INDIRECT_P(pData2);
    2370             :                 }
    2371             : 
    2372        3890 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    2373           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    2374           0 :                                 return -1;
    2375             :                         }
    2376        3890 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    2377           0 :                         return 1;
    2378             :                 } else {
    2379        3890 :                         result = compar(pData1, pData2);
    2380        3890 :                         if (result != 0) {
    2381         164 :                                 return result;
    2382             :                         }
    2383             :                 }
    2384             :         }
    2385             : 
    2386         410 :         return 0;
    2387             : }
    2388             : 
    2389         918 : 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         918 :         HASH_PROTECT_RECURSION(ht1);
    2396         918 :         HASH_PROTECT_RECURSION(ht2);
    2397        1836 :         result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
    2398         918 :         HASH_UNPROTECT_RECURSION(ht1);
    2399         918 :         HASH_UNPROTECT_RECURSION(ht2);
    2400             : 
    2401         918 :         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      384183 : ZEND_API int ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    2443             : {
    2444      384183 :         register const char *tmp = key;
    2445             : 
    2446      384183 :         const char *end = key + length;
    2447             :         ZEND_ASSERT(*end == '\0');
    2448             : 
    2449      384183 :         if (*tmp == '-') {
    2450          62 :                 tmp++;
    2451             :         }
    2452             : 
    2453      748154 :         if ((*tmp == '0' && length > 1) /* numbers with leading zeros */
    2454      363971 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    2455             :          || (SIZEOF_ZEND_LONG == 4 &&
    2456             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    2457             :              *tmp > '2')) { /* overflow */
    2458       20239 :                 return 0;
    2459             :         }
    2460      363944 :         *idx = (*tmp - '0');
    2461             :         while (1) {
    2462     1447235 :                 ++tmp;
    2463     1447235 :                 if (tmp == end) {
    2464      363546 :                         if (*key == '-') {
    2465          31 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    2466           0 :                                         return 0;
    2467             :                                 }
    2468          31 :                                 *idx = 0 - *idx;
    2469      363515 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    2470           0 :                                 return 0;
    2471             :                         }
    2472      363546 :                         return 1;
    2473             :                 }
    2474     2166980 :                 if (*tmp <= '9' && *tmp >= '0') {
    2475     1083291 :                         *idx = (*idx * 10) + (*tmp - '0');
    2476             :                 } else {
    2477         398 :                         return 0;
    2478             :                 }
    2479     1083291 :         }
    2480             : }
    2481             : 
    2482             : /*
    2483             :  * Local variables:
    2484             :  * tab-width: 4
    2485             :  * c-basic-offset: 4
    2486             :  * indent-tabs-mode: t
    2487             :  * End:
    2488             :  */

Generated by: LCOV version 1.10

Generated at Tue, 26 Jul 2016 17:07:32 +0000 (2 days ago)

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