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: 1076 1204 89.4 %
Date: 2015-08-29 Functions: 69 77 89.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 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             :    +----------------------------------------------------------------------+
      18             : */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : #include "zend.h"
      23             : #include "zend_globals.h"
      24             : #include "zend_variables.h"
      25             : 
      26             : #define HT_DEBUG 0
      27             : #if HT_DEBUG
      28             : # define HT_ASSERT(c) ZEND_ASSERT(c)
      29             : #else
      30             : # define HT_ASSERT(c)
      31             : #endif
      32             : 
      33             : #if ZEND_DEBUG
      34             : /*
      35             : #define HASH_MASK_CONSISTENCY   0xc0
      36             : */
      37             : #define HT_OK                                   0x00
      38             : #define HT_IS_DESTROYING                0x40
      39             : #define HT_DESTROYED                    0x80
      40             : #define HT_CLEANING                             0xc0
      41             : 
      42             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      43             : {
      44             :         if ((ht->u.flags & HASH_MASK_CONSISTENCY) == HT_OK) {
      45             :                 return;
      46             :         }
      47             :         switch ((ht->u.flags & HASH_MASK_CONSISTENCY)) {
      48             :                 case HT_IS_DESTROYING:
      49             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      50             :                         break;
      51             :                 case HT_DESTROYED:
      52             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      53             :                         break;
      54             :                 case HT_CLEANING:
      55             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      56             :                         break;
      57             :                 default:
      58             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      59             :                         break;
      60             :         }
      61             :         zend_bailout();
      62             : }
      63             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      64             : #define SET_INCONSISTENT(n) do { \
      65             :                 (ht)->u.flags |= n; \
      66             :         } while (0)
      67             : #else
      68             : #define IS_CONSISTENT(a)
      69             : #define SET_INCONSISTENT(n)
      70             : #endif
      71             : 
      72             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      73             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      74             :                 if (((ht)->u.flags & ZEND_HASH_APPLY_COUNT_MASK) >= (3 << 8)) {                                                                                         \
      75             :                         zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");\
      76             :                 }                                                                                                                                                               \
      77             :                 ZEND_HASH_INC_APPLY_COUNT(ht);                                                                                                  \
      78             :         }
      79             : 
      80             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      81             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      82             :                 ZEND_HASH_DEC_APPLY_COUNT(ht);                                                                                                  \
      83             :         }
      84             : 
      85             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
      86             :         if ((ht)->nNumUsed >= (ht)->nTableSize) {              \
      87             :                 zend_hash_do_resize(ht);                                        \
      88             :         }
      89             : 
      90             : static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht);
      91             : 
      92             : static uint32_t zend_always_inline zend_hash_check_size(uint32_t nSize)
      93             : {
      94             : #if defined(ZEND_WIN32)
      95             :         unsigned long index;
      96             : #endif
      97             : 
      98             :         /* Use big enough power of 2 */
      99             :         /* size should be between HT_MIN_SIZE and HT_MAX_SIZE */
     100    19682223 :         if (nSize < HT_MIN_SIZE) {
     101     5240930 :                 nSize = HT_MIN_SIZE;
     102    14441293 :         } else if (UNEXPECTED(nSize >= HT_MAX_SIZE)) {
     103           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nSize, sizeof(Bucket), sizeof(Bucket));
     104             :         }
     105             : 
     106             : #if defined(ZEND_WIN32)
     107             :         if (BitScanReverse(&index, nSize - 1)) {
     108             :                 return 0x2 << ((31 - index) ^ 0x1f);
     109             :         } else {
     110             :                 /* nSize is ensured to be in the valid range, fall back to it
     111             :                    rather than using an undefined bis scan result. */
     112             :                 return nSize;
     113             :         }
     114             : #elif defined(__GNUC__) || __has_builtin(__builtin_clz)
     115    19682223 :         return 0x2 << (__builtin_clz(nSize - 1) ^ 0x1f);
     116             : #else
     117             :         nSize -= 1;
     118             :         nSize |= (nSize >> 1);
     119             :         nSize |= (nSize >> 2);
     120             :         nSize |= (nSize >> 4);
     121             :         nSize |= (nSize >> 8);
     122             :         nSize |= (nSize >> 16);
     123             :         return nSize + 1;
     124             : #endif
     125             : }
     126             : 
     127             : static void zend_always_inline zend_hash_real_init_ex(HashTable *ht, int packed)
     128             : {
     129             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     130             :         ZEND_ASSERT(!((ht)->u.flags & HASH_FLAG_INITIALIZED));
     131     9487597 :         if (packed) {
     132     3896488 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     133     1948244 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED;
     134     1948244 :                 HT_HASH_RESET_PACKED(ht);
     135             :         } else {
     136     7539353 :                 (ht)->nTableMask = -(ht)->nTableSize;
     137    15078706 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     138     7539353 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED;
     139     7539353 :                 if (EXPECTED(ht->nTableMask == -8)) {
     140     6530095 :                         Bucket *arData = ht->arData;
     141             : 
     142     6530095 :                         HT_HASH_EX(arData, -8) = -1;
     143     6530095 :                         HT_HASH_EX(arData, -7) = -1;
     144     6530095 :                         HT_HASH_EX(arData, -6) = -1;
     145     6530095 :                         HT_HASH_EX(arData, -5) = -1;
     146     6530095 :                         HT_HASH_EX(arData, -4) = -1;
     147     6530095 :                         HT_HASH_EX(arData, -3) = -1;
     148     6530095 :                         HT_HASH_EX(arData, -2) = -1;
     149     6530095 :                         HT_HASH_EX(arData, -1) = -1;
     150             :                 } else {
     151     1009258 :                         HT_HASH_RESET(ht);
     152             :                 }
     153             :         }
     154             : }
     155             : 
     156             : static void zend_always_inline zend_hash_check_init(HashTable *ht, int packed)
     157             : {
     158             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     159     9300341 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     160             :                 zend_hash_real_init_ex(ht, packed);
     161             :         }
     162             : }
     163             : 
     164             : #define CHECK_INIT(ht, packed) \
     165             :         zend_hash_check_init(ht, packed)
     166             : 
     167             : static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
     168             :         {HT_INVALID_IDX, HT_INVALID_IDX};
     169             : 
     170    18018680 : ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     171             : {
     172    18018680 :         GC_REFCOUNT(ht) = 1;
     173    18018680 :         GC_TYPE_INFO(ht) = IS_ARRAY;
     174    18018680 :         ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
     175    18018680 :         ht->nTableSize = zend_hash_check_size(nSize);
     176    18018680 :         ht->nTableMask = HT_MIN_MASK;
     177    18018680 :         HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
     178    18018680 :         ht->nNumUsed = 0;
     179    18018680 :         ht->nNumOfElements = 0;
     180    18018680 :         ht->nInternalPointer = HT_INVALID_IDX;
     181    18018680 :         ht->nNextFreeElement = 0;
     182    18018680 :         ht->pDestructor = pDestructor;
     183    18018680 : }
     184             : 
     185       15765 : static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
     186             : {
     187             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     188       15765 :         if (ht->nTableSize >= HT_MAX_SIZE) {
     189           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
     190             :         }
     191       15765 :         HANDLE_BLOCK_INTERRUPTIONS();
     192       15765 :         ht->nTableSize += ht->nTableSize;
     193       31530 :         HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
     194       15765 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     195       15765 : }
     196             : 
     197      187256 : ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, zend_bool packed)
     198             : {
     199             :         IS_CONSISTENT(ht);
     200             : 
     201             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     202      187256 :         zend_hash_real_init_ex(ht, packed);
     203      187256 : }
     204             : 
     205       28926 : ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
     206             : {
     207       28926 :         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     208       28926 :         Bucket *old_buckets = ht->arData;
     209             : 
     210             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     211       28926 :         HANDLE_BLOCK_INTERRUPTIONS();
     212       28926 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     213       57852 :         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, -ht->nTableSize), (ht)->u.flags & HASH_FLAG_PERSISTENT);
     214       28926 :         ht->nTableMask = -ht->nTableSize;
     215       28926 :         HT_SET_DATA_ADDR(ht, new_data);
     216       28926 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     217       28926 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     218       28926 :         zend_hash_rehash(ht);
     219       28926 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     220       28926 : }
     221             : 
     222          15 : ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
     223             : {
     224          15 :         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     225          15 :         Bucket *old_buckets = ht->arData;
     226             : 
     227             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     228          15 :         HANDLE_BLOCK_INTERRUPTIONS();
     229          30 :         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (ht)->u.flags & HASH_FLAG_PERSISTENT);
     230          15 :         ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
     231          15 :         ht->nTableMask = HT_MIN_MASK;
     232          15 :         HT_SET_DATA_ADDR(ht, new_data);
     233          15 :         HT_HASH_RESET_PACKED(ht);
     234          15 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     235          15 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     236          15 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     237          15 : }
     238             : 
     239    12350155 : 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)
     240             : {
     241    12350155 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
     242    12350155 :         if (!bApplyProtection) {
     243    12350155 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     244             :         }
     245    12350155 : }
     246             : 
     247     2831774 : ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, zend_bool packed)
     248             : {
     249             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     250     2831774 :         if (nSize == 0) return;
     251     2689614 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     252     1599105 :                 if (nSize > ht->nTableSize) {
     253      768001 :                         ht->nTableSize = zend_hash_check_size(nSize);
     254             :                 }
     255     1599105 :                 zend_hash_check_init(ht, packed);
     256             :         } else {
     257     1090509 :                 if (packed) {
     258             :                         ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED);
     259           0 :                         if (nSize > ht->nTableSize) {
     260           0 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     261           0 :                                 ht->nTableSize = zend_hash_check_size(nSize);
     262           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));
     263           0 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     264             :                         }
     265             :                 } else {
     266             :                         ZEND_ASSERT(!(ht->u.flags & HASH_FLAG_PACKED));
     267     1090509 :                         if (nSize > ht->nTableSize) {
     268      895542 :                                 void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     269      895542 :                                 Bucket *old_buckets = ht->arData;
     270      895542 :                                 nSize = zend_hash_check_size(nSize);
     271      895542 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     272     1791084 :                                 new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT);
     273      895542 :                                 ht->nTableSize = nSize;
     274      895542 :                                 ht->nTableMask = -ht->nTableSize;
     275      895542 :                                 HT_SET_DATA_ADDR(ht, new_data);
     276      895542 :                                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     277      895542 :                                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     278      895542 :                                 zend_hash_rehash(ht);
     279      895542 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     280             :                         }
     281             :                 }
     282             :         }
     283             : }
     284             : 
     285           0 : ZEND_API void ZEND_FASTCALL zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     286             : {
     287           0 :         if (bApplyProtection) {
     288           0 :                 ht->u.flags |= HASH_FLAG_APPLY_PROTECTION;
     289             :         } else {
     290           0 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     291             :         }
     292           0 : }
     293             : 
     294         699 : ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPosition pos)
     295             : {
     296         699 :         HashTableIterator *iter = EG(ht_iterators);
     297         699 :         HashTableIterator *end  = iter + EG(ht_iterators_count);
     298             :         uint32_t idx;
     299             : 
     300         699 :         if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     301         699 :                 ht->u.v.nIteratorsCount++;
     302             :         }
     303        1856 :         while (iter != end) {
     304        1157 :                 if (iter->ht == NULL) {
     305         699 :                         iter->ht = ht;
     306         699 :                         iter->pos = pos;
     307         699 :                         idx = iter - EG(ht_iterators);
     308         699 :                         if (idx + 1 > EG(ht_iterators_used)) {
     309         685 :                                 EG(ht_iterators_used) = idx + 1;
     310             :                         }
     311         699 :                         return idx;
     312             :                 }
     313         458 :                 iter++;
     314             :         }
     315           0 :         if (EG(ht_iterators) == EG(ht_iterators_slots)) {
     316           0 :                 EG(ht_iterators) = emalloc(sizeof(HashTableIterator) * (EG(ht_iterators_count) + 8));
     317           0 :                 memcpy(EG(ht_iterators), EG(ht_iterators_slots), sizeof(HashTableIterator) * EG(ht_iterators_count));
     318             :         } else {
     319           0 :                 EG(ht_iterators) = erealloc(EG(ht_iterators), sizeof(HashTableIterator) * (EG(ht_iterators_count) + 8));
     320             :         }
     321           0 :         iter = EG(ht_iterators) + EG(ht_iterators_count);
     322           0 :         EG(ht_iterators_count) += 8;
     323           0 :         iter->ht = ht;
     324           0 :         iter->pos = pos;
     325           0 :         memset(iter + 1, 0, sizeof(HashTableIterator) * 7);
     326           0 :         idx = iter - EG(ht_iterators);
     327           0 :         EG(ht_iterators_used) = idx + 1;
     328           0 :         return idx;
     329             : }
     330             : 
     331        1389 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTable *ht)
     332             : {
     333        1389 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     334             : 
     335             :         ZEND_ASSERT(idx != (uint32_t)-1);
     336        1389 :         if (iter->pos == HT_INVALID_IDX) {
     337         175 :                 return HT_INVALID_IDX;
     338        1214 :         } else if (UNEXPECTED(iter->ht != ht)) {
     339           0 :                 if (EXPECTED(iter->ht) && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     340           0 :                         iter->ht->u.v.nIteratorsCount--;
     341             :                 }
     342           0 :                 if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     343           0 :                         ht->u.v.nIteratorsCount++;
     344             :                 }
     345           0 :                 iter->ht = ht;
     346           0 :                 iter->pos = ht->nInternalPointer;
     347             :         }
     348        1214 :         return iter->pos;
     349             : }
     350             : 
     351         188 : ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
     352             : {
     353         188 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     354             : 
     355             :         ZEND_ASSERT(idx != (uint32_t)-1);
     356             : 
     357         188 :         if (EXPECTED(iter->ht) && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     358         188 :                 iter->ht->u.v.nIteratorsCount--;
     359             :         }
     360         188 :         iter->ht = NULL;
     361             : 
     362         188 :         if (idx == EG(ht_iterators_used) - 1) {
     363         376 :                 while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) {
     364           0 :                         idx--;
     365             :                 }
     366         188 :                 EG(ht_iterators_used) = idx;
     367             :         }
     368         188 : }
     369             : 
     370         493 : static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTable *ht)
     371             : {
     372         493 :         HashTableIterator *iter = EG(ht_iterators);
     373         493 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     374             :         uint32_t idx;
     375             : 
     376        1961 :         while (iter != end) {
     377         975 :                 if (iter->ht == ht) {
     378         503 :                         iter->ht = NULL;
     379             :                 }
     380         975 :                 iter++;
     381             :         }
     382             : 
     383         493 :         idx = EG(ht_iterators_used);
     384        1472 :         while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) {
     385         486 :                 idx--;
     386             :         }
     387         493 :         EG(ht_iterators_used) = idx;
     388         493 : }
     389             : 
     390             : static zend_always_inline void zend_hash_iterators_remove(HashTable *ht)
     391             : {
     392    10488240 :         if (UNEXPECTED(ht->u.v.nIteratorsCount)) {
     393         493 :                 _zend_hash_iterators_remove(ht);
     394             :         }
     395             : }
     396             : 
     397         200 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterators_lower_pos(HashTable *ht, HashPosition start)
     398             : {
     399         200 :         HashTableIterator *iter = EG(ht_iterators);
     400         200 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     401         200 :         HashPosition res = HT_INVALID_IDX;
     402             : 
     403         490 :         while (iter != end) {
     404          90 :                 if (iter->ht == ht) {
     405          90 :                         if (iter->pos >= start && iter->pos < res) {
     406          48 :                                 res = iter->pos;
     407             :                         }
     408             :                 }
     409          90 :                 iter++;
     410             :         }
     411         200 :         return res;
     412             : }
     413             : 
     414         237 : ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to)
     415             : {
     416         237 :         HashTableIterator *iter = EG(ht_iterators);
     417         237 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     418             : 
     419         739 :         while (iter != end) {
     420         265 :                 if (iter->ht == ht && iter->pos == from) {
     421          77 :                         iter->pos = to;
     422             :                 }
     423         265 :                 iter++;
     424             :         }
     425         237 : }
     426             : 
     427             : static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
     428             : {
     429             :         zend_ulong h;
     430             :         uint32_t nIndex;
     431             :         uint32_t idx;
     432             :         Bucket *p, *arData;
     433             : 
     434   240578855 :         h = zend_string_hash_val(key);
     435   240578855 :         arData = ht->arData;
     436   240578855 :         nIndex = h | ht->nTableMask;
     437   240578855 :         idx = HT_HASH_EX(arData, nIndex);
     438   380292785 :         while (EXPECTED(idx != HT_INVALID_IDX)) {
     439   153629803 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     440   153629803 :                 if (EXPECTED(p->key == key)) { /* check for the same interned string */
     441     9300318 :                         return p;
     442   158182624 :                 } else if (EXPECTED(p->h == h) &&
     443     4617713 :                      EXPECTED(p->key) &&
     444     4617713 :                      EXPECTED(ZSTR_LEN(p->key) == ZSTR_LEN(key)) &&
     445     4617713 :                      EXPECTED(memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
     446     4615555 :                         return p;
     447             :                 }
     448   139713930 :                 idx = Z_NEXT(p->val);
     449             :         }
     450   226662982 :         return NULL;
     451             : }
     452             : 
     453             : static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
     454             : {
     455             :         uint32_t nIndex;
     456             :         uint32_t idx;
     457             :         Bucket *p, *arData;
     458             : 
     459     2907241 :         arData = ht->arData;
     460     2907241 :         nIndex = h | ht->nTableMask;
     461     2907241 :         idx = HT_HASH_EX(arData, nIndex);
     462     3592111 :         while (idx != HT_INVALID_IDX) {
     463             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     464     2855416 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     465     9367105 :                 if ((p->h == h)
     466             :                          && p->key
     467     4341126 :                          && (ZSTR_LEN(p->key) == len)
     468     2170563 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
     469     2170546 :                         return p;
     470             :                 }
     471      684870 :                 idx = Z_NEXT(p->val);
     472             :         }
     473      736695 :         return NULL;
     474             : }
     475             : 
     476             : static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
     477             : {
     478             :         uint32_t nIndex;
     479             :         uint32_t idx;
     480             :         Bucket *p, *arData;
     481             : 
     482     4083804 :         arData = ht->arData;
     483     4083804 :         nIndex = h | ht->nTableMask;
     484     4083804 :         idx = HT_HASH_EX(arData, nIndex);
     485     5556463 :         while (idx != HT_INVALID_IDX) {
     486             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     487     2497336 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     488     2497336 :                 if (p->h == h && !p->key) {
     489     1024677 :                         return p;
     490             :                 }
     491     1472659 :                 idx = Z_NEXT(p->val);
     492             :         }
     493     3059127 :         return NULL;
     494             : }
     495             : 
     496             : 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)
     497             : {
     498             :         zend_ulong h;
     499             :         uint32_t nIndex;
     500             :         uint32_t idx;
     501             :         Bucket *p;
     502             : 
     503             :         IS_CONSISTENT(ht);
     504             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     505             : 
     506   190699390 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     507             :                 CHECK_INIT(ht, 0);
     508             :                 goto add_to_hash;
     509   184944697 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     510       27351 :                 zend_hash_packed_to_hash(ht);
     511   184917346 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     512   182559401 :                 p = zend_hash_find_bucket(ht, key);
     513             : 
     514   182559401 :                 if (p) {
     515             :                         zval *data;
     516             : 
     517      567284 :                         if (flag & HASH_ADD) {
     518      267482 :                                 return NULL;
     519             :                         }
     520             :                         ZEND_ASSERT(&p->val != pData);
     521      299802 :                         data = &p->val;
     522      354501 :                         if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     523         285 :                                 data = Z_INDIRECT_P(data);
     524             :                         }
     525      299802 :                         HANDLE_BLOCK_INTERRUPTIONS();
     526      299802 :                         if (ht->pDestructor) {
     527      256846 :                                 ht->pDestructor(data);
     528             :                         }
     529      299802 :                         ZVAL_COPY_VALUE(data, pData);
     530      299802 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     531      299802 :                         return data;
     532             :                 }
     533             :         }
     534             : 
     535   184377413 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     536             : 
     537             : add_to_hash:
     538   190132106 :         HANDLE_BLOCK_INTERRUPTIONS();
     539   190132106 :         idx = ht->nNumUsed++;
     540   190132106 :         ht->nNumOfElements++;
     541   190132106 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     542     5933475 :                 ht->nInternalPointer = idx;
     543             :         }
     544             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     545   190132106 :         p = ht->arData + idx;
     546   190132106 :         p->key = key;
     547   190132106 :         if (!ZSTR_IS_INTERNED(key)) {
     548             :                 zend_string_addref(key);
     549   103611068 :                 ht->u.flags &= ~HASH_FLAG_STATIC_KEYS;
     550             :                 zend_string_hash_val(key);
     551             :         }
     552   190132106 :         p->h = h = ZSTR_H(key);
     553   190132106 :         ZVAL_COPY_VALUE(&p->val, pData);
     554   190132106 :         nIndex = h | ht->nTableMask;
     555   190132106 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     556   190132106 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     557   190132106 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     558             : 
     559   190132106 :         return &p->val;
     560             : }
     561             : 
     562     3109981 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     563             : {
     564     3109981 :         return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     565             : }
     566             : 
     567   139307750 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     568             : {
     569   139307750 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     570             : }
     571             : 
     572     7872047 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     573             : {
     574     7872047 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     575             : }
     576             : 
     577        1140 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     578             : {
     579        1140 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     580             : }
     581             : 
     582     2398532 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     583             : {
     584     2398532 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     585             : }
     586             : 
     587           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)
     588             : {
     589           0 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     590           0 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     591             :         zend_string_release(key);
     592           0 :         return ret;
     593             : }
     594             : 
     595    23632776 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     596             : {
     597    47265552 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     598    23632776 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     599             :         zend_string_release(key);
     600    23632776 :         return ret;
     601             : }
     602             : 
     603     1312231 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     604             : {
     605     2624462 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     606     1312231 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     607             :         zend_string_release(key);
     608     1312231 :         return ret;
     609             : }
     610             : 
     611    13062067 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     612             : {
     613    26124134 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     614    13062067 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     615             :         zend_string_release(key);
     616    13062067 :         return ret;
     617             : }
     618             : 
     619        2866 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     620             : {
     621        5732 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     622        2866 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     623             :         zend_string_delref(key);
     624        2866 :         return ret;
     625             : }
     626             : 
     627           0 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     628             : {
     629             :         zval dummy;
     630             : 
     631           0 :         ZVAL_NULL(&dummy);
     632           0 :         return zend_hash_index_add(ht, h, &dummy);
     633             : }
     634             : 
     635       49918 : ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     636             : {
     637             :         zval dummy;
     638             : 
     639       49918 :         ZVAL_NULL(&dummy);
     640       49918 :         return zend_hash_add(ht, key, &dummy);
     641             : }
     642             : 
     643      503777 : ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
     644             : {
     645             :         zval dummy;
     646             : 
     647      503777 :         ZVAL_NULL(&dummy);
     648      503777 :         return zend_hash_str_add(ht, str, len, &dummy);
     649             : }
     650             : 
     651             : 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)
     652             : {
     653             :         uint32_t nIndex;
     654             :         uint32_t idx;
     655             :         Bucket *p;
     656             : 
     657             :         IS_CONSISTENT(ht);
     658             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     659             : 
     660     7191726 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     661     1946543 :                 CHECK_INIT(ht, h < ht->nTableSize);
     662     1946543 :                 if (h < ht->nTableSize) {
     663     1844248 :                         p = ht->arData + h;
     664             :                         goto add_to_packed;
     665             :                 }
     666             :                 goto add_to_hash;
     667     5245183 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     668     3266797 :                 if (h < ht->nNumUsed) {
     669        3774 :                         p = ht->arData + h;
     670        7548 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     671        3621 :                                 if (flag & HASH_ADD) {
     672           0 :                                         return NULL;
     673             :                                 }
     674        3621 :                                 if (ht->pDestructor) {
     675        3621 :                                         ht->pDestructor(&p->val);
     676             :                                 }
     677        3621 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     678        3621 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     679           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     680             :                                 }
     681        3621 :                                 return &p->val;
     682             :                         } else { /* we have to keep the order :( */
     683             :                                 goto convert_to_hash;
     684             :                         }
     685     3263023 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     686     3246080 :                         p = ht->arData + h;
     687       33808 :                 } else if ((h >> 1) < ht->nTableSize &&
     688       16865 :                            (ht->nTableSize >> 1) < ht->nNumOfElements) {
     689       15765 :                         zend_hash_packed_grow(ht);
     690       15765 :                         p = ht->arData + h;
     691             :                 } else {
     692             :                         goto convert_to_hash;
     693             :                 }
     694             : 
     695             : add_to_packed:
     696     5106093 :                 HANDLE_BLOCK_INTERRUPTIONS();
     697             :                 /* incremental initialization of empty Buckets */
     698     5106093 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     699     1184162 :                         ht->nNumUsed = h + 1;
     700     3921931 :                 } else if (h >= ht->nNumUsed) {
     701     3921931 :                         if (h > ht->nNumUsed) {
     702      900007 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     703     1807150 :                                 while (q != p) {
     704      907143 :                                         ZVAL_UNDEF(&q->val);
     705      907143 :                                         q++;
     706             :                                 }
     707             :                         }
     708     3921931 :                         ht->nNumUsed = h + 1;
     709             :                 }
     710     5106093 :                 ht->nNumOfElements++;
     711     5106093 :                 if (ht->nInternalPointer == HT_INVALID_IDX) {
     712     1844369 :                         ht->nInternalPointer = h;
     713             :                 }
     714     5106093 :                 zend_hash_iterators_update(ht, HT_INVALID_IDX, h);
     715     5106093 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     716     5106082 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     717             :                 }
     718     5106093 :                 p->h = h;
     719     5106093 :                 p->key = NULL;
     720     5106093 :                 ZVAL_COPY_VALUE(&p->val, pData);
     721             : 
     722     5106093 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     723             : 
     724     5106093 :                 return &p->val;
     725             : 
     726             : convert_to_hash:
     727        1331 :                 zend_hash_packed_to_hash(ht);
     728     1978386 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     729     1323899 :                 p = zend_hash_index_find_bucket(ht, h);
     730     1323899 :                 if (p) {
     731       10407 :                         if (flag & HASH_ADD) {
     732         158 :                                 return NULL;
     733             :                         }
     734             :                         ZEND_ASSERT(&p->val != pData);
     735       10249 :                         HANDLE_BLOCK_INTERRUPTIONS();
     736       10249 :                         if (ht->pDestructor) {
     737       10204 :                                 ht->pDestructor(&p->val);
     738             :                         }
     739       10249 :                         ZVAL_COPY_VALUE(&p->val, pData);
     740       10249 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     741       10249 :                         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     742           1 :                                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     743             :                         }
     744       10249 :                         return &p->val;
     745             :                 }
     746             :         }
     747             : 
     748     1969310 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     749             : 
     750             : add_to_hash:
     751     2071605 :         HANDLE_BLOCK_INTERRUPTIONS();
     752     2071605 :         idx = ht->nNumUsed++;
     753     2071605 :         ht->nNumOfElements++;
     754     2071605 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     755      170809 :                 ht->nInternalPointer = idx;
     756             :         }
     757             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     758     2071605 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     759      661522 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     760             :         }
     761     2071605 :         p = ht->arData + idx;
     762     2071605 :         p->h = h;
     763     2071605 :         p->key = NULL;
     764     2071605 :         nIndex = h | ht->nTableMask;
     765     2071605 :         ZVAL_COPY_VALUE(&p->val, pData);
     766     2071605 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     767     2071605 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     768     2071605 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     769             : 
     770     2071605 :         return &p->val;
     771             : }
     772             : 
     773           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)
     774             : {
     775           0 :         return _zend_hash_index_add_or_update_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
     776             : }
     777             : 
     778         520 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     779             : {
     780         520 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     781             : }
     782             : 
     783     1092290 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     784             : {
     785     1092290 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     786             : }
     787             : 
     788     2329688 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     789             : {
     790     2329688 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     791             : }
     792             : 
     793     2584537 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     794             : {
     795     5169074 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     796             : }
     797             : 
     798     1184691 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     799             : {
     800     2369382 :         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);
     801             : }
     802             : 
     803     4603499 : static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
     804             : {
     805             : 
     806             :         IS_CONSISTENT(ht);
     807             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     808             : 
     809     4603499 :         if (ht->nNumUsed > ht->nNumOfElements + (ht->nNumOfElements >> 5)) { /* additional term is there to amortize the cost of compaction */
     810       24362 :                 HANDLE_BLOCK_INTERRUPTIONS();
     811       24362 :                 zend_hash_rehash(ht);
     812       24362 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     813     4579137 :         } else if (ht->nTableSize < HT_MAX_SIZE) {        /* Let's double the table size */
     814     4579137 :                 void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
     815     4579137 :                 uint32_t nSize = ht->nTableSize + ht->nTableSize;
     816     4579137 :                 Bucket *old_buckets = ht->arData;
     817             : 
     818     4579137 :                 HANDLE_BLOCK_INTERRUPTIONS();
     819     9158274 :                 new_data = pemalloc(HT_SIZE_EX(nSize, -nSize), ht->u.flags & HASH_FLAG_PERSISTENT);
     820     4579137 :                 ht->nTableSize = nSize;
     821     4579137 :                 ht->nTableMask = -ht->nTableSize;
     822     4579137 :                 HT_SET_DATA_ADDR(ht, new_data);
     823     4579137 :                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     824     4579137 :                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     825     4579137 :                 zend_hash_rehash(ht);
     826     4579137 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     827             :         } else {
     828           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket) + sizeof(uint32_t), sizeof(Bucket));
     829             :         }
     830     4603499 : }
     831             : 
     832     5614058 : ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
     833             : {
     834             :         Bucket *p;
     835             :         uint32_t nIndex, i;
     836             : 
     837             :         IS_CONSISTENT(ht);
     838             : 
     839     5614058 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     840           5 :                 if (ht->u.flags & HASH_FLAG_INITIALIZED) {
     841           2 :                         ht->nNumUsed = 0;
     842           2 :                         HT_HASH_RESET(ht);
     843             :                 }
     844           5 :                 return SUCCESS;
     845             :         }
     846             : 
     847     5614053 :         HT_HASH_RESET(ht);
     848     5614053 :         i = 0;
     849     5614053 :         p = ht->arData;
     850     5614053 :         if (ht->nNumUsed == ht->nNumOfElements) {
     851             :                 do {
     852   400770390 :                         nIndex = p->h | ht->nTableMask;
     853   400770390 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     854   400770390 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     855   400770390 :                         p++;
     856   400770390 :                 } while (++i < ht->nNumUsed);
     857             :         } else {
     858             :                 do {
     859      357616 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) {
     860       25875 :                                 uint32_t j = i;
     861       25875 :                                 Bucket *q = p;
     862             : 
     863       25875 :                                 if (EXPECTED(ht->u.v.nIteratorsCount == 0)) {
     864      259312 :                                         while (++i < ht->nNumUsed) {
     865      207568 :                                                 p++;
     866      207568 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     867      168079 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     868      168079 :                                                         q->h = p->h;
     869      168079 :                                                         nIndex = q->h | ht->nTableMask;
     870      168079 :                                                         q->key = p->key;
     871      168079 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     872      168079 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     873      168079 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     874       22775 :                                                                 ht->nInternalPointer = j;
     875             :                                                         }
     876      168079 :                                                         q++;
     877      168079 :                                                         j++;
     878             :                                                 }
     879             :                                         }
     880             :                                 } else {
     881           3 :                                         uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, 0);
     882             : 
     883          27 :                                         while (++i < ht->nNumUsed) {
     884          21 :                                                 p++;
     885          21 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     886          12 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     887          12 :                                                         q->h = p->h;
     888          12 :                                                         nIndex = q->h | ht->nTableMask;
     889          12 :                                                         q->key = p->key;
     890          12 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     891          12 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     892          12 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     893           3 :                                                                 ht->nInternalPointer = j;
     894             :                                                         }
     895          12 :                                                         if (UNEXPECTED(i == iter_pos)) {
     896             :                                                                 zend_hash_iterators_update(ht, i, j);
     897           5 :                                                                 iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1);
     898             :                                                         }
     899          12 :                                                         q++;
     900          12 :                                                         j++;
     901             :                                                 }
     902             :                                         }
     903             :                                 }
     904       25875 :                                 ht->nNumUsed = j;
     905       25875 :                                 break;
     906             :                         }
     907      152933 :                         nIndex = p->h | ht->nTableMask;
     908      152933 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     909      152933 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     910      152933 :                         p++;
     911      152933 :                 } while (++i < ht->nNumUsed);
     912             :         }
     913     5614053 :         return SUCCESS;
     914             : }
     915             : 
     916             : static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
     917             : {
     918    51637665 :         HANDLE_BLOCK_INTERRUPTIONS();
     919    51637665 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     920    51531960 :                 if (prev) {
     921     3070388 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     922             :                 } else {
     923    48461572 :                         HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val);
     924             :                 }
     925             :         }
     926    51637665 :         if (HT_IDX_TO_HASH(ht->nNumUsed - 1) == idx) {
     927             :                 do {
     928     3694747 :                         ht->nNumUsed--;
     929     7213291 :                 } while (ht->nNumUsed > 0 && (UNEXPECTED(Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF)));
     930             :         }
     931    51637665 :         ht->nNumOfElements--;
     932    51637665 :         if (HT_IDX_TO_HASH(ht->nInternalPointer) == idx || UNEXPECTED(ht->u.v.nIteratorsCount)) {
     933             :                 uint32_t new_idx;
     934             : 
     935     3298562 :                 new_idx = idx = HT_HASH_TO_IDX(idx);
     936             :                 while (1) {
     937    45951781 :                         new_idx++;
     938    45951781 :                         if (new_idx >= ht->nNumUsed) {
     939      133640 :                                 new_idx = HT_INVALID_IDX;
     940             :                                 break;
     941    91636282 :                         } else if (Z_TYPE(ht->arData[new_idx].val) != IS_UNDEF) {
     942             :                                 break;
     943             :                         }
     944             :                 }
     945     3298562 :                 if (ht->nInternalPointer == idx) {
     946     3298525 :                         ht->nInternalPointer = new_idx;
     947             :                 }
     948             :                 zend_hash_iterators_update(ht, idx, new_idx);
     949             :         }
     950    51637665 :         if (p->key) {
     951    51358768 :                 zend_string_release(p->key);
     952             :         }
     953    51637665 :         if (ht->pDestructor) {
     954             :                 zval tmp;
     955    50819209 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     956    50819209 :                 ZVAL_UNDEF(&p->val);
     957    50819209 :                 ht->pDestructor(&tmp);
     958             :         } else {
     959      818456 :                 ZVAL_UNDEF(&p->val);
     960             :         }
     961    51637665 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     962             : }
     963             : 
     964             : static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
     965             : {
     966     7150758 :         Bucket *prev = NULL;
     967             : 
     968     7150758 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     969     7146844 :                 uint32_t nIndex = p->h | ht->nTableMask;
     970     7146844 :                 uint32_t i = HT_HASH(ht, nIndex);
     971             : 
     972     7146844 :                 if (i != idx) {
     973      596489 :                         prev = HT_HASH_TO_BUCKET(ht, i);
     974      641191 :                         while (Z_NEXT(prev->val) != idx) {
     975       44702 :                                 i = Z_NEXT(prev->val);
     976       44702 :                                 prev = HT_HASH_TO_BUCKET(ht, i);
     977             :                         }
     978             :                 }
     979             :         }
     980             : 
     981             :         _zend_hash_del_el_ex(ht, idx, p, prev);
     982             : }
     983             : 
     984          24 : ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p)
     985             : {
     986             :         IS_CONSISTENT(ht);
     987             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     988          24 :         _zend_hash_del_el(ht, HT_IDX_TO_HASH(p - ht->arData), p);
     989          24 : }
     990             : 
     991    44282750 : ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
     992             : {
     993             :         zend_ulong h;
     994             :         uint32_t nIndex;
     995             :         uint32_t idx;
     996             :         Bucket *p;
     997    44282750 :         Bucket *prev = NULL;
     998             : 
     999             :         IS_CONSISTENT(ht);
    1000             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1001             : 
    1002    44282750 :         h = zend_string_hash_val(key);
    1003    44282750 :         nIndex = h | ht->nTableMask;
    1004             : 
    1005    44282750 :         idx = HT_HASH(ht, nIndex);
    1006    91164014 :         while (idx != HT_INVALID_IDX) {
    1007    46105210 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1008   222619062 :                 if ((p->key == key) ||
    1009    46077314 :                         (p->h == h &&
    1010    43478846 :                      p->key &&
    1011    43478846 :                      ZSTR_LEN(p->key) == ZSTR_LEN(key) &&
    1012    43478846 :                      memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
    1013             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1014    43506696 :                         return SUCCESS;
    1015             :                 }
    1016     2598514 :                 prev = p;
    1017     2598514 :                 idx = Z_NEXT(p->val);
    1018             :         }
    1019      776054 :         return FAILURE;
    1020             : }
    1021             : 
    1022         399 : ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key)
    1023             : {
    1024             :         zend_ulong h;
    1025             :         uint32_t nIndex;
    1026             :         uint32_t idx;
    1027             :         Bucket *p;
    1028         399 :         Bucket *prev = NULL;
    1029             : 
    1030             :         IS_CONSISTENT(ht);
    1031             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1032             : 
    1033         399 :         h = zend_string_hash_val(key);
    1034         399 :         nIndex = h | ht->nTableMask;
    1035             : 
    1036         399 :         idx = HT_HASH(ht, nIndex);
    1037         806 :         while (idx != HT_INVALID_IDX) {
    1038         218 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1039         914 :                 if ((p->key == key) ||
    1040         180 :                         (p->h == h &&
    1041         172 :                      p->key &&
    1042         172 :                      ZSTR_LEN(p->key) == ZSTR_LEN(key) &&
    1043         172 :                      memcmp(ZSTR_VAL(p->key), ZSTR_VAL(key), ZSTR_LEN(key)) == 0)) {
    1044         420 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
    1045          14 :                                 zval *data = Z_INDIRECT(p->val);
    1046             : 
    1047          14 :                                 if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1048           0 :                                         return FAILURE;
    1049             :                                 } else {
    1050          14 :                                         if (ht->pDestructor) {
    1051          14 :                                                 ht->pDestructor(data);
    1052             :                                         }
    1053          14 :                                         ZVAL_UNDEF(data);
    1054             :                                 }
    1055             :                         } else {
    1056             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
    1057             :                         }
    1058         210 :                         return SUCCESS;
    1059             :                 }
    1060           8 :                 prev = p;
    1061           8 :                 idx = Z_NEXT(p->val);
    1062             :         }
    1063         189 :         return FAILURE;
    1064             : }
    1065             : 
    1066           0 : ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
    1067             : {
    1068             :         zend_ulong h;
    1069             :         uint32_t nIndex;
    1070             :         uint32_t idx;
    1071             :         Bucket *p;
    1072           0 :         Bucket *prev = NULL;
    1073             : 
    1074             :         IS_CONSISTENT(ht);
    1075             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1076             : 
    1077           0 :         h = zend_inline_hash_func(str, len);
    1078           0 :         nIndex = h | ht->nTableMask;
    1079             : 
    1080           0 :         idx = HT_HASH(ht, nIndex);
    1081           0 :         while (idx != HT_INVALID_IDX) {
    1082           0 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1083           0 :                 if ((p->h == h)
    1084             :                          && p->key
    1085           0 :                          && (ZSTR_LEN(p->key) == len)
    1086           0 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
    1087           0 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
    1088           0 :                                 zval *data = Z_INDIRECT(p->val);
    1089             : 
    1090           0 :                                 if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1091           0 :                                         return FAILURE;
    1092             :                                 } else {
    1093           0 :                                         if (ht->pDestructor) {
    1094           0 :                                                 ht->pDestructor(data);
    1095             :                                         }
    1096           0 :                                         ZVAL_UNDEF(data);
    1097             :                                 }
    1098             :                         } else {
    1099             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
    1100             :                         }
    1101           0 :                         return SUCCESS;
    1102             :                 }
    1103           0 :                 prev = p;
    1104           0 :                 idx = Z_NEXT(p->val);
    1105             :         }
    1106           0 :         return FAILURE;
    1107             : }
    1108             : 
    1109      750926 : ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
    1110             : {
    1111             :         zend_ulong h;
    1112             :         uint32_t nIndex;
    1113             :         uint32_t idx;
    1114             :         Bucket *p;
    1115      750926 :         Bucket *prev = NULL;
    1116             : 
    1117             :         IS_CONSISTENT(ht);
    1118             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1119             : 
    1120      750926 :         h = zend_inline_hash_func(str, len);
    1121      750926 :         nIndex = h | ht->nTableMask;
    1122             : 
    1123      750926 :         idx = HT_HASH(ht, nIndex);
    1124     1544952 :         while (idx != HT_INVALID_IDX) {
    1125      769952 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1126     2950508 :                 if ((p->h == h)
    1127             :                          && p->key
    1128     1453704 :                          && (ZSTR_LEN(p->key) == len)
    1129      726852 :                          && !memcmp(ZSTR_VAL(p->key), str, len)) {
    1130             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1131      726852 :                         return SUCCESS;
    1132             :                 }
    1133       43100 :                 prev = p;
    1134       43100 :                 idx = Z_NEXT(p->val);
    1135             :         }
    1136       24074 :         return FAILURE;
    1137             : }
    1138             : 
    1139      264522 : ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
    1140             : {
    1141             :         uint32_t nIndex;
    1142             :         uint32_t idx;
    1143             :         Bucket *p;
    1144      264522 :         Bucket *prev = NULL;
    1145             : 
    1146             :         IS_CONSISTENT(ht);
    1147             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1148             : 
    1149      264522 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1150      107957 :                 if (h < ht->nNumUsed) {
    1151      101796 :                         p = ht->arData + h;
    1152      203592 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1153      101791 :                                 _zend_hash_del_el_ex(ht, HT_IDX_TO_HASH(h), p, NULL);
    1154      101791 :                                 return SUCCESS;
    1155             :                         }
    1156             :                 }
    1157        6166 :                 return FAILURE;
    1158             :         }
    1159      156565 :         nIndex = h | ht->nTableMask;
    1160             : 
    1161      156565 :         idx = HT_HASH(ht, nIndex);
    1162      314235 :         while (idx != HT_INVALID_IDX) {
    1163      152477 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1164      152477 :                 if ((p->h == h) && (p->key == NULL)) {
    1165             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1166      151372 :                         return SUCCESS;
    1167             :                 }
    1168        1105 :                 prev = p;
    1169        1105 :                 idx = Z_NEXT(p->val);
    1170             :         }
    1171        5193 :         return FAILURE;
    1172             : }
    1173             : 
    1174    13843928 : ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
    1175             : {
    1176             :         Bucket *p, *end;
    1177             : 
    1178             :         IS_CONSISTENT(ht);
    1179             :         HT_ASSERT(GC_REFCOUNT(ht) <= 1);
    1180             : 
    1181    13843928 :         if (ht->nNumUsed) {
    1182     7356341 :                 p = ht->arData;
    1183     7356341 :                 end = p + ht->nNumUsed;
    1184     7356341 :                 if (ht->pDestructor) {
    1185             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
    1186             : 
    1187     7049553 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1188     4319386 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1189             :                                         do {
    1190   156521312 :                                                 ht->pDestructor(&p->val);
    1191   156521311 :                                         } while (++p != end);
    1192             :                                 } else {
    1193             :                                         do {
    1194    89394406 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1195     1343036 :                                                         ht->pDestructor(&p->val);
    1196             :                                                 }
    1197    44697203 :                                         } while (++p != end);
    1198             :                                 }
    1199     2730167 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1200             :                                 do {
    1201    91055095 :                                         ht->pDestructor(&p->val);
    1202    91055095 :                                         if (EXPECTED(p->key)) {
    1203    91048735 :                                                 zend_string_release(p->key);
    1204             :                                         }
    1205    91055095 :                                 } while (++p != end);
    1206             :                         } else {
    1207             :                                 do {
    1208     9501428 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1209      277457 :                                                 ht->pDestructor(&p->val);
    1210      277457 :                                                 if (EXPECTED(p->key)) {
    1211      277457 :                                                         zend_string_release(p->key);
    1212             :                                                 }
    1213             :                                         }
    1214     4750714 :                                 } while (++p != end);
    1215             :                         }
    1216             : 
    1217             :                         SET_INCONSISTENT(HT_DESTROYED);
    1218             :                 } else {
    1219      306788 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1220             :                                 do {
    1221    18200642 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1222     9015010 :                                                 if (EXPECTED(p->key)) {
    1223     9014380 :                                                         zend_string_release(p->key);
    1224             :                                                 }
    1225             :                                         }
    1226     9100321 :                                 } while (++p != end);
    1227             :                         }
    1228             :                 }
    1229             :                 zend_hash_iterators_remove(ht);
    1230     6487587 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1231     6417858 :                 return;
    1232             :         }
    1233     7426069 :         pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1234             : }
    1235             : 
    1236     5379113 : ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
    1237             : {
    1238             :         Bucket *p, *end;
    1239             : 
    1240             :         IS_CONSISTENT(ht);
    1241             :         HT_ASSERT(GC_REFCOUNT(ht) <= 1);
    1242             : 
    1243             :         /* break possible cycles */
    1244     5379113 :         GC_REMOVE_FROM_BUFFER(ht);
    1245     5379113 :         GC_TYPE_INFO(ht) = IS_NULL | (GC_WHITE << 16);
    1246             : 
    1247     5379113 :         if (ht->nNumUsed) {
    1248             :                 /* In some rare cases destructors of regular arrays may be changed */
    1249     3131975 :                 if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
    1250          73 :                         zend_hash_destroy(ht);
    1251          73 :                         goto free_ht;
    1252             :                 }
    1253             : 
    1254     3131902 :                 p = ht->arData;
    1255     3131902 :                 end = p + ht->nNumUsed;
    1256             :                 SET_INCONSISTENT(HT_IS_DESTROYING);
    1257             : 
    1258     3131902 :                 if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1259             :                         do {
    1260     7900553 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1261     7900551 :                         } while (++p != end);
    1262      261709 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1263             :                         do {
    1264     4512696 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1265     4512696 :                                 if (EXPECTED(p->key)) {
    1266     4451031 :                                         zend_string_release(p->key);
    1267             :                                 }
    1268     4512696 :                         } while (++p != end);
    1269             :                 } else {
    1270             :                         do {
    1271        4504 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1272        1954 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1273        1954 :                                         if (EXPECTED(p->key)) {
    1274        1895 :                                                 zend_string_release(p->key);
    1275             :                                         }
    1276             :                                 }
    1277        2252 :                         } while (++p != end);
    1278             :                 }
    1279             :                 zend_hash_iterators_remove(ht);
    1280             :                 SET_INCONSISTENT(HT_DESTROYED);
    1281     2247138 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1282     2244844 :                 goto free_ht;
    1283             :         }
    1284     3134194 :         efree(HT_GET_DATA_ADDR(ht));
    1285             : free_ht:
    1286     5379111 :         FREE_HASHTABLE(ht);
    1287     5379111 : }
    1288             : 
    1289       51605 : ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
    1290             : {
    1291             :         Bucket *p, *end;
    1292             : 
    1293             :         IS_CONSISTENT(ht);
    1294             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1295             : 
    1296       51605 :         if (ht->nNumUsed) {
    1297        8632 :                 p = ht->arData;
    1298        8632 :                 end = p + ht->nNumUsed;
    1299        8632 :                 if (ht->pDestructor) {
    1300        3617 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1301         991 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1302             :                                         do {
    1303      518320 :                                                 ht->pDestructor(&p->val);
    1304      518320 :                                         } while (++p != end);
    1305             :                                 } else {
    1306             :                                         do {
    1307          78 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1308           9 :                                                         ht->pDestructor(&p->val);
    1309             :                                                 }
    1310          39 :                                         } while (++p != end);
    1311             :                                 }
    1312        2626 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1313             :                                 do {
    1314     1256895 :                                         ht->pDestructor(&p->val);
    1315     1256895 :                                         if (EXPECTED(p->key)) {
    1316     1256895 :                                                 zend_string_release(p->key);
    1317             :                                         }
    1318     1256895 :                                 } while (++p != end);
    1319             :                         } else {
    1320             :                                 do {
    1321           0 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1322           0 :                                                 ht->pDestructor(&p->val);
    1323           0 :                                                 if (EXPECTED(p->key)) {
    1324           0 :                                                         zend_string_release(p->key);
    1325             :                                                 }
    1326             :                                         }
    1327           0 :                                 } while (++p != end);
    1328             :                         }
    1329             :                 } else {
    1330        5015 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1331        4588 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1332             :                                         do {
    1333       27553 :                                                 if (EXPECTED(p->key)) {
    1334       27553 :                                                         zend_string_release(p->key);
    1335             :                                                 }
    1336       27553 :                                         } while (++p != end);
    1337             :                                 } else {
    1338             :                                         do {
    1339           0 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1340           0 :                                                         if (EXPECTED(p->key)) {
    1341           0 :                                                                 zend_string_release(p->key);
    1342             :                                                         }
    1343             :                                                 }
    1344           0 :                                         } while (++p != end);
    1345             :                                 }
    1346             :                         }
    1347             :                 }
    1348        8632 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1349        8617 :                         HT_HASH_RESET(ht);
    1350             :                 }
    1351             :         }
    1352       51605 :         ht->nNumUsed = 0;
    1353       51605 :         ht->nNumOfElements = 0;
    1354       51605 :         ht->nNextFreeElement = 0;
    1355       51605 :         ht->nInternalPointer = HT_INVALID_IDX;
    1356       51605 : }
    1357             : 
    1358       87846 : ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
    1359             : {
    1360             :         Bucket *p, *end;
    1361             : 
    1362             :         IS_CONSISTENT(ht);
    1363             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1364             : 
    1365       87846 :         if (ht->nNumUsed) {
    1366       87838 :                 p = ht->arData;
    1367       87838 :                 end = p + ht->nNumUsed;
    1368       87838 :                 if (ht->u.flags & HASH_FLAG_STATIC_KEYS) {
    1369             :                         do {
    1370      177058 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1371      177058 :                         } while (++p != end);
    1372          80 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1373             :                         do {
    1374         570 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1375         570 :                                 zend_string_release(p->key);
    1376         570 :                         } while (++p != end);
    1377             :                 } else {
    1378             :                         do {
    1379           0 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1380           0 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1381           0 :                                         zend_string_release(p->key);
    1382             :                                 }
    1383           0 :                         } while (++p != end);
    1384             :                 }
    1385       87838 :                 HT_HASH_RESET(ht);
    1386             :         }
    1387       87846 :         ht->nNumUsed = 0;
    1388       87846 :         ht->nNumOfElements = 0;
    1389       87846 :         ht->nNextFreeElement = 0;
    1390       87846 :         ht->nInternalPointer = HT_INVALID_IDX;
    1391       87846 : }
    1392             : 
    1393           0 : ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht)
    1394             : {
    1395             :         uint32_t idx;
    1396             :         Bucket *p;
    1397             : 
    1398             :         IS_CONSISTENT(ht);
    1399             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1400             : 
    1401           0 :         p = ht->arData;
    1402           0 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1403           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1404             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1405             :         }
    1406           0 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1407           0 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1408             :         }
    1409             : 
    1410             :         SET_INCONSISTENT(HT_DESTROYED);
    1411           0 : }
    1412             : 
    1413       85348 : ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht)
    1414             : {
    1415             :         uint32_t idx;
    1416             :         Bucket *p;
    1417             : 
    1418             :         IS_CONSISTENT(ht);
    1419             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1420             : 
    1421       85348 :         idx = ht->nNumUsed;
    1422       85348 :         p = ht->arData + ht->nNumUsed;
    1423     1881908 :         while (idx > 0) {
    1424     1711212 :                 idx--;
    1425     1711212 :                 p--;
    1426     3422424 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1427             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1428             :         }
    1429             : 
    1430       85348 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1431       64845 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1432             :         }
    1433             : 
    1434             :         SET_INCONSISTENT(HT_DESTROYED);
    1435       85348 : }
    1436             : 
    1437             : /* This is used to recurse elements and selectively delete certain entries
    1438             :  * from a hashtable. apply_func() receives the data and decides if the entry
    1439             :  * should be deleted or recursion should be stopped. The following three
    1440             :  * return codes are possible:
    1441             :  * ZEND_HASH_APPLY_KEEP   - continue
    1442             :  * ZEND_HASH_APPLY_STOP   - stop iteration
    1443             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
    1444             :  */
    1445             : 
    1446       94731 : ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
    1447             : {
    1448             :         uint32_t idx;
    1449             :         Bucket *p;
    1450             :         int result;
    1451             : 
    1452             :         IS_CONSISTENT(ht);
    1453             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1454             : 
    1455       94731 :         HASH_PROTECT_RECURSION(ht);
    1456       94731 :         p = ht->arData;
    1457     1678191 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1458     3166930 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1459     1583444 :                 result = apply_func(&p->val);
    1460             : 
    1461     1583439 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1462             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1463             :                 }
    1464     1583439 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1465           0 :                         break;
    1466             :                 }
    1467             :         }
    1468       94726 :         HASH_UNPROTECT_RECURSION(ht);
    1469       94726 : }
    1470             : 
    1471             : 
    1472      586562 : ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
    1473             : {
    1474             :     uint32_t idx;
    1475             :         Bucket *p;
    1476             :         int result;
    1477             : 
    1478             :         IS_CONSISTENT(ht);
    1479             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1480             : 
    1481      586562 :         HASH_PROTECT_RECURSION(ht);
    1482      586562 :         p = ht->arData;
    1483   124989654 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1484   248813866 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1485    91005299 :                 result = apply_func(&p->val, argument);
    1486             : 
    1487    91005299 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1488             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1489             :                 }
    1490    91005299 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1491        3841 :                         break;
    1492             :                 }
    1493             :         }
    1494      586562 :         HASH_UNPROTECT_RECURSION(ht);
    1495      586562 : }
    1496             : 
    1497             : 
    1498         303 : ZEND_API void ZEND_FASTCALL zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args, ...)
    1499             : {
    1500             :         uint32_t idx;
    1501             :         Bucket *p;
    1502             :         va_list args;
    1503             :         zend_hash_key hash_key;
    1504             :         int result;
    1505             : 
    1506             :         IS_CONSISTENT(ht);
    1507             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1508             : 
    1509         303 :         HASH_PROTECT_RECURSION(ht);
    1510             : 
    1511         303 :         p = ht->arData;
    1512      161260 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1513      321914 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1514      160891 :                 va_start(args, num_args);
    1515      160891 :                 hash_key.h = p->h;
    1516      160891 :                 hash_key.key = p->key;
    1517             : 
    1518      160891 :                 result = apply_func(&p->val, num_args, args, &hash_key);
    1519             : 
    1520      160891 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1521             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1522             :                 }
    1523      160891 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1524           0 :                         va_end(args);
    1525           0 :                         break;
    1526             :                 }
    1527      160891 :                 va_end(args);
    1528             :         }
    1529             : 
    1530         303 :         HASH_UNPROTECT_RECURSION(ht);
    1531         303 : }
    1532             : 
    1533             : 
    1534      111466 : ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func)
    1535             : {
    1536             :         uint32_t idx;
    1537             :         Bucket *p;
    1538             :         int result;
    1539             : 
    1540             :         IS_CONSISTENT(ht);
    1541             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1542             : 
    1543      111466 :         HASH_PROTECT_RECURSION(ht);
    1544      111466 :         idx = ht->nNumUsed;
    1545      111466 :         p = ht->arData + idx;
    1546      734902 :         while (idx > 0) {
    1547      575828 :                 idx--;
    1548      575828 :                 p--;
    1549     1151656 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1550             : 
    1551      523085 :                 result = apply_func(&p->val);
    1552             : 
    1553      523085 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1554             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1555             :                 }
    1556      523085 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1557       63858 :                         break;
    1558             :                 }
    1559             :         }
    1560      111466 :         HASH_UNPROTECT_RECURSION(ht);
    1561      111466 : }
    1562             : 
    1563             : 
    1564         469 : ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
    1565             : {
    1566             :     uint32_t idx;
    1567             :         Bucket *p;
    1568             :         zval *new_entry, *data;
    1569             :         zend_bool setTargetPointer;
    1570             : 
    1571             :         IS_CONSISTENT(source);
    1572             :         IS_CONSISTENT(target);
    1573             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1574             : 
    1575         469 :         setTargetPointer = (target->nInternalPointer == HT_INVALID_IDX);
    1576       11241 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1577       10772 :                 p = source->arData + idx;
    1578       21544 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1579             : 
    1580       10772 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1581         311 :                         target->nInternalPointer = HT_INVALID_IDX;
    1582             :                 }
    1583             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1584       10772 :                 data = &p->val;
    1585       10772 :                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1586         100 :                         data = Z_INDIRECT_P(data);
    1587         100 :                         if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1588           4 :                                 continue;
    1589             :                         }
    1590             :                 }
    1591       10768 :                 if (p->key) {
    1592       10679 :                         new_entry = zend_hash_update(target, p->key, data);
    1593             :                 } else {
    1594          89 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1595             :                 }
    1596       10768 :                 if (pCopyConstructor) {
    1597         408 :                         pCopyConstructor(new_entry);
    1598             :                 }
    1599             :         }
    1600         469 :         if (target->nInternalPointer == HT_INVALID_IDX && target->nNumOfElements > 0) {
    1601           0 :                 idx = 0;
    1602           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1603           0 :                         idx++;
    1604             :                 }
    1605           0 :                 target->nInternalPointer = idx;
    1606             :         }
    1607         469 : }
    1608             : 
    1609             : 
    1610             : 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)
    1611             : {
    1612     3559929 :         zval *data = &p->val;
    1613             : 
    1614     3559929 :         if (with_holes) {
    1615     2543791 :                 if (!packed && Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1616           0 :                         data = Z_INDIRECT_P(data);
    1617             :                 }
    1618     2543791 :                 if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1619      847099 :                         return 0;
    1620             :                 }
    1621     1016138 :         } else if (!packed) {
    1622             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1623      708611 :                 if (Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1624       17832 :                         data = Z_INDIRECT_P(data);
    1625       17832 :                         if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1626        2856 :                                 return 0;
    1627             :                         }
    1628             :                 }
    1629             :         }
    1630             : 
    1631             :         do {
    1632     2709974 :                 if (Z_OPT_REFCOUNTED_P(data)) {
    1633     2525988 :                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1 &&
    1634          61 :                             (Z_TYPE_P(Z_REFVAL_P(data)) != IS_ARRAY ||
    1635          18 :                               Z_ARRVAL_P(Z_REFVAL_P(data)) != source)) {
    1636          58 :                                 data = Z_REFVAL_P(data);
    1637          58 :                                 if (!Z_OPT_REFCOUNTED_P(data)) {
    1638             :                                         break;
    1639             :                                 }
    1640             :                         }
    1641             :                         Z_ADDREF_P(data);
    1642             :                 }
    1643             :         } while (0);
    1644     2709974 :         ZVAL_COPY_VALUE(&q->val, data);
    1645             : 
    1646     2709974 :         q->h = p->h;
    1647     2709974 :         if (packed) {
    1648     2004199 :                 q->key = NULL;
    1649             :         } else {
    1650             :                 uint32_t nIndex;
    1651             : 
    1652      705775 :                 q->key = p->key;
    1653      705775 :                 if (!static_keys && q->key) {
    1654      699883 :                         zend_string_addref(q->key);
    1655             :                 }
    1656             : 
    1657      705775 :                 nIndex = q->h | target->nTableMask;
    1658      705775 :                 Z_NEXT(q->val) = HT_HASH(target, nIndex);
    1659      705775 :                 HT_HASH(target, nIndex) = HT_IDX_TO_HASH(idx);
    1660             :         }
    1661     2709974 :         return 1;
    1662             : }
    1663             : 
    1664             : static zend_always_inline void zend_array_dup_packed_elements(HashTable *source, HashTable *target, int with_holes)
    1665             : {
    1666     1047629 :         Bucket *p = source->arData;
    1667     1047629 :         Bucket *q = target->arData;
    1668     1047629 :         Bucket *end = p + source->nNumUsed;
    1669             : 
    1670             :         do {
    1671     2851294 :                 if (!zend_array_dup_element(source, target, 0, p, q, 1, 1, with_holes)) {
    1672      847095 :                         if (with_holes) {
    1673      847095 :                                 ZVAL_UNDEF(&q->val);
    1674             :                         }
    1675             :                 }
    1676     2851294 :                 p++; q++;
    1677     2851294 :         } while (p != end);
    1678             : }
    1679             : 
    1680             : static zend_always_inline uint32_t zend_array_dup_elements(HashTable *source, HashTable *target, int static_keys, int with_holes)
    1681             : {
    1682       57121 :     uint32_t idx = 0;
    1683       57121 :         Bucket *p = source->arData;
    1684       57121 :         Bucket *q = target->arData;
    1685       57121 :         Bucket *end = p + source->nNumUsed;
    1686             : 
    1687             :         do {
    1688      697774 :                 if (!zend_array_dup_element(source, target, idx, p, q, 0, static_keys, with_holes)) {
    1689        1894 :                         uint32_t target_idx = idx;
    1690             : 
    1691        1894 :                         idx++; p++;
    1692       12755 :                         while (p != end) {
    1693       10861 :                                 if (zend_array_dup_element(source, target, target_idx, p, q, 0, static_keys, with_holes)) {
    1694        9895 :                                         if (source->nInternalPointer == idx) {
    1695           0 :                                                 target->nInternalPointer = target_idx;
    1696             :                                         }
    1697        9895 :                                         target_idx++; q++;
    1698             :                                 }
    1699       10861 :                                 idx++; p++;
    1700             :                         }
    1701        1894 :                         return target_idx;
    1702             :                 }
    1703      695880 :                 idx++; p++; q++;
    1704      695880 :         } while (p != end);
    1705       55227 :         return idx;
    1706             : }
    1707             : 
    1708     1268145 : ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
    1709             : {
    1710             :     uint32_t idx;
    1711             :         HashTable *target;
    1712             : 
    1713             :         IS_CONSISTENT(source);
    1714             : 
    1715     1268145 :         ALLOC_HASHTABLE(target);
    1716     1268145 :         GC_REFCOUNT(target) = 1;
    1717     1268145 :         GC_TYPE_INFO(target) = IS_ARRAY;
    1718             : 
    1719     1268145 :         target->nTableSize = source->nTableSize;
    1720     1268145 :         target->pDestructor = source->pDestructor;
    1721             : 
    1722     1268145 :         if (source->nNumUsed == 0) {
    1723      163381 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED|HASH_FLAG_PERSISTENT)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
    1724      163381 :                 target->nTableMask = HT_MIN_MASK;
    1725      163381 :                 target->nNumUsed = 0;
    1726      163381 :                 target->nNumOfElements = 0;
    1727      163381 :                 target->nNextFreeElement = 0;
    1728      163381 :                 target->nInternalPointer = HT_INVALID_IDX;
    1729      163381 :                 HT_SET_DATA_ADDR(target, &uninitialized_bucket);
    1730     1104764 :         } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) {
    1731          14 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1732          14 :                 target->nTableMask = source->nTableMask;
    1733          14 :                 target->nNumUsed = source->nNumUsed;
    1734          14 :                 target->nNumOfElements = source->nNumOfElements;
    1735          14 :                 target->nNextFreeElement = source->nNextFreeElement;
    1736          14 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1737          14 :                 target->nInternalPointer = source->nInternalPointer;
    1738          14 :                 memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source));
    1739          28 :                 if (target->nNumOfElements > 0 &&
    1740          14 :                     target->nInternalPointer == HT_INVALID_IDX) {
    1741           0 :                         idx = 0;
    1742           0 :                         while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1743           0 :                                 idx++;
    1744             :                         }
    1745           0 :                         target->nInternalPointer = idx;
    1746             :                 }
    1747     1104750 :         } else if (source->u.flags & HASH_FLAG_PACKED) {
    1748     1047629 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1749     1047629 :                 target->nTableMask = source->nTableMask;
    1750     1047629 :                 target->nNumUsed = source->nNumUsed;
    1751     1047629 :                 target->nNumOfElements = source->nNumOfElements;
    1752     1047629 :                 target->nNextFreeElement = source->nNextFreeElement;
    1753     1047629 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1754     1047629 :                 target->nInternalPointer = source->nInternalPointer;
    1755     1047629 :                 HT_HASH_RESET_PACKED(target);
    1756             : 
    1757     1047629 :                 if (target->nNumUsed == target->nNumOfElements) {
    1758             :                         zend_array_dup_packed_elements(source, target, 0);
    1759             :                 } else {
    1760             :                         zend_array_dup_packed_elements(source, target, 1);
    1761             :                 }
    1762     2095258 :                 if (target->nNumOfElements > 0 &&
    1763     1047629 :                     target->nInternalPointer == HT_INVALID_IDX) {
    1764           8 :                         idx = 0;
    1765          26 :                         while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1766           1 :                                 idx++;
    1767             :                         }
    1768           8 :                         target->nInternalPointer = idx;
    1769             :                 }
    1770             :         } else {
    1771       57121 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1772       57121 :                 target->nTableMask = source->nTableMask;
    1773       57121 :                 target->nNextFreeElement = source->nNextFreeElement;
    1774       57121 :                 target->nInternalPointer = HT_INVALID_IDX;
    1775       57121 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1776       57121 :                 HT_HASH_RESET(target);
    1777             : 
    1778       57121 :                 if (target->u.flags & HASH_FLAG_STATIC_KEYS) {
    1779         909 :                         if (source->nNumUsed == source->nNumOfElements) {
    1780         909 :                                 idx = zend_array_dup_elements(source, target, 1, 0);
    1781             :                         } else {
    1782           0 :                                 idx = zend_array_dup_elements(source, target, 1, 1);
    1783             :                         }
    1784             :                 } else {
    1785       56212 :                         if (source->nNumUsed == source->nNumOfElements) {
    1786       56209 :                                 idx = zend_array_dup_elements(source, target, 0, 0);
    1787             :                         } else {
    1788           3 :                                 idx = zend_array_dup_elements(source, target, 0, 1);
    1789             :                         }
    1790             :                 }
    1791       57121 :                 target->nNumUsed = idx;
    1792       57121 :                 target->nNumOfElements = idx;
    1793       57121 :                 if (idx > 0 && target->nInternalPointer == HT_INVALID_IDX) {
    1794       57111 :                         target->nInternalPointer = 0;
    1795             :                 }
    1796             :         }
    1797     1268145 :         return target;
    1798             : }
    1799             : 
    1800             : 
    1801      191708 : ZEND_API void ZEND_FASTCALL _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
    1802             : {
    1803             :     uint32_t idx;
    1804             :         Bucket *p;
    1805             :         zval *t;
    1806      191708 :         uint32_t mode = (overwrite?HASH_UPDATE:HASH_ADD);
    1807             : 
    1808             :         IS_CONSISTENT(source);
    1809             :         IS_CONSISTENT(target);
    1810             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1811             : 
    1812     3301740 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1813     3110032 :                 p = source->arData + idx;
    1814     6220064 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1815     3110032 :                 if (p->key) {
    1816     3109981 :                         t = _zend_hash_add_or_update(target, p->key, &p->val, mode ZEND_FILE_LINE_RELAY_CC);
    1817     3109981 :                         if (t && pCopyConstructor) {
    1818     3109399 :                                 pCopyConstructor(t);
    1819             :                         }
    1820             :                 } else {
    1821          51 :                         if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h))) {
    1822          26 :                                 t = zend_hash_index_update(target, p->h, &p->val);
    1823          26 :                                 if (t && pCopyConstructor) {
    1824          26 :                                         pCopyConstructor(t);
    1825             :                                 }
    1826             :                         }
    1827             :                 }
    1828             :         }
    1829      191708 :         if (target->nNumOfElements > 0) {
    1830      191706 :                 idx = 0;
    1831      575118 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1832           0 :                         idx++;
    1833             :                 }
    1834      191706 :                 target->nInternalPointer = idx;
    1835             :         }
    1836      191708 : }
    1837             : 
    1838             : 
    1839           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)
    1840             : {
    1841             :         zend_hash_key hash_key;
    1842             : 
    1843           0 :         hash_key.h = p->h;
    1844           0 :         hash_key.key = p->key;
    1845           0 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1846             : }
    1847             : 
    1848             : 
    1849           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)
    1850             : {
    1851             :         uint32_t idx;
    1852             :         Bucket *p;
    1853             :         zval *t;
    1854             : 
    1855             :         IS_CONSISTENT(source);
    1856             :         IS_CONSISTENT(target);
    1857             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1858             : 
    1859           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1860           0 :                 p = source->arData + idx;
    1861           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1862           0 :                 if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
    1863           0 :                         t = zend_hash_update(target, p->key, &p->val);
    1864           0 :                         if (t && pCopyConstructor) {
    1865           0 :                                 pCopyConstructor(t);
    1866             :                         }
    1867             :                 }
    1868             :         }
    1869           0 :         if (target->nNumOfElements > 0) {
    1870           0 :                 idx = 0;
    1871           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1872           0 :                         idx++;
    1873             :                 }
    1874           0 :                 target->nInternalPointer = idx;
    1875             :         }
    1876           0 : }
    1877             : 
    1878             : 
    1879             : /* Returns the hash table data if found and NULL if not. */
    1880    55284736 : ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
    1881             : {
    1882             :         Bucket *p;
    1883             : 
    1884             :         IS_CONSISTENT(ht);
    1885             : 
    1886    55284736 :         p = zend_hash_find_bucket(ht, key);
    1887    55284736 :         return p ? &p->val : NULL;
    1888             : }
    1889             : 
    1890     1998084 : ZEND_API zval* ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
    1891             : {
    1892             :         zend_ulong h;
    1893             :         Bucket *p;
    1894             : 
    1895             :         IS_CONSISTENT(ht);
    1896             : 
    1897     1998084 :         h = zend_inline_hash_func(str, len);
    1898     1998084 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1899     1998084 :         return p ? &p->val : NULL;
    1900             : }
    1901             : 
    1902     2734718 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_exists(const HashTable *ht, zend_string *key)
    1903             : {
    1904             :         Bucket *p;
    1905             : 
    1906             :         IS_CONSISTENT(ht);
    1907             : 
    1908     2734718 :         p = zend_hash_find_bucket(ht, key);
    1909     2734718 :         return p ? 1 : 0;
    1910             : }
    1911             : 
    1912      909157 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
    1913             : {
    1914             :         zend_ulong h;
    1915             :         Bucket *p;
    1916             : 
    1917             :         IS_CONSISTENT(ht);
    1918             : 
    1919      909157 :         h = zend_inline_hash_func(str, len);
    1920      909157 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1921      909157 :         return p ? 1 : 0;
    1922             : }
    1923             : 
    1924     5809814 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
    1925             : {
    1926             :         Bucket *p;
    1927             : 
    1928             :         IS_CONSISTENT(ht);
    1929             : 
    1930     5809814 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1931     4625757 :                 if (h < ht->nNumUsed) {
    1932     4374220 :                         p = ht->arData + h;
    1933     8748440 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1934     4373811 :                                 return &p->val;
    1935             :                         }
    1936             :                 }
    1937      251946 :                 return NULL;
    1938             :         }
    1939             : 
    1940     1184057 :         p = zend_hash_index_find_bucket(ht, h);
    1941     1184057 :         return p ? &p->val : NULL;
    1942             : }
    1943             : 
    1944             : 
    1945     1575944 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h)
    1946             : {
    1947             :         Bucket *p;
    1948             : 
    1949             :         IS_CONSISTENT(ht);
    1950             : 
    1951     1575944 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1952          96 :                 if (h < ht->nNumUsed) {
    1953         132 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    1954          65 :                                 return 1;
    1955             :                         }
    1956             :                 }
    1957          31 :                 return 0;
    1958             :         }
    1959             : 
    1960     1575848 :         p = zend_hash_index_find_bucket(ht, h);
    1961     1575848 :         return p ? 1 : 0;
    1962             : }
    1963             : 
    1964             : 
    1965       19198 : ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1966             : {
    1967             :     uint32_t idx;
    1968             : 
    1969             :         IS_CONSISTENT(ht);
    1970             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    1971             : 
    1972       19642 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1973       38980 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1974       19046 :                         *pos = idx;
    1975       19046 :                         return;
    1976             :                 }
    1977             :         }
    1978         152 :         *pos = HT_INVALID_IDX;
    1979             : }
    1980             : 
    1981             : 
    1982             : /* This function will be extremely optimized by remembering
    1983             :  * the end of the list
    1984             :  */
    1985          47 : ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1986             : {
    1987             :         uint32_t idx;
    1988             : 
    1989             :         IS_CONSISTENT(ht);
    1990             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    1991             : 
    1992          47 :         idx = ht->nNumUsed;
    1993          94 :         while (idx > 0) {
    1994          45 :                 idx--;
    1995          90 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1996          45 :                         *pos = idx;
    1997          45 :                         return;
    1998             :                 }
    1999             :         }
    2000           2 :         *pos = HT_INVALID_IDX;
    2001             : }
    2002             : 
    2003             : 
    2004       68150 : ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    2005             : {
    2006       68150 :         uint32_t idx = *pos;
    2007             : 
    2008             :         IS_CONSISTENT(ht);
    2009             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    2010             : 
    2011       68150 :         if (idx != HT_INVALID_IDX) {
    2012             :                 while (1) {
    2013       68186 :                         idx++;
    2014       68186 :                         if (idx >= ht->nNumUsed) {
    2015       16232 :                                 *pos = HT_INVALID_IDX;
    2016       16232 :                                 return SUCCESS;
    2017             :                         }
    2018      103908 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2019       51883 :                                 *pos = idx;
    2020       51883 :                                 return SUCCESS;
    2021             :                         }
    2022          71 :                 }
    2023             :         } else {
    2024          35 :                 return FAILURE;
    2025             :         }
    2026             : }
    2027             : 
    2028          21 : ZEND_API int ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    2029             : {
    2030          21 :         uint32_t idx = *pos;
    2031             : 
    2032             :         IS_CONSISTENT(ht);
    2033             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    2034             : 
    2035          21 :         if (idx != HT_INVALID_IDX) {
    2036          38 :                 while (idx > 0) {
    2037          14 :                         idx--;
    2038          28 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2039          14 :                                 *pos = idx;
    2040          14 :                                 return SUCCESS;
    2041             :                         }
    2042             :                 }
    2043           5 :                 *pos = HT_INVALID_IDX;
    2044           5 :                 return SUCCESS;
    2045             :         } else {
    2046           2 :                 return FAILURE;
    2047             :         }
    2048             : }
    2049             : 
    2050             : 
    2051             : /* This function should be made binary safe  */
    2052       12821 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, HashPosition *pos)
    2053             : {
    2054       12821 :         uint32_t idx = *pos;
    2055             :         Bucket *p;
    2056             : 
    2057             :         IS_CONSISTENT(ht);
    2058       12821 :         if (idx != HT_INVALID_IDX) {
    2059       12388 :                 p = ht->arData + idx;
    2060       12388 :                 if (p->key) {
    2061       11036 :                         *str_index = p->key;
    2062       11036 :                         return HASH_KEY_IS_STRING;
    2063             :                 } else {
    2064        1352 :                         *num_index = p->h;
    2065        1352 :                         return HASH_KEY_IS_LONG;
    2066             :                 }
    2067             :         }
    2068         433 :         return HASH_KEY_NON_EXISTENT;
    2069             : }
    2070             : 
    2071        3372 : ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    2072             : {
    2073        3372 :         uint32_t idx = *pos;
    2074             :         Bucket *p;
    2075             : 
    2076             :         IS_CONSISTENT(ht);
    2077        3372 :         if (idx == HT_INVALID_IDX) {
    2078          52 :                 ZVAL_NULL(key);
    2079             :         } else {
    2080        3320 :                 p = ht->arData + idx;
    2081        3320 :                 if (p->key) {
    2082         670 :                         ZVAL_STR_COPY(key, p->key);
    2083             :                 } else {
    2084        2650 :                         ZVAL_LONG(key, p->h);
    2085             :                 }
    2086             :         }
    2087        3372 : }
    2088             : 
    2089       78739 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    2090             : {
    2091       78739 :     uint32_t idx = *pos;
    2092             :         Bucket *p;
    2093             : 
    2094             :         IS_CONSISTENT(ht);
    2095       78739 :         if (idx != HT_INVALID_IDX) {
    2096       63498 :                 p = ht->arData + idx;
    2097       63498 :                 if (p->key) {
    2098       60822 :                         return HASH_KEY_IS_STRING;
    2099             :                 } else {
    2100        2676 :                         return HASH_KEY_IS_LONG;
    2101             :                 }
    2102             :         }
    2103       15241 :         return HASH_KEY_NON_EXISTENT;
    2104             : }
    2105             : 
    2106             : 
    2107       65720 : ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    2108             : {
    2109       65720 :         uint32_t idx = *pos;
    2110             :         Bucket *p;
    2111             : 
    2112             :         IS_CONSISTENT(ht);
    2113       65720 :         if (idx != HT_INVALID_IDX) {
    2114       64873 :                 p = ht->arData + idx;
    2115       64873 :                 return &p->val;
    2116             :         } else {
    2117         847 :                 return NULL;
    2118             :         }
    2119             : }
    2120             : 
    2121       86846 : ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q)
    2122             : {
    2123             :         zval val;
    2124             :         zend_ulong h;
    2125             :         zend_string *key;
    2126             : 
    2127       86846 :         ZVAL_COPY_VALUE(&val, &p->val);
    2128       86846 :         h = p->h;
    2129       86846 :         key = p->key;
    2130             : 
    2131       86846 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2132       86846 :         p->h = q->h;
    2133       86846 :         p->key = q->key;
    2134             : 
    2135       86846 :         ZVAL_COPY_VALUE(&q->val, &val);
    2136       86846 :         q->h = h;
    2137       86846 :         q->key = key;
    2138       86846 : }
    2139             : 
    2140       70048 : ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
    2141             : {
    2142             :         zval val;
    2143             : 
    2144       70048 :         ZVAL_COPY_VALUE(&val, &p->val);
    2145       70048 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2146       70048 :         ZVAL_COPY_VALUE(&q->val, &val);
    2147       70048 : }
    2148             : 
    2149        1082 : ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q)
    2150             : {
    2151             :         zval val;
    2152             :         zend_ulong h;
    2153             : 
    2154        1082 :         ZVAL_COPY_VALUE(&val, &p->val);
    2155        1082 :         h = p->h;
    2156             : 
    2157        1082 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2158        1082 :         p->h = q->h;
    2159             : 
    2160        1082 :         ZVAL_COPY_VALUE(&q->val, &val);
    2161        1082 :         q->h = h;
    2162        1082 : }
    2163             : 
    2164       22992 : ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber)
    2165             : {
    2166             :         Bucket *p;
    2167             :         uint32_t i, j;
    2168             : 
    2169             :         IS_CONSISTENT(ht);
    2170             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    2171             : 
    2172       22992 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    2173         294 :                 return SUCCESS;
    2174             :         }
    2175             : 
    2176       22698 :         if (ht->nNumUsed == ht->nNumOfElements) {
    2177       22605 :                 i = ht->nNumUsed;
    2178             :         } else {
    2179         679 :                 for (j = 0, i = 0; j < ht->nNumUsed; j++) {
    2180         586 :                         p = ht->arData + j;
    2181        1172 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    2182         475 :                         if (i != j) {
    2183         459 :                                 ht->arData[i] = *p;
    2184             :                         }
    2185         475 :                         i++;
    2186             :                 }
    2187             :         }
    2188             : 
    2189       45098 :         sort((void *)ht->arData, i, sizeof(Bucket), compar,
    2190             :                         (swap_func_t)(renumber? zend_hash_bucket_renum_swap :
    2191       22400 :                                 ((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
    2192             : 
    2193       22697 :         HANDLE_BLOCK_INTERRUPTIONS();
    2194       22697 :         ht->nNumUsed = i;
    2195       22697 :         ht->nInternalPointer = 0;
    2196             : 
    2197       22697 :         if (renumber) {
    2198       16090 :                 for (j = 0; j < i; j++) {
    2199       15793 :                         p = ht->arData + j;
    2200       15793 :                         p->h = j;
    2201       15793 :                         if (p->key) {
    2202         231 :                                 zend_string_release(p->key);
    2203         231 :                                 p->key = NULL;
    2204             :                         }
    2205             :                 }
    2206             : 
    2207         297 :                 ht->nNextFreeElement = i;
    2208             :         }
    2209       22697 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2210         495 :                 if (!renumber) {
    2211         244 :                         zend_hash_packed_to_hash(ht);
    2212             :                 }
    2213             :         } else {
    2214       22202 :                 if (renumber) {
    2215          46 :                         void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
    2216          46 :                         Bucket *old_buckets = ht->arData;
    2217             : 
    2218          92 :                         new_data = pemalloc(HT_SIZE_EX(ht->nTableSize, HT_MIN_MASK), (ht->u.flags & HASH_FLAG_PERSISTENT));
    2219          46 :                         ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
    2220          46 :                         ht->nTableMask = HT_MIN_MASK;
    2221          46 :                         HT_SET_DATA_ADDR(ht, new_data);
    2222          46 :                         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
    2223          46 :                         pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT & HASH_FLAG_PERSISTENT);
    2224          46 :                         HT_HASH_RESET_PACKED(ht);
    2225             :                 } else {
    2226       22156 :                         zend_hash_rehash(ht);
    2227             :                 }
    2228             :         }
    2229             : 
    2230       22697 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2231             : 
    2232       22697 :         return SUCCESS;
    2233             : }
    2234             : 
    2235             : static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered) {
    2236             :         uint32_t idx1, idx2;
    2237             : 
    2238         888 :         if (ht1->nNumOfElements != ht2->nNumOfElements) {
    2239         302 :                 return ht1->nNumOfElements > ht2->nNumOfElements ? 1 : -1;
    2240             :         }
    2241             : 
    2242        4283 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    2243        3877 :                 Bucket *p1 = ht1->arData + idx1, *p2;
    2244             :                 zval *pData1, *pData2;
    2245             :                 int result;
    2246             : 
    2247        7754 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    2248        3864 :                 if (ordered) {
    2249             :                         while (1) {
    2250             :                                 ZEND_ASSERT(idx2 != ht2->nNumUsed);
    2251        1133 :                                 p2 = ht2->arData + idx2;
    2252        2266 :                                 if (Z_TYPE(p2->val) != IS_UNDEF) break;
    2253           1 :                                 idx2++;
    2254             :                         }
    2255        1132 :                         if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
    2256         364 :                                 if (p1->h != p2->h) {
    2257           2 :                                         return p1->h > p2->h ? 1 : -1;
    2258             :                                 }
    2259         768 :                         } else if (p1->key != NULL && p2->key != NULL) { /* string indices */
    2260         767 :                                 if (ZSTR_LEN(p1->key) != ZSTR_LEN(p2->key)) {
    2261           0 :                                         return ZSTR_LEN(p1->key) > ZSTR_LEN(p2->key) ? 1 : -1;
    2262             :                                 }
    2263             : 
    2264         767 :                                 result = memcmp(ZSTR_VAL(p1->key), ZSTR_VAL(p2->key), ZSTR_LEN(p1->key));
    2265         767 :                                 if (result != 0) {
    2266           0 :                                         return result;
    2267             :                                 }
    2268             :                         } else {
    2269             :                                 /* Mixed key types: A string key is considered as larger */
    2270           1 :                                 return p1->key != NULL ? 1 : -1;
    2271             :                         }
    2272        1129 :                         pData2 = &p2->val;
    2273        1129 :                         idx2++;
    2274             :                 } else {
    2275        2732 :                         if (p1->key == NULL) { /* numeric index */
    2276         485 :                                 pData2 = zend_hash_index_find(ht2, p1->h);
    2277         485 :                                 if (pData2 == NULL) {
    2278           2 :                                         return 1;
    2279             :                                 }
    2280             :                         } else { /* string index */
    2281        2247 :                                 pData2 = zend_hash_find(ht2, p1->key);
    2282        2247 :                                 if (pData2 == NULL) {
    2283          11 :                                         return 1;
    2284             :                                 }
    2285             :                         }
    2286             :                 }
    2287             : 
    2288        3848 :                 pData1 = &p1->val;
    2289        3848 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    2290         129 :                         pData1 = Z_INDIRECT_P(pData1);
    2291             :                 }
    2292        3848 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    2293         129 :                         pData2 = Z_INDIRECT_P(pData2);
    2294             :                 }
    2295             : 
    2296        3848 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    2297           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    2298           0 :                                 return -1;
    2299             :                         }
    2300        3848 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    2301           0 :                         return 1;
    2302             :                 } else {
    2303        3848 :                         result = compar(pData1, pData2);
    2304        3848 :                         if (result != 0) {
    2305         164 :                                 return result;
    2306             :                         }
    2307             :                 }
    2308             :         }
    2309             : 
    2310         406 :         return 0;
    2311             : }
    2312             : 
    2313         888 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
    2314             : {
    2315             :         int result;
    2316             :         IS_CONSISTENT(ht1);
    2317             :         IS_CONSISTENT(ht2);
    2318             : 
    2319         888 :         HASH_PROTECT_RECURSION(ht1);
    2320         888 :         HASH_PROTECT_RECURSION(ht2);
    2321        1776 :         result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
    2322         888 :         HASH_UNPROTECT_RECURSION(ht1);
    2323         888 :         HASH_UNPROTECT_RECURSION(ht2);
    2324             : 
    2325         888 :         return result;
    2326             : }
    2327             : 
    2328             : 
    2329          82 : ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
    2330             : {
    2331             :         uint32_t idx;
    2332             :         Bucket *p, *res;
    2333             : 
    2334             :         IS_CONSISTENT(ht);
    2335             : 
    2336          82 :         if (ht->nNumOfElements == 0 ) {
    2337           4 :                 return NULL;
    2338             :         }
    2339             : 
    2340          78 :         idx = 0;
    2341             :         while (1) {
    2342          78 :                 if (idx == ht->nNumUsed) {
    2343           0 :                         return NULL;
    2344             :                 }
    2345         156 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
    2346           0 :                 idx++;
    2347           0 :         }
    2348          78 :         res = ht->arData + idx;
    2349         376 :         for (; idx < ht->nNumUsed; idx++) {
    2350         298 :                 p = ht->arData + idx;
    2351         596 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    2352             : 
    2353         298 :                 if (flag) {
    2354         229 :                         if (compar(res, p) < 0) { /* max */
    2355          20 :                                 res = p;
    2356             :                         }
    2357             :                 } else {
    2358          69 :                         if (compar(res, p) > 0) { /* min */
    2359           6 :                                 res = p;
    2360             :                         }
    2361             :                 }
    2362             :         }
    2363          78 :         return &res->val;
    2364             : }
    2365             : 
    2366      383119 : ZEND_API int ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    2367             : {
    2368      383119 :         register const char *tmp = key;
    2369             : 
    2370      383119 :         const char *end = key + length;
    2371             :         ZEND_ASSERT(*end == '\0');
    2372             : 
    2373      383119 :         if (*tmp == '-') {
    2374          59 :                 tmp++;
    2375             :         }
    2376             : 
    2377      746097 :         if ((*tmp == '0' && length > 1) /* numbers with leading zeros */
    2378      362978 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    2379             :          || (SIZEOF_ZEND_LONG == 4 &&
    2380             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    2381             :              *tmp > '2')) { /* overflow */
    2382       20168 :                 return 0;
    2383             :         }
    2384      362951 :         *idx = (*tmp - '0');
    2385             :         while (1) {
    2386     1444636 :                 ++tmp;
    2387     1444636 :                 if (tmp == end) {
    2388      362688 :                         if (*key == '-') {
    2389          28 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    2390           0 :                                         return 0;
    2391             :                                 }
    2392          28 :                                 *idx = 0 - *idx;
    2393      362660 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    2394           0 :                                 return 0;
    2395             :                         }
    2396      362688 :                         return 1;
    2397             :                 }
    2398     2163633 :                 if (*tmp <= '9' && *tmp >= '0') {
    2399     1081685 :                         *idx = (*idx * 10) + (*tmp - '0');
    2400             :                 } else {
    2401         263 :                         return 0;
    2402             :                 }
    2403     1081685 :         }
    2404             : }
    2405             : 
    2406             : /*
    2407             :  * Local variables:
    2408             :  * tab-width: 4
    2409             :  * c-basic-offset: 4
    2410             :  * indent-tabs-mode: t
    2411             :  * End:
    2412             :  */

Generated by: LCOV version 1.10

Generated at Sat, 29 Aug 2015 10:22:12 +0000 (33 hours ago)

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