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: 1054 1182 89.2 %
Date: 2015-06-27 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   0x60
      36             : */
      37             : #define HT_OK                                   0x00
      38             : #define HT_IS_DESTROYING                0x20
      39             : #define HT_DESTROYED                    0x40
      40             : #define HT_CLEANING                             0x60
      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    19309295 :         nSize = (nSize <= HT_MIN_SIZE ? HT_MIN_SIZE : (nSize >= HT_MAX_SIZE ? HT_MAX_SIZE : nSize));
     101             : 
     102             : #if defined(ZEND_WIN32)
     103             :         if (BitScanReverse(&index, nSize - 1)) {
     104             :                 return 0x2 << ((31 - index) ^ 0x1f);
     105             :         } else {
     106             :                 /* nSize is ensured to be in the valid range, fall back to it
     107             :                    rather than using an undefined bis scan result. */
     108             :                 return nSize;
     109             :         }
     110             : #elif defined(__GNUC__) || __has_builtin(__builtin_clz)
     111    19309295 :         return 0x2 << (__builtin_clz(nSize - 1) ^ 0x1f);
     112             : #else
     113             :         nSize -= 1;
     114             :         nSize |= (nSize >> 1);
     115             :         nSize |= (nSize >> 2);
     116             :         nSize |= (nSize >> 4);
     117             :         nSize |= (nSize >> 8);
     118             :         nSize |= (nSize >> 16);
     119             :         return nSize + 1;
     120             : #endif
     121             : }
     122             : 
     123             : static void zend_always_inline zend_hash_real_init_ex(HashTable *ht, int packed)
     124             : {
     125             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     126             :         ZEND_ASSERT(!((ht)->u.flags & HASH_FLAG_INITIALIZED));
     127     9300741 :         if (packed) {
     128     3875116 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     129     1937558 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED;
     130     1937558 :                 HT_HASH_RESET_PACKED(ht);
     131             :         } else {
     132     7363183 :                 (ht)->nTableMask = -(ht)->nTableSize;
     133    14726366 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     134     7363183 :                 (ht)->u.flags |= HASH_FLAG_INITIALIZED;
     135     7363183 :                 HT_HASH_RESET(ht);
     136             :         }
     137             : }
     138             : 
     139             : static void zend_always_inline zend_hash_check_init(HashTable *ht, int packed)
     140             : {
     141             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     142     9113533 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     143             :                 zend_hash_real_init_ex(ht, packed);
     144             :         }
     145             : }
     146             : 
     147             : #define CHECK_INIT(ht, packed) \
     148             :         zend_hash_check_init(ht, packed)
     149             : 
     150             : static const uint32_t uninitialized_bucket[-HT_MIN_MASK] =
     151             :         {HT_INVALID_IDX, HT_INVALID_IDX};
     152             : 
     153    17706747 : ZEND_API void ZEND_FASTCALL _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     154             : {
     155    17706747 :         GC_REFCOUNT(ht) = 1;
     156    17706747 :         GC_TYPE_INFO(ht) = IS_ARRAY;
     157    17706747 :         ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
     158    17706747 :         ht->nTableSize = zend_hash_check_size(nSize);
     159    17706747 :         ht->nTableMask = HT_MIN_MASK;
     160    17706747 :         HT_SET_DATA_ADDR(ht, &uninitialized_bucket);
     161    17706747 :         ht->nNumUsed = 0;
     162    17706747 :         ht->nNumOfElements = 0;
     163    17706747 :         ht->nInternalPointer = HT_INVALID_IDX;
     164    17706747 :         ht->nNextFreeElement = 0;
     165    17706747 :         ht->pDestructor = pDestructor;
     166    17706747 : }
     167             : 
     168       16009 : static void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
     169             : {
     170             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     171       16009 :         if (ht->nTableSize >= HT_MAX_SIZE) {
     172           0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", ht->nTableSize * 2, sizeof(Bucket), sizeof(Bucket));
     173             :         }
     174       16009 :         HANDLE_BLOCK_INTERRUPTIONS();
     175       16009 :         ht->nTableSize += ht->nTableSize;
     176       32018 :         HT_SET_DATA_ADDR(ht, perealloc2(HT_GET_DATA_ADDR(ht), HT_SIZE(ht), HT_USED_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
     177       16009 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     178       16009 : }
     179             : 
     180      187208 : ZEND_API void ZEND_FASTCALL zend_hash_real_init(HashTable *ht, zend_bool packed)
     181             : {
     182             :         IS_CONSISTENT(ht);
     183             : 
     184             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     185      187208 :         zend_hash_real_init_ex(ht, packed);
     186      187208 : }
     187             : 
     188       29585 : ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
     189             : {
     190       29585 :         void *old_data = HT_GET_DATA_ADDR(ht);
     191       29585 :         Bucket *old_buckets = ht->arData;
     192             : 
     193             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     194       29585 :         HANDLE_BLOCK_INTERRUPTIONS();
     195       29585 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     196       29585 :         ht->nTableMask = -ht->nTableSize;
     197       59170 :         HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     198       29585 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     199       29585 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     200       29585 :         zend_hash_rehash(ht);
     201       29585 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     202       29585 : }
     203             : 
     204          15 : ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
     205             : {
     206          15 :         void *old_data = HT_GET_DATA_ADDR(ht);
     207          15 :         Bucket *old_buckets = ht->arData;
     208             : 
     209             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     210          15 :         HANDLE_BLOCK_INTERRUPTIONS();
     211          15 :         ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
     212          15 :         ht->nTableMask = HT_MIN_MASK;
     213          30 :         HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
     214          15 :         HT_HASH_RESET_PACKED(ht);
     215          15 :         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     216          15 :         pefree(old_data, (ht)->u.flags & HASH_FLAG_PERSISTENT);
     217          15 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     218          15 : }
     219             : 
     220    12083621 : 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)
     221             : {
     222    12083621 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
     223    12083621 :         if (!bApplyProtection) {
     224    12083621 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     225             :         }
     226    12083621 : }
     227             : 
     228     2575527 : ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, zend_bool packed)
     229             : {
     230             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     231     2575527 :         if (nSize == 0) return;
     232     2575527 :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) {
     233     1496508 :                 if (nSize > ht->nTableSize) {
     234      717186 :                         ht->nTableSize = zend_hash_check_size(nSize);
     235             :                 }
     236     1496508 :                 zend_hash_check_init(ht, packed);
     237             :         } else {
     238     1079019 :                 if (packed) {
     239             :                         ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED);
     240           0 :                         if (nSize > ht->nTableSize) {
     241           0 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     242           0 :                                 ht->nTableSize = zend_hash_check_size(nSize);
     243           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));
     244           0 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     245             :                         }
     246             :                 } else {
     247             :                         ZEND_ASSERT(!(ht->u.flags & HASH_FLAG_PACKED));
     248     1079019 :                         if (nSize > ht->nTableSize) {
     249      885362 :                                 void *old_data = HT_GET_DATA_ADDR(ht);
     250      885362 :                                 Bucket *old_buckets = ht->arData;
     251             : 
     252      885362 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     253      885362 :                                 ht->nTableSize = zend_hash_check_size(nSize);
     254      885362 :                                 ht->nTableMask = -ht->nTableSize;
     255     1770724 :                                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
     256      885362 :                                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     257      885362 :                                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     258      885362 :                                 zend_hash_rehash(ht);
     259      885362 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     260             :                         }
     261             :                 }
     262             :         }
     263             : }
     264             : 
     265           0 : ZEND_API void ZEND_FASTCALL zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     266             : {
     267           0 :         if (bApplyProtection) {
     268           0 :                 ht->u.flags |= HASH_FLAG_APPLY_PROTECTION;
     269             :         } else {
     270           0 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     271             :         }
     272           0 : }
     273             : 
     274         687 : ZEND_API uint32_t ZEND_FASTCALL zend_hash_iterator_add(HashTable *ht, HashPosition pos)
     275             : {
     276         687 :         HashTableIterator *iter = EG(ht_iterators);
     277         687 :         HashTableIterator *end  = iter + EG(ht_iterators_count);
     278             :         uint32_t idx;
     279             : 
     280         687 :         if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     281         687 :                 ht->u.v.nIteratorsCount++;
     282             :         }
     283        1820 :         while (iter != end) {
     284        1133 :                 if (iter->ht == NULL) {
     285         687 :                         iter->ht = ht;
     286         687 :                         iter->pos = pos;
     287         687 :                         idx = iter - EG(ht_iterators);
     288         687 :                         if (idx + 1 > EG(ht_iterators_used)) {
     289         673 :                                 EG(ht_iterators_used) = idx + 1;
     290             :                         }
     291         687 :                         return idx;
     292             :                 }
     293         446 :                 iter++;
     294             :         }
     295           0 :         if (EG(ht_iterators) == EG(ht_iterators_slots)) {
     296           0 :                 EG(ht_iterators) = emalloc(sizeof(HashTableIterator) * (EG(ht_iterators_count) + 8));
     297           0 :                 memcpy(EG(ht_iterators), EG(ht_iterators_slots), sizeof(HashTableIterator) * EG(ht_iterators_count));
     298             :         } else {
     299           0 :                 EG(ht_iterators) = erealloc(EG(ht_iterators), sizeof(HashTableIterator) * (EG(ht_iterators_count) + 8));
     300             :         }
     301           0 :         iter = EG(ht_iterators) + EG(ht_iterators_count);
     302           0 :         EG(ht_iterators_count) += 8;
     303           0 :         iter->ht = ht;
     304           0 :         iter->pos = pos;
     305           0 :         memset(iter + 1, 0, sizeof(HashTableIterator) * 7);
     306           0 :         idx = iter - EG(ht_iterators);
     307           0 :         EG(ht_iterators_used) = idx + 1;
     308           0 :         return idx;
     309             : }
     310             : 
     311        1386 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterator_pos(uint32_t idx, HashTable *ht)
     312             : {
     313        1386 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     314             : 
     315             :         ZEND_ASSERT(idx != (uint32_t)-1);
     316        1386 :         if (iter->pos == HT_INVALID_IDX) {
     317         175 :                 return HT_INVALID_IDX;
     318        1211 :         } else if (UNEXPECTED(iter->ht != ht)) {
     319           0 :                 if (EXPECTED(iter->ht) && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     320           0 :                         iter->ht->u.v.nIteratorsCount--;
     321             :                 }
     322           0 :                 if (EXPECTED(ht->u.v.nIteratorsCount != 255)) {
     323           0 :                         ht->u.v.nIteratorsCount++;
     324             :                 }
     325           0 :                 iter->ht = ht;
     326           0 :                 iter->pos = ht->nInternalPointer;
     327             :         }
     328        1211 :         return iter->pos;
     329             : }
     330             : 
     331         185 : ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
     332             : {
     333         185 :         HashTableIterator *iter = EG(ht_iterators) + idx;
     334             : 
     335             :         ZEND_ASSERT(idx != (uint32_t)-1);
     336             : 
     337         185 :         if (EXPECTED(iter->ht) && EXPECTED(iter->ht->u.v.nIteratorsCount != 255)) {
     338         185 :                 iter->ht->u.v.nIteratorsCount--;
     339             :         }
     340         185 :         iter->ht = NULL;
     341             : 
     342         185 :         if (idx == EG(ht_iterators_used) - 1) {
     343         370 :                 while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) {
     344           0 :                         idx--;
     345             :                 }
     346         185 :                 EG(ht_iterators_used) = idx;
     347             :         }
     348         185 : }
     349             : 
     350         484 : static zend_never_inline void ZEND_FASTCALL _zend_hash_iterators_remove(HashTable *ht)
     351             : {
     352         484 :         HashTableIterator *iter = EG(ht_iterators);
     353         484 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     354             :         uint32_t idx;
     355             : 
     356        1922 :         while (iter != end) {
     357         954 :                 if (iter->ht == ht) {
     358         494 :                         iter->ht = NULL;
     359             :                 }
     360         954 :                 iter++;
     361             :         }
     362             : 
     363         484 :         idx = EG(ht_iterators_used);
     364        1445 :         while (idx > 0 && EG(ht_iterators)[idx - 1].ht == NULL) {
     365         477 :                 idx--;
     366             :         }
     367         484 :         EG(ht_iterators_used) = idx;
     368         484 : }
     369             : 
     370             : static zend_always_inline void zend_hash_iterators_remove(HashTable *ht)
     371             : {
     372    10297209 :         if (UNEXPECTED(ht->u.v.nIteratorsCount)) {
     373         484 :                 _zend_hash_iterators_remove(ht);
     374             :         }
     375             : }
     376             : 
     377         200 : ZEND_API HashPosition ZEND_FASTCALL zend_hash_iterators_lower_pos(HashTable *ht, HashPosition start)
     378             : {
     379         200 :         HashTableIterator *iter = EG(ht_iterators);
     380         200 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     381         200 :         HashPosition res = HT_INVALID_IDX;
     382             : 
     383         490 :         while (iter != end) {
     384          90 :                 if (iter->ht == ht) {
     385          90 :                         if (iter->pos >= start && iter->pos < res) {
     386          48 :                                 res = iter->pos;
     387             :                         }
     388             :                 }
     389          90 :                 iter++;
     390             :         }
     391         200 :         return res;
     392             : }
     393             : 
     394         237 : ZEND_API void ZEND_FASTCALL _zend_hash_iterators_update(HashTable *ht, HashPosition from, HashPosition to)
     395             : {
     396         237 :         HashTableIterator *iter = EG(ht_iterators);
     397         237 :         HashTableIterator *end  = iter + EG(ht_iterators_used);
     398             : 
     399         739 :         while (iter != end) {
     400         265 :                 if (iter->ht == ht && iter->pos == from) {
     401          77 :                         iter->pos = to;
     402             :                 }
     403         265 :                 iter++;
     404             :         }
     405         237 : }
     406             : 
     407             : static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
     408             : {
     409             :         zend_ulong h;
     410             :         uint32_t nIndex;
     411             :         uint32_t idx;
     412             :         Bucket *p, *arData;
     413             : 
     414   236120220 :         h = zend_string_hash_val(key);
     415   236120220 :         arData = ht->arData;
     416   236120220 :         nIndex = h | ht->nTableMask;
     417   236120220 :         idx = HT_HASH_EX(arData, nIndex);
     418   373148377 :         while (EXPECTED(idx != HT_INVALID_IDX)) {
     419   150935549 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     420   150935549 :                 if (EXPECTED(p->key == key)) { /* check for the same interned string */
     421     9207751 :                         return p;
     422   155833744 :                 } else if (EXPECTED(p->h == h) &&
     423     4701982 :                      EXPECTED(p->key) &&
     424     4701982 :                      EXPECTED(p->key->len == key->len) &&
     425     4701982 :                      EXPECTED(memcmp(p->key->val, key->val, key->len) == 0)) {
     426     4699641 :                         return p;
     427             :                 }
     428   137028157 :                 idx = Z_NEXT(p->val);
     429             :         }
     430   222212828 :         return NULL;
     431             : }
     432             : 
     433             : static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
     434             : {
     435             :         uint32_t nIndex;
     436             :         uint32_t idx;
     437             :         Bucket *p, *arData;
     438             : 
     439     2878985 :         arData = ht->arData;
     440     2878985 :         nIndex = h | ht->nTableMask;
     441     2878985 :         idx = HT_HASH_EX(arData, nIndex);
     442     3556842 :         while (idx != HT_INVALID_IDX) {
     443             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     444     2824610 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     445     9264920 :                 if ((p->h == h)
     446             :                          && p->key
     447     4293540 :                          && (p->key->len == len)
     448     2146770 :                          && !memcmp(p->key->val, str, len)) {
     449     2146753 :                         return p;
     450             :                 }
     451      677857 :                 idx = Z_NEXT(p->val);
     452             :         }
     453      732232 :         return NULL;
     454             : }
     455             : 
     456             : static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
     457             : {
     458             :         uint32_t nIndex;
     459             :         uint32_t idx;
     460             :         Bucket *p, *arData;
     461             : 
     462     4054166 :         arData = ht->arData;
     463     4054166 :         nIndex = h | ht->nTableMask;
     464     4054166 :         idx = HT_HASH_EX(arData, nIndex);
     465     5526972 :         while (idx != HT_INVALID_IDX) {
     466             :                 ZEND_ASSERT(idx < HT_IDX_TO_HASH(ht->nTableSize));
     467     2496309 :                 p = HT_HASH_TO_BUCKET_EX(arData, idx);
     468     2496309 :                 if (p->h == h && !p->key) {
     469     1023503 :                         return p;
     470             :                 }
     471     1472806 :                 idx = Z_NEXT(p->val);
     472             :         }
     473     3030663 :         return NULL;
     474             : }
     475             : 
     476             : 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)
     477             : {
     478             :         zend_ulong h;
     479             :         uint32_t nIndex;
     480             :         uint32_t idx;
     481             :         Bucket *p;
     482             : 
     483             :         IS_CONSISTENT(ht);
     484             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     485             : 
     486   187997884 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     487             :                 CHECK_INIT(ht, 0);
     488             :                 goto add_to_hash;
     489   182316842 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     490       28014 :                 zend_hash_packed_to_hash(ht);
     491   182288828 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     492   179956602 :                 p = zend_hash_find_bucket(ht, key);
     493             : 
     494   179956602 :                 if (p) {
     495             :                         zval *data;
     496             : 
     497      564602 :                         if (flag & HASH_ADD) {
     498      264556 :                                 return NULL;
     499             :                         }
     500             :                         ZEND_ASSERT(&p->val != pData);
     501      300046 :                         data = &p->val;
     502      354452 :                         if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     503         263 :                                 data = Z_INDIRECT_P(data);
     504             :                         }
     505      300046 :                         HANDLE_BLOCK_INTERRUPTIONS();
     506      300046 :                         if (ht->pDestructor) {
     507      257574 :                                 ht->pDestructor(data);
     508             :                         }
     509      300046 :                         ZVAL_COPY_VALUE(data, pData);
     510      300046 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     511      300046 :                         return data;
     512             :                 }
     513             :         }
     514             : 
     515   181752240 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     516             : 
     517             : add_to_hash:
     518   187433282 :         HANDLE_BLOCK_INTERRUPTIONS();
     519   187433282 :         idx = ht->nNumUsed++;
     520   187433282 :         ht->nNumOfElements++;
     521   187433282 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     522     5857666 :                 ht->nInternalPointer = idx;
     523             :         }
     524             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     525   187433282 :         p = ht->arData + idx;
     526   187433282 :         p->key = key;
     527   187433282 :         if (!IS_INTERNED(key)) {
     528             :                 zend_string_addref(key);
     529   102012482 :                 ht->u.flags &= ~HASH_FLAG_STATIC_KEYS;
     530             :                 zend_string_hash_val(key);
     531             :         }
     532   187433282 :         p->h = h = key->h;
     533   187433282 :         ZVAL_COPY_VALUE(&p->val, pData);
     534   187433282 :         nIndex = h | ht->nTableMask;
     535   187433282 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     536   187433282 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     537   187433282 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     538             : 
     539   187433282 :         return &p->val;
     540             : }
     541             : 
     542     3074649 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     543             : {
     544     3074649 :         return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     545             : }
     546             : 
     547   137262064 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     548             : {
     549   137262064 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     550             : }
     551             : 
     552     7738349 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     553             : {
     554     7738349 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     555             : }
     556             : 
     557        1118 : ZEND_API zval* ZEND_FASTCALL _zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     558             : {
     559        1118 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     560             : }
     561             : 
     562     2372686 : ZEND_API zval* ZEND_FASTCALL _zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     563             : {
     564     2372686 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     565             : }
     566             : 
     567           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)
     568             : {
     569           0 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     570           0 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     571             :         zend_string_release(key);
     572           0 :         return ret;
     573             : }
     574             : 
     575    23333715 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     576             : {
     577    46667430 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     578    23333715 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     579             :         zend_string_release(key);
     580    23333715 :         return ret;
     581             : }
     582             : 
     583     1298062 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     584             : {
     585     2596124 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     586     1298062 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     587             :         zend_string_release(key);
     588     1298062 :         return ret;
     589             : }
     590             : 
     591    12914411 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     592             : {
     593    25828822 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     594    12914411 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     595             :         zend_string_release(key);
     596    12914411 :         return ret;
     597             : }
     598             : 
     599        2830 : ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     600             : {
     601        5660 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     602        2830 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     603             :         zend_string_delref(key);
     604        2830 :         return ret;
     605             : }
     606             : 
     607           0 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     608             : {
     609             :         zval dummy;
     610             : 
     611           0 :         ZVAL_NULL(&dummy);
     612           0 :         return zend_hash_index_add(ht, h, &dummy);
     613             : }
     614             : 
     615       49417 : ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     616             : {
     617             :         zval dummy;
     618             : 
     619       49417 :         ZVAL_NULL(&dummy);
     620       49417 :         return zend_hash_add(ht, key, &dummy);
     621             : }
     622             : 
     623      498452 : ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
     624             : {
     625             :         zval dummy;
     626             : 
     627      498452 :         ZVAL_NULL(&dummy);
     628      498452 :         return zend_hash_str_add(ht, str, len, &dummy);
     629             : }
     630             : 
     631             : 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)
     632             : {
     633             :         uint32_t nIndex;
     634             :         uint32_t idx;
     635             :         Bucket *p;
     636             : 
     637             :         IS_CONSISTENT(ht);
     638             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     639             : 
     640     7143225 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     641     1935983 :                 CHECK_INIT(ht, h < ht->nTableSize);
     642     1935983 :                 if (h < ht->nTableSize) {
     643     1833591 :                         p = ht->arData + h;
     644             :                         goto add_to_packed;
     645             :                 }
     646             :                 goto add_to_hash;
     647     5207242 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     648     3244312 :                 if (h < ht->nNumUsed) {
     649        3773 :                         p = ht->arData + h;
     650        7546 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     651        3620 :                                 if (flag & HASH_ADD) {
     652           0 :                                         return NULL;
     653             :                                 }
     654        3620 :                                 if (ht->pDestructor) {
     655        3620 :                                         ht->pDestructor(&p->val);
     656             :                                 }
     657        3620 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     658        3620 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     659           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     660             :                                 }
     661        3620 :                                 return &p->val;
     662             :                         } else { /* we have to keep the order :( */
     663             :                                 goto convert_to_hash;
     664             :                         }
     665     3240539 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     666     3223356 :                         p = ht->arData + h;
     667       34288 :                 } else if ((h >> 1) < ht->nTableSize &&
     668       17105 :                            (ht->nTableSize >> 1) < ht->nNumOfElements) {
     669       16009 :                         zend_hash_packed_grow(ht);
     670       16009 :                         p = ht->arData + h;
     671             :                 } else {
     672             :                         goto convert_to_hash;
     673             :                 }
     674             : 
     675             : add_to_packed:
     676     5072956 :                 HANDLE_BLOCK_INTERRUPTIONS();
     677             :                 /* incremental initialization of empty Buckets */
     678     5072956 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     679     1176994 :                         ht->nNumUsed = h + 1;
     680     3895962 :                 } else if (h >= ht->nNumUsed) {
     681     3895962 :                         if (h > ht->nNumUsed) {
     682      895270 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     683     1797595 :                                 while (q != p) {
     684      902325 :                                         ZVAL_UNDEF(&q->val);
     685      902325 :                                         q++;
     686             :                                 }
     687             :                         }
     688     3895962 :                         ht->nNumUsed = h + 1;
     689             :                 }
     690     5072956 :                 ht->nNumOfElements++;
     691     5072956 :                 if (ht->nInternalPointer == HT_INVALID_IDX) {
     692     1833731 :                         ht->nInternalPointer = h;
     693             :                 }
     694     5072956 :                 zend_hash_iterators_update(ht, HT_INVALID_IDX, h);
     695     5072956 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     696     5072945 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     697             :                 }
     698     5072956 :                 p->h = h;
     699     5072956 :                 p->key = NULL;
     700     5072956 :                 ZVAL_COPY_VALUE(&p->val, pData);
     701             : 
     702     5072956 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     703             : 
     704     5072956 :                 return &p->val;
     705             : 
     706             : convert_to_hash:
     707        1327 :                 zend_hash_packed_to_hash(ht);
     708     1962930 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     709     1309744 :                 p = zend_hash_index_find_bucket(ht, h);
     710     1309744 :                 if (p) {
     711       10407 :                         if (flag & HASH_ADD) {
     712         158 :                                 return NULL;
     713             :                         }
     714             :                         ZEND_ASSERT(&p->val != pData);
     715       10249 :                         HANDLE_BLOCK_INTERRUPTIONS();
     716       10249 :                         if (ht->pDestructor) {
     717       10204 :                                 ht->pDestructor(&p->val);
     718             :                         }
     719       10249 :                         ZVAL_COPY_VALUE(&p->val, pData);
     720       10249 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     721       10249 :                         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     722           1 :                                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     723             :                         }
     724       10249 :                         return &p->val;
     725             :                 }
     726             :         }
     727             : 
     728     1953850 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     729             : 
     730             : add_to_hash:
     731     2056242 :         HANDLE_BLOCK_INTERRUPTIONS();
     732     2056242 :         idx = ht->nNumUsed++;
     733     2056242 :         ht->nNumOfElements++;
     734     2056242 :         if (ht->nInternalPointer == HT_INVALID_IDX) {
     735      170883 :                 ht->nInternalPointer = idx;
     736             :         }
     737             :         zend_hash_iterators_update(ht, HT_INVALID_IDX, idx);
     738     2056242 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     739      660533 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     740             :         }
     741     2056242 :         p = ht->arData + idx;
     742     2056242 :         p->h = h;
     743     2056242 :         p->key = NULL;
     744     2056242 :         nIndex = h | ht->nTableMask;
     745     2056242 :         ZVAL_COPY_VALUE(&p->val, pData);
     746     2056242 :         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     747     2056242 :         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
     748     2056242 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     749             : 
     750     2056242 :         return &p->val;
     751             : }
     752             : 
     753           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)
     754             : {
     755           0 :         return _zend_hash_index_add_or_update_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
     756             : }
     757             : 
     758         520 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     759             : {
     760         520 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     761             : }
     762             : 
     763     1091219 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     764             : {
     765     1091219 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     766             : }
     767             : 
     768     2309449 : ZEND_API zval* ZEND_FASTCALL _zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     769             : {
     770     2309449 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     771             : }
     772             : 
     773     2564514 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     774             : {
     775     5129028 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     776             : }
     777             : 
     778     1177523 : ZEND_API zval* ZEND_FASTCALL _zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     779             : {
     780     2355046 :         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);
     781             : }
     782             : 
     783     4551115 : static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
     784             : {
     785             : 
     786             :         IS_CONSISTENT(ht);
     787             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     788             : 
     789     4551115 :         if (ht->nNumUsed > ht->nNumOfElements) {
     790       24166 :                 HANDLE_BLOCK_INTERRUPTIONS();
     791       24166 :                 zend_hash_rehash(ht);
     792       24166 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     793     4526949 :         } else if (ht->nTableSize < HT_MAX_SIZE) {        /* Let's double the table size */
     794     4526949 :                 void *old_data = HT_GET_DATA_ADDR(ht);
     795     4526949 :                 Bucket *old_buckets = ht->arData;
     796             : 
     797     4526949 :                 HANDLE_BLOCK_INTERRUPTIONS();
     798     4526949 :                 ht->nTableSize += ht->nTableSize;
     799     4526949 :                 ht->nTableMask = -ht->nTableSize;
     800     9053898 :                 HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
     801     4526949 :                 memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
     802     4526949 :                 pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
     803     4526949 :                 zend_hash_rehash(ht);
     804     4526949 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     805             :         } else {
     806           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));
     807             :         }
     808     4551115 : }
     809             : 
     810     5551185 : ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht)
     811             : {
     812             :         Bucket *p;
     813             :         uint32_t nIndex, i;
     814             : 
     815             :         IS_CONSISTENT(ht);
     816             : 
     817     5551185 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     818           5 :                 if (ht->u.flags & HASH_FLAG_INITIALIZED) {
     819           2 :                         ht->nNumUsed = 0;
     820           2 :                         HT_HASH_RESET(ht);
     821             :                 }
     822           5 :                 return SUCCESS;
     823             :         }
     824             : 
     825     5551180 :         HT_HASH_RESET(ht);
     826     5551180 :         i = 0;
     827     5551180 :         p = ht->arData;
     828     5551180 :         if (ht->nNumUsed == ht->nNumOfElements) {
     829             :                 do {
     830   396242703 :                         nIndex = p->h | ht->nTableMask;
     831   396242703 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     832   396242703 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     833   396242703 :                         p++;
     834   396242703 :                 } while (++i < ht->nNumUsed);
     835             :         } else {
     836             :                 do {
     837      720336 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) {
     838       25663 :                                 uint32_t j = i;
     839       25663 :                                 Bucket *q = p;
     840             : 
     841       25663 :                                 if (EXPECTED(ht->u.v.nIteratorsCount == 0)) {
     842      258222 :                                         while (++i < ht->nNumUsed) {
     843      206902 :                                                 p++;
     844      206902 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     845      167227 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     846      167227 :                                                         q->h = p->h;
     847      167227 :                                                         nIndex = q->h | ht->nTableMask;
     848      167227 :                                                         q->key = p->key;
     849      167227 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     850      167227 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     851      167227 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     852       22526 :                                                                 ht->nInternalPointer = j;
     853             :                                                         }
     854      167227 :                                                         q++;
     855      167227 :                                                         j++;
     856             :                                                 }
     857             :                                         }
     858             :                                 } else {
     859           3 :                                         uint32_t iter_pos = zend_hash_iterators_lower_pos(ht, 0);
     860             : 
     861          27 :                                         while (++i < ht->nNumUsed) {
     862          21 :                                                 p++;
     863          21 :                                                 if (EXPECTED(Z_TYPE_INFO(p->val) != IS_UNDEF)) {
     864          12 :                                                         ZVAL_COPY_VALUE(&q->val, &p->val);
     865          12 :                                                         q->h = p->h;
     866          12 :                                                         nIndex = q->h | ht->nTableMask;
     867          12 :                                                         q->key = p->key;
     868          12 :                                                         Z_NEXT(q->val) = HT_HASH(ht, nIndex);
     869          12 :                                                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(j);
     870          12 :                                                         if (UNEXPECTED(ht->nInternalPointer == i)) {
     871           3 :                                                                 ht->nInternalPointer = j;
     872             :                                                         }
     873          12 :                                                         if (UNEXPECTED(i == iter_pos)) {
     874             :                                                                 zend_hash_iterators_update(ht, i, j);
     875           5 :                                                                 iter_pos = zend_hash_iterators_lower_pos(ht, iter_pos + 1);
     876             :                                                         }
     877          12 :                                                         q++;
     878          12 :                                                         j++;
     879             :                                                 }
     880             :                                         }
     881             :                                 }
     882       25663 :                                 ht->nNumUsed = j;
     883       25663 :                                 break;
     884             :                         }
     885      334505 :                         nIndex = p->h | ht->nTableMask;
     886      334505 :                         Z_NEXT(p->val) = HT_HASH(ht, nIndex);
     887      334505 :                         HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(i);
     888      334505 :                         p++;
     889      334505 :                 } while (++i < ht->nNumUsed);
     890             :         }
     891     5551180 :         return SUCCESS;
     892             : }
     893             : 
     894             : static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
     895             : {
     896    51000272 :         HANDLE_BLOCK_INTERRUPTIONS();
     897    51000272 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     898    50895789 :                 if (prev) {
     899     3014335 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     900             :                 } else {
     901    47881454 :                         HT_HASH(ht, p->h | ht->nTableMask) = Z_NEXT(p->val);
     902             :                 }
     903             :         }
     904    51000272 :         if (HT_IDX_TO_HASH(ht->nNumUsed - 1) == idx) {
     905             :                 do {
     906     3650846 :                         ht->nNumUsed--;
     907     7127448 :                 } while (ht->nNumUsed > 0 && (UNEXPECTED(Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF)));
     908             :         }
     909    51000272 :         ht->nNumOfElements--;
     910    51000272 :         if (HT_IDX_TO_HASH(ht->nInternalPointer) == idx || UNEXPECTED(ht->u.v.nIteratorsCount)) {
     911             :                 uint32_t new_idx;
     912             : 
     913     3240302 :                 new_idx = idx = HT_HASH_TO_IDX(idx);
     914             :                 while (1) {
     915    45380297 :                         new_idx++;
     916    45380297 :                         if (new_idx >= ht->nNumUsed) {
     917      132165 :                                 new_idx = HT_INVALID_IDX;
     918             :                                 break;
     919    90496264 :                         } else if (Z_TYPE(ht->arData[new_idx].val) != IS_UNDEF) {
     920             :                                 break;
     921             :                         }
     922             :                 }
     923     3240302 :                 if (ht->nInternalPointer == idx) {
     924     3240265 :                         ht->nInternalPointer = new_idx;
     925             :                 }
     926             :                 zend_hash_iterators_update(ht, idx, new_idx);
     927             :         }
     928    51000272 :         if (p->key) {
     929    50723972 :                 zend_string_release(p->key);
     930             :         }
     931    51000272 :         if (ht->pDestructor) {
     932             :                 zval tmp;
     933    50191026 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     934    50191026 :                 ZVAL_UNDEF(&p->val);
     935    50191026 :                 ht->pDestructor(&tmp);
     936             :         } else {
     937      809246 :                 ZVAL_UNDEF(&p->val);
     938             :         }
     939    51000272 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     940             : }
     941             : 
     942             : static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
     943             : {
     944     7067606 :         Bucket *prev = NULL;
     945             : 
     946     7067606 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     947     7063689 :                 uint32_t nIndex = p->h | ht->nTableMask;
     948     7063689 :                 uint32_t i = HT_HASH(ht, nIndex);
     949             : 
     950     7063689 :                 if (i != idx) {
     951      589725 :                         prev = HT_HASH_TO_BUCKET(ht, i);
     952      633944 :                         while (Z_NEXT(prev->val) != idx) {
     953       44219 :                                 i = Z_NEXT(prev->val);
     954       44219 :                                 prev = HT_HASH_TO_BUCKET(ht, i);
     955             :                         }
     956             :                 }
     957             :         }
     958             : 
     959             :         _zend_hash_del_el_ex(ht, idx, p, prev);
     960             : }
     961             : 
     962          24 : ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p)
     963             : {
     964             :         IS_CONSISTENT(ht);
     965             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     966          24 :         _zend_hash_del_el(ht, HT_IDX_TO_HASH(p - ht->arData), p);
     967          24 : }
     968             : 
     969    43738355 : ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key)
     970             : {
     971             :         zend_ulong h;
     972             :         uint32_t nIndex;
     973             :         uint32_t idx;
     974             :         Bucket *p;
     975    43738355 :         Bucket *prev = NULL;
     976             : 
     977             :         IS_CONSISTENT(ht);
     978             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
     979             : 
     980    43738355 :         h = zend_string_hash_val(key);
     981    43738355 :         nIndex = h | ht->nTableMask;
     982             : 
     983    43738355 :         idx = HT_HASH(ht, nIndex);
     984    90024501 :         while (idx != HT_INVALID_IDX) {
     985    45510839 :                 p = HT_HASH_TO_BUCKET(ht, idx);
     986   219799760 :                 if ((p->key == key) ||
     987    45483039 :                         (p->h == h &&
     988    42935294 :                      p->key &&
     989    42935294 :                      p->key->len == key->len &&
     990    42935294 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     991             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     992    42963048 :                         return SUCCESS;
     993             :                 }
     994     2547791 :                 prev = p;
     995     2547791 :                 idx = Z_NEXT(p->val);
     996             :         }
     997      775307 :         return FAILURE;
     998             : }
     999             : 
    1000         399 : ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key)
    1001             : {
    1002             :         zend_ulong h;
    1003             :         uint32_t nIndex;
    1004             :         uint32_t idx;
    1005             :         Bucket *p;
    1006         399 :         Bucket *prev = NULL;
    1007             : 
    1008             :         IS_CONSISTENT(ht);
    1009             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1010             : 
    1011         399 :         h = zend_string_hash_val(key);
    1012         399 :         nIndex = h | ht->nTableMask;
    1013             : 
    1014         399 :         idx = HT_HASH(ht, nIndex);
    1015         806 :         while (idx != HT_INVALID_IDX) {
    1016         218 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1017         914 :                 if ((p->key == key) ||
    1018         180 :                         (p->h == h &&
    1019         172 :                      p->key &&
    1020         172 :                      p->key->len == key->len &&
    1021         172 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
    1022         420 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
    1023          14 :                                 zval *data = Z_INDIRECT(p->val);
    1024             : 
    1025          14 :                                 if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1026           0 :                                         return FAILURE;
    1027             :                                 } else {
    1028          14 :                                         if (ht->pDestructor) {
    1029          14 :                                                 ht->pDestructor(data);
    1030             :                                         }
    1031          14 :                                         ZVAL_UNDEF(data);
    1032             :                                 }
    1033             :                         } else {
    1034             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
    1035             :                         }
    1036         210 :                         return SUCCESS;
    1037             :                 }
    1038           8 :                 prev = p;
    1039           8 :                 idx = Z_NEXT(p->val);
    1040             :         }
    1041         189 :         return FAILURE;
    1042             : }
    1043             : 
    1044           0 : ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
    1045             : {
    1046             :         zend_ulong h;
    1047             :         uint32_t nIndex;
    1048             :         uint32_t idx;
    1049             :         Bucket *p;
    1050           0 :         Bucket *prev = NULL;
    1051             : 
    1052             :         IS_CONSISTENT(ht);
    1053             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1054             : 
    1055           0 :         h = zend_inline_hash_func(str, len);
    1056           0 :         nIndex = h | ht->nTableMask;
    1057             : 
    1058           0 :         idx = HT_HASH(ht, nIndex);
    1059           0 :         while (idx != HT_INVALID_IDX) {
    1060           0 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1061           0 :                 if ((p->h == h)
    1062             :                          && p->key
    1063           0 :                          && (p->key->len == len)
    1064           0 :                          && !memcmp(p->key->val, str, len)) {
    1065           0 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
    1066           0 :                                 zval *data = Z_INDIRECT(p->val);
    1067             : 
    1068           0 :                                 if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1069           0 :                                         return FAILURE;
    1070             :                                 } else {
    1071           0 :                                         if (ht->pDestructor) {
    1072           0 :                                                 ht->pDestructor(data);
    1073             :                                         }
    1074           0 :                                         ZVAL_UNDEF(data);
    1075             :                                 }
    1076             :                         } else {
    1077             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
    1078             :                         }
    1079           0 :                         return SUCCESS;
    1080             :                 }
    1081           0 :                 prev = p;
    1082           0 :                 idx = Z_NEXT(p->val);
    1083             :         }
    1084           0 :         return FAILURE;
    1085             : }
    1086             : 
    1087      742433 : ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
    1088             : {
    1089             :         zend_ulong h;
    1090             :         uint32_t nIndex;
    1091             :         uint32_t idx;
    1092             :         Bucket *p;
    1093      742433 :         Bucket *prev = NULL;
    1094             : 
    1095             :         IS_CONSISTENT(ht);
    1096             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1097             : 
    1098      742433 :         h = zend_inline_hash_func(str, len);
    1099      742433 :         nIndex = h | ht->nTableMask;
    1100             : 
    1101      742433 :         idx = HT_HASH(ht, nIndex);
    1102     1527478 :         while (idx != HT_INVALID_IDX) {
    1103      761226 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1104     2917068 :                 if ((p->h == h)
    1105             :                          && p->key
    1106     1437228 :                          && (p->key->len == len)
    1107      718614 :                          && !memcmp(p->key->val, str, len)) {
    1108             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1109      718614 :                         return SUCCESS;
    1110             :                 }
    1111       42612 :                 prev = p;
    1112       42612 :                 idx = Z_NEXT(p->val);
    1113             :         }
    1114       23819 :         return FAILURE;
    1115             : }
    1116             : 
    1117      262168 : ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
    1118             : {
    1119             :         uint32_t nIndex;
    1120             :         uint32_t idx;
    1121             :         Bucket *p;
    1122      262168 :         Bucket *prev = NULL;
    1123             : 
    1124             :         IS_CONSISTENT(ht);
    1125             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1126             : 
    1127      262168 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1128      106733 :                 if (h < ht->nNumUsed) {
    1129      100572 :                         p = ht->arData + h;
    1130      201144 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1131      100566 :                                 _zend_hash_del_el_ex(ht, HT_IDX_TO_HASH(h), p, NULL);
    1132      100566 :                                 return SUCCESS;
    1133             :                         }
    1134             :                 }
    1135        6167 :                 return FAILURE;
    1136             :         }
    1137      155435 :         nIndex = h | ht->nTableMask;
    1138             : 
    1139      155435 :         idx = HT_HASH(ht, nIndex);
    1140      311941 :         while (idx != HT_INVALID_IDX) {
    1141      151313 :                 p = HT_HASH_TO_BUCKET(ht, idx);
    1142      151313 :                 if ((p->h == h) && (p->key == NULL)) {
    1143             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
    1144      150242 :                         return SUCCESS;
    1145             :                 }
    1146        1071 :                 prev = p;
    1147        1071 :                 idx = Z_NEXT(p->val);
    1148             :         }
    1149        5193 :         return FAILURE;
    1150             : }
    1151             : 
    1152    15245207 : ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
    1153             : {
    1154             :         Bucket *p, *end;
    1155             : 
    1156             :         IS_CONSISTENT(ht);
    1157             :         HT_ASSERT(GC_REFCOUNT(ht) <= 1);
    1158             : 
    1159    15245207 :         if (ht->nNumUsed) {
    1160     8030780 :                 p = ht->arData;
    1161     8030780 :                 end = p + ht->nNumUsed;
    1162     8030780 :                 if (ht->pDestructor) {
    1163             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
    1164             : 
    1165     7727399 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1166     5073125 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1167             :                                         do {
    1168   153533500 :                                                 ht->pDestructor(&p->val);
    1169   153533499 :                                         } while (++p != end);
    1170             :                                 } else {
    1171             :                                         do {
    1172    93332730 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1173     3012574 :                                                         ht->pDestructor(&p->val);
    1174             :                                                 }
    1175    46666365 :                                         } while (++p != end);
    1176             :                                 }
    1177     2654274 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1178             :                                 do {
    1179    89327233 :                                         ht->pDestructor(&p->val);
    1180    89327233 :                                         if (EXPECTED(p->key)) {
    1181    89320873 :                                                 zend_string_release(p->key);
    1182             :                                         }
    1183    89327233 :                                 } while (++p != end);
    1184             :                         } else {
    1185             :                                 do {
    1186     9394820 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1187      274308 :                                                 ht->pDestructor(&p->val);
    1188      274308 :                                                 if (EXPECTED(p->key)) {
    1189      274308 :                                                         zend_string_release(p->key);
    1190             :                                                 }
    1191             :                                         }
    1192     4697410 :                                 } while (++p != end);
    1193             :                         }
    1194             : 
    1195             :                         SET_INCONSISTENT(HT_DESTROYED);
    1196             :                 } else {
    1197      303381 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1198             :                                 do {
    1199    17995370 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1200     8913342 :                                                 if (EXPECTED(p->key)) {
    1201     8912712 :                                                         zend_string_release(p->key);
    1202             :                                                 }
    1203             :                                         }
    1204     8997685 :                                 } while (++p != end);
    1205             :                         }
    1206             :                 }
    1207             :                 zend_hash_iterators_remove(ht);
    1208     7214427 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1209     7145448 :                 return;
    1210             :         }
    1211     8099758 :         pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1212             : }
    1213             : 
    1214     3661401 : ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
    1215             : {
    1216             :         Bucket *p, *end;
    1217             : 
    1218             :         IS_CONSISTENT(ht);
    1219             :         HT_ASSERT(GC_REFCOUNT(ht) <= 1);
    1220             : 
    1221     3661401 :         if (ht->nNumUsed) {
    1222             : 
    1223             :                 /* In some rare cases destructors of regular arrays may be changed */
    1224     2266503 :                 if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
    1225          71 :                         zend_hash_destroy(ht);
    1226          71 :                         goto free_ht;
    1227             :                 }
    1228             : 
    1229     2266432 :                 p = ht->arData;
    1230     2266432 :                 end = p + ht->nNumUsed;
    1231             :                 SET_INCONSISTENT(HT_IS_DESTROYING);
    1232             : 
    1233     2266432 :                 if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1234             :                         do {
    1235     5337369 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1236     5337367 :                         } while (++p != end);
    1237      253917 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1238             :                         do {
    1239     4442742 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1240     4442742 :                                 if (EXPECTED(p->key)) {
    1241     4380080 :                                         zend_string_release(p->key);
    1242             :                                 }
    1243     4442742 :                         } while (++p != end);
    1244             :                 } else {
    1245             :                         do {
    1246        4504 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1247        1954 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1248        1954 :                                         if (EXPECTED(p->key)) {
    1249        1895 :                                                 zend_string_release(p->key);
    1250             :                                         }
    1251             :                                 }
    1252        2252 :                         } while (++p != end);
    1253             :                 }
    1254             :                 zend_hash_iterators_remove(ht);
    1255             :                 SET_INCONSISTENT(HT_DESTROYED);
    1256     1394898 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
    1257     1392615 :                 goto free_ht;
    1258             :         }
    1259     2268713 :         efree(HT_GET_DATA_ADDR(ht));
    1260             : free_ht:
    1261     3661399 :         FREE_HASHTABLE(ht);
    1262     3661399 : }
    1263             : 
    1264       51110 : ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
    1265             : {
    1266             :         Bucket *p, *end;
    1267             : 
    1268             :         IS_CONSISTENT(ht);
    1269             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1270             : 
    1271       51110 :         if (ht->nNumUsed) {
    1272        8625 :                 p = ht->arData;
    1273        8625 :                 end = p + ht->nNumUsed;
    1274        8625 :                 if (ht->pDestructor) {
    1275        3610 :                         if (ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS)) {
    1276         991 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1277             :                                         do {
    1278      517146 :                                                 ht->pDestructor(&p->val);
    1279      517146 :                                         } while (++p != end);
    1280             :                                 } else {
    1281             :                                         do {
    1282          78 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1283           9 :                                                         ht->pDestructor(&p->val);
    1284             :                                                 }
    1285          39 :                                         } while (++p != end);
    1286             :                                 }
    1287        2619 :                         } else if (ht->nNumUsed == ht->nNumOfElements) {
    1288             :                                 do {
    1289     1249834 :                                         ht->pDestructor(&p->val);
    1290     1249834 :                                         if (EXPECTED(p->key)) {
    1291     1249834 :                                                 zend_string_release(p->key);
    1292             :                                         }
    1293     1249834 :                                 } while (++p != end);
    1294             :                         } else {
    1295             :                                 do {
    1296           0 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1297           0 :                                                 ht->pDestructor(&p->val);
    1298           0 :                                                 if (EXPECTED(p->key)) {
    1299           0 :                                                         zend_string_release(p->key);
    1300             :                                                 }
    1301             :                                         }
    1302           0 :                                 } while (++p != end);
    1303             :                         }
    1304             :                 } else {
    1305        5015 :                         if (!(ht->u.flags & (HASH_FLAG_PACKED|HASH_FLAG_STATIC_KEYS))) {
    1306        4588 :                                 if (ht->nNumUsed == ht->nNumOfElements) {
    1307             :                                         do {
    1308       27553 :                                                 if (EXPECTED(p->key)) {
    1309       27553 :                                                         zend_string_release(p->key);
    1310             :                                                 }
    1311       27553 :                                         } while (++p != end);
    1312             :                                 } else {
    1313             :                                         do {
    1314           0 :                                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1315           0 :                                                         if (EXPECTED(p->key)) {
    1316           0 :                                                                 zend_string_release(p->key);
    1317             :                                                         }
    1318             :                                                 }
    1319           0 :                                         } while (++p != end);
    1320             :                                 }
    1321             :                         }
    1322             :                 }
    1323        8625 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1324        8610 :                         HT_HASH_RESET(ht);
    1325             :                 }
    1326             :         }
    1327       51110 :         ht->nNumUsed = 0;
    1328       51110 :         ht->nNumOfElements = 0;
    1329       51110 :         ht->nNextFreeElement = 0;
    1330       51110 :         ht->nInternalPointer = HT_INVALID_IDX;
    1331       51110 : }
    1332             : 
    1333       87839 : ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
    1334             : {
    1335             :         Bucket *p, *end;
    1336             : 
    1337             :         IS_CONSISTENT(ht);
    1338             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1339             : 
    1340       87839 :         if (ht->nNumUsed) {
    1341       87832 :                 p = ht->arData;
    1342       87832 :                 end = p + ht->nNumUsed;
    1343       87832 :                 if (ht->u.flags & HASH_FLAG_STATIC_KEYS) {
    1344             :                         do {
    1345      176995 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1346      176995 :                         } while (++p != end);
    1347          80 :                 } else if (ht->nNumUsed == ht->nNumOfElements) {
    1348             :                         do {
    1349         570 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1350         570 :                                 zend_string_release(p->key);
    1351         570 :                         } while (++p != end);
    1352             :                 } else {
    1353             :                         do {
    1354           0 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1355           0 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1356           0 :                                         zend_string_release(p->key);
    1357             :                                 }
    1358           0 :                         } while (++p != end);
    1359             :                 }
    1360       87832 :                 HT_HASH_RESET(ht);
    1361             :         }
    1362       87839 :         ht->nNumUsed = 0;
    1363       87839 :         ht->nNumOfElements = 0;
    1364       87839 :         ht->nNextFreeElement = 0;
    1365       87839 :         ht->nInternalPointer = HT_INVALID_IDX;
    1366       87839 : }
    1367             : 
    1368           0 : ZEND_API void ZEND_FASTCALL zend_hash_graceful_destroy(HashTable *ht)
    1369             : {
    1370             :         uint32_t idx;
    1371             :         Bucket *p;
    1372             : 
    1373             :         IS_CONSISTENT(ht);
    1374             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1375             : 
    1376           0 :         p = ht->arData;
    1377           0 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1378           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1379             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1380             :         }
    1381           0 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1382           0 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1383             :         }
    1384             : 
    1385             :         SET_INCONSISTENT(HT_DESTROYED);
    1386           0 : }
    1387             : 
    1388       84380 : ZEND_API void ZEND_FASTCALL zend_hash_graceful_reverse_destroy(HashTable *ht)
    1389             : {
    1390             :         uint32_t idx;
    1391             :         Bucket *p;
    1392             : 
    1393             :         IS_CONSISTENT(ht);
    1394             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1395             : 
    1396       84380 :         idx = ht->nNumUsed;
    1397       84380 :         p = ht->arData + ht->nNumUsed;
    1398     1857944 :         while (idx > 0) {
    1399     1689184 :                 idx--;
    1400     1689184 :                 p--;
    1401     3378368 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1402             :                 _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1403             :         }
    1404             : 
    1405       84380 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1406       64118 :                 pefree(HT_GET_DATA_ADDR(ht), ht->u.flags & HASH_FLAG_PERSISTENT);
    1407             :         }
    1408             : 
    1409             :         SET_INCONSISTENT(HT_DESTROYED);
    1410       84380 : }
    1411             : 
    1412             : /* This is used to recurse elements and selectively delete certain entries
    1413             :  * from a hashtable. apply_func() receives the data and decides if the entry
    1414             :  * should be deleted or recursion should be stopped. The following three
    1415             :  * return codes are possible:
    1416             :  * ZEND_HASH_APPLY_KEEP   - continue
    1417             :  * ZEND_HASH_APPLY_STOP   - stop iteration
    1418             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
    1419             :  */
    1420             : 
    1421       93742 : ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
    1422             : {
    1423             :         uint32_t idx;
    1424             :         Bucket *p;
    1425             :         int result;
    1426             : 
    1427             :         IS_CONSISTENT(ht);
    1428             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1429             : 
    1430       93742 :         HASH_PROTECT_RECURSION(ht);
    1431       93742 :         p = ht->arData;
    1432     1659750 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1433     3132026 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1434     1565992 :                 result = apply_func(&p->val);
    1435             : 
    1436     1565987 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1437             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1438             :                 }
    1439     1565987 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1440           0 :                         break;
    1441             :                 }
    1442             :         }
    1443       93737 :         HASH_UNPROTECT_RECURSION(ht);
    1444       93737 : }
    1445             : 
    1446             : 
    1447      580031 : ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
    1448             : {
    1449             :     uint32_t idx;
    1450             :         Bucket *p;
    1451             :         int result;
    1452             : 
    1453             :         IS_CONSISTENT(ht);
    1454             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1455             : 
    1456      580031 :         HASH_PROTECT_RECURSION(ht);
    1457      580031 :         p = ht->arData;
    1458   123598445 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1459   246044510 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1460    89999109 :                 result = apply_func(&p->val, argument);
    1461             : 
    1462    89999109 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1463             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1464             :                 }
    1465    89999109 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1466        3841 :                         break;
    1467             :                 }
    1468             :         }
    1469      580031 :         HASH_UNPROTECT_RECURSION(ht);
    1470      580031 : }
    1471             : 
    1472             : 
    1473         297 : ZEND_API void ZEND_FASTCALL zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args, ...)
    1474             : {
    1475             :         uint32_t idx;
    1476             :         Bucket *p;
    1477             :         va_list args;
    1478             :         zend_hash_key hash_key;
    1479             :         int result;
    1480             : 
    1481             :         IS_CONSISTENT(ht);
    1482             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1483             : 
    1484         297 :         HASH_PROTECT_RECURSION(ht);
    1485             : 
    1486         297 :         p = ht->arData;
    1487      157904 :         for (idx = 0; idx < ht->nNumUsed; idx++, p++) {
    1488      315214 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1489      157541 :                 va_start(args, num_args);
    1490      157541 :                 hash_key.h = p->h;
    1491      157541 :                 hash_key.key = p->key;
    1492             : 
    1493      157541 :                 result = apply_func(&p->val, num_args, args, &hash_key);
    1494             : 
    1495      157541 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1496             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1497             :                 }
    1498      157541 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1499           0 :                         va_end(args);
    1500           0 :                         break;
    1501             :                 }
    1502      157541 :                 va_end(args);
    1503             :         }
    1504             : 
    1505         297 :         HASH_UNPROTECT_RECURSION(ht);
    1506         297 : }
    1507             : 
    1508             : 
    1509      110210 : ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func)
    1510             : {
    1511             :         uint32_t idx;
    1512             :         Bucket *p;
    1513             :         int result;
    1514             : 
    1515             :         IS_CONSISTENT(ht);
    1516             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    1517             : 
    1518      110210 :         HASH_PROTECT_RECURSION(ht);
    1519      110210 :         idx = ht->nNumUsed;
    1520      110210 :         p = ht->arData + idx;
    1521      724549 :         while (idx > 0) {
    1522      567261 :                 idx--;
    1523      567261 :                 p--;
    1524     1134522 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1525             : 
    1526      515245 :                 result = apply_func(&p->val);
    1527             : 
    1528      515245 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1529             :                         _zend_hash_del_el(ht, HT_IDX_TO_HASH(idx), p);
    1530             :                 }
    1531      515245 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1532       63132 :                         break;
    1533             :                 }
    1534             :         }
    1535      110210 :         HASH_UNPROTECT_RECURSION(ht);
    1536      110210 : }
    1537             : 
    1538             : 
    1539         465 : ZEND_API void ZEND_FASTCALL zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
    1540             : {
    1541             :     uint32_t idx;
    1542             :         Bucket *p;
    1543             :         zval *new_entry, *data;
    1544             :         zend_bool setTargetPointer;
    1545             : 
    1546             :         IS_CONSISTENT(source);
    1547             :         IS_CONSISTENT(target);
    1548             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1549             : 
    1550         465 :         setTargetPointer = (target->nInternalPointer == HT_INVALID_IDX);
    1551       11233 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1552       10768 :                 p = source->arData + idx;
    1553       21536 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1554             : 
    1555       10768 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1556         307 :                         target->nInternalPointer = HT_INVALID_IDX;
    1557             :                 }
    1558             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1559       10768 :                 data = &p->val;
    1560       10768 :                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1561          96 :                         data = Z_INDIRECT_P(data);
    1562          96 :                         if (UNEXPECTED(Z_TYPE_P(data) == IS_UNDEF)) {
    1563           0 :                                 continue;
    1564             :                         }
    1565             :                 }
    1566       10768 :                 if (p->key) {
    1567       10679 :                         new_entry = zend_hash_update(target, p->key, data);
    1568             :                 } else {
    1569          89 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1570             :                 }
    1571       10768 :                 if (pCopyConstructor) {
    1572         408 :                         pCopyConstructor(new_entry);
    1573             :                 }
    1574             :         }
    1575         465 :         if (target->nInternalPointer == HT_INVALID_IDX && target->nNumOfElements > 0) {
    1576           0 :                 idx = 0;
    1577           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1578           0 :                         idx++;
    1579             :                 }
    1580           0 :                 target->nInternalPointer = idx;
    1581             :         }
    1582         465 : }
    1583             : 
    1584             : 
    1585             : 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)
    1586             : {
    1587     3537870 :         zval *data = &p->val;
    1588             : 
    1589     3537870 :         if (with_holes) {
    1590     2531167 :                 if (!packed && Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1591           0 :                         data = Z_INDIRECT_P(data);
    1592             :                 }
    1593     2531167 :                 if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1594      842891 :                         return 0;
    1595             :                 }
    1596     1006703 :         } else if (!packed) {
    1597             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1598      700517 :                 if (Z_TYPE_INFO_P(data) == IS_INDIRECT) {
    1599       17825 :                         data = Z_INDIRECT_P(data);
    1600       17825 :                         if (UNEXPECTED(Z_TYPE_INFO_P(data) == IS_UNDEF)) {
    1601        2851 :                                 return 0;
    1602             :                         }
    1603             :                 }
    1604             :         }
    1605             : 
    1606             :         do {
    1607     2692128 :                 if (Z_OPT_REFCOUNTED_P(data)) {
    1608     2508519 :                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1 &&
    1609          62 :                             (Z_TYPE_P(Z_REFVAL_P(data)) != IS_ARRAY ||
    1610          19 :                               Z_ARRVAL_P(Z_REFVAL_P(data)) != source)) {
    1611          59 :                                 data = Z_REFVAL_P(data);
    1612          59 :                                 if (!Z_OPT_REFCOUNTED_P(data)) {
    1613             :                                         break;
    1614             :                                 }
    1615             :                         }
    1616             :                         Z_ADDREF_P(data);
    1617             :                 }
    1618             :         } while (0);
    1619     2692128 :         ZVAL_COPY_VALUE(&q->val, data);
    1620             : 
    1621     2692128 :         q->h = p->h;
    1622     2692128 :         if (packed) {
    1623     1994442 :                 q->key = NULL;
    1624             :         } else {
    1625             :                 uint32_t nIndex;
    1626             : 
    1627      697686 :                 q->key = p->key;
    1628      697686 :                 if (!static_keys && q->key) {
    1629      691769 :                         zend_string_addref(q->key);
    1630             :                 }
    1631             : 
    1632      697686 :                 nIndex = q->h | target->nTableMask;
    1633      697686 :                 Z_NEXT(q->val) = HT_HASH(target, nIndex);
    1634      697686 :                 HT_HASH(target, nIndex) = HT_IDX_TO_HASH(idx);
    1635             :         }
    1636     2692128 :         return 1;
    1637             : }
    1638             : 
    1639             : static zend_always_inline void zend_array_dup_packed_elements(HashTable *source, HashTable *target, int with_holes)
    1640             : {
    1641     1042875 :         Bucket *p = source->arData;
    1642     1042875 :         Bucket *q = target->arData;
    1643     1042875 :         Bucket *end = p + source->nNumUsed;
    1644             : 
    1645             :         do {
    1646     2837329 :                 if (!zend_array_dup_element(source, target, 0, p, q, 1, 1, with_holes)) {
    1647      842887 :                         if (with_holes) {
    1648      842887 :                                 ZVAL_UNDEF(&q->val);
    1649             :                         }
    1650             :                 }
    1651     2837329 :                 p++; q++;
    1652     2837329 :         } while (p != end);
    1653             : }
    1654             : 
    1655             : static zend_always_inline uint32_t zend_array_dup_elements(HashTable *source, HashTable *target, int static_keys, int with_holes)
    1656             : {
    1657       56588 :     uint32_t idx = 0;
    1658       56588 :         Bucket *p = source->arData;
    1659       56588 :         Bucket *q = target->arData;
    1660       56588 :         Bucket *end = p + source->nNumUsed;
    1661             : 
    1662             :         do {
    1663      689683 :                 if (!zend_array_dup_element(source, target, idx, p, q, 0, static_keys, with_holes)) {
    1664        1892 :                         uint32_t target_idx = idx;
    1665             : 
    1666        1892 :                         idx++; p++;
    1667       12750 :                         while (p != end) {
    1668       10858 :                                 if (zend_array_dup_element(source, target, target_idx, p, q, 0, static_keys, with_holes)) {
    1669        9895 :                                         if (source->nInternalPointer == idx) {
    1670           0 :                                                 target->nInternalPointer = target_idx;
    1671             :                                         }
    1672        9895 :                                         target_idx++; q++;
    1673             :                                 }
    1674       10858 :                                 idx++; p++;
    1675             :                         }
    1676        1892 :                         return target_idx;
    1677             :                 }
    1678      687791 :                 idx++; p++; q++;
    1679      687791 :         } while (p != end);
    1680       54696 :         return idx;
    1681             : }
    1682             : 
    1683     1262877 : ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
    1684             : {
    1685             :     uint32_t idx;
    1686             :         HashTable *target;
    1687             : 
    1688             :         IS_CONSISTENT(source);
    1689             : 
    1690     1262877 :         ALLOC_HASHTABLE(target);
    1691     1262877 :         GC_REFCOUNT(target) = 1;
    1692     1262877 :         GC_TYPE_INFO(target) = IS_ARRAY;
    1693             : 
    1694     1262877 :         target->nTableSize = source->nTableSize;
    1695     1262877 :         target->pDestructor = source->pDestructor;
    1696             : 
    1697     1262877 :         if (source->nNumUsed == 0) {
    1698      163400 :                 target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED|HASH_FLAG_PERSISTENT)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
    1699      163400 :                 target->nTableMask = HT_MIN_MASK;
    1700      163400 :                 target->nNumUsed = 0;
    1701      163400 :                 target->nNumOfElements = 0;
    1702      163400 :                 target->nNextFreeElement = 0;
    1703      163400 :                 target->nInternalPointer = HT_INVALID_IDX;
    1704      163400 :                 HT_SET_DATA_ADDR(target, &uninitialized_bucket);
    1705     1099477 :         } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) {
    1706          14 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1707          14 :                 target->nTableMask = source->nTableMask;
    1708          14 :                 target->nNumUsed = source->nNumUsed;
    1709          14 :                 target->nNumOfElements = source->nNumOfElements;
    1710          14 :                 target->nNextFreeElement = source->nNextFreeElement;
    1711          14 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1712          14 :                 target->nInternalPointer = source->nInternalPointer;
    1713          14 :                 memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source));
    1714          28 :                 if (target->nNumOfElements > 0 &&
    1715          14 :                     target->nInternalPointer == HT_INVALID_IDX) {
    1716           0 :                         idx = 0;
    1717           0 :                         while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1718           0 :                                 idx++;
    1719             :                         }
    1720           0 :                         target->nInternalPointer = idx;
    1721             :                 }
    1722     1099463 :         } else if (source->u.flags & HASH_FLAG_PACKED) {
    1723     1042875 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1724     1042875 :                 target->nTableMask = source->nTableMask;
    1725     1042875 :                 target->nNumUsed = source->nNumUsed;
    1726     1042875 :                 target->nNumOfElements = source->nNumOfElements;
    1727     1042875 :                 target->nNextFreeElement = source->nNextFreeElement;
    1728     1042875 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1729     1042875 :                 target->nInternalPointer = source->nInternalPointer;
    1730     1042875 :                 HT_HASH_RESET_PACKED(target);
    1731             : 
    1732     1042875 :                 if (target->nNumUsed == target->nNumOfElements) {
    1733             :                         zend_array_dup_packed_elements(source, target, 0);
    1734             :                 } else {
    1735             :                         zend_array_dup_packed_elements(source, target, 1);
    1736             :                 }
    1737     2085750 :                 if (target->nNumOfElements > 0 &&
    1738     1042875 :                     target->nInternalPointer == HT_INVALID_IDX) {
    1739           8 :                         idx = 0;
    1740          26 :                         while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1741           1 :                                 idx++;
    1742             :                         }
    1743           8 :                         target->nInternalPointer = idx;
    1744             :                 }
    1745             :         } else {
    1746       56588 :                 target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1747       56588 :                 target->nTableMask = source->nTableMask;
    1748       56588 :                 target->nNextFreeElement = source->nNextFreeElement;
    1749       56588 :                 target->nInternalPointer = HT_INVALID_IDX;
    1750       56588 :                 HT_SET_DATA_ADDR(target, emalloc(HT_SIZE(target)));
    1751       56588 :                 HT_HASH_RESET(target);
    1752             : 
    1753       56588 :                 if (target->u.flags & HASH_FLAG_STATIC_KEYS) {
    1754         910 :                         if (source->nNumUsed == source->nNumOfElements) {
    1755         910 :                                 idx = zend_array_dup_elements(source, target, 1, 0);
    1756             :                         } else {
    1757           0 :                                 idx = zend_array_dup_elements(source, target, 1, 1);
    1758             :                         }
    1759             :                 } else {
    1760       55678 :                         if (source->nNumUsed == source->nNumOfElements) {
    1761       55675 :                                 idx = zend_array_dup_elements(source, target, 0, 0);
    1762             :                         } else {
    1763           3 :                                 idx = zend_array_dup_elements(source, target, 0, 1);
    1764             :                         }
    1765             :                 }
    1766       56588 :                 target->nNumUsed = idx;
    1767       56588 :                 target->nNumOfElements = idx;
    1768       56588 :                 if (idx > 0 && target->nInternalPointer == HT_INVALID_IDX) {
    1769       56578 :                         target->nInternalPointer = 0;
    1770             :                 }
    1771             :         }
    1772     1262877 :         return target;
    1773             : }
    1774             : 
    1775             : 
    1776      189516 : ZEND_API void ZEND_FASTCALL _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
    1777             : {
    1778             :     uint32_t idx;
    1779             :         Bucket *p;
    1780             :         zval *t;
    1781      189516 :         uint32_t mode = (overwrite?HASH_UPDATE:HASH_ADD);
    1782             : 
    1783             :         IS_CONSISTENT(source);
    1784             :         IS_CONSISTENT(target);
    1785             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1786             : 
    1787     3264202 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1788     3074686 :                 p = source->arData + idx;
    1789     6149372 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1790     3074686 :                 if (p->key) {
    1791     3074649 :                         t = _zend_hash_add_or_update(target, p->key, &p->val, mode ZEND_FILE_LINE_RELAY_CC);
    1792     3074649 :                         if (t && pCopyConstructor) {
    1793     3074067 :                                 pCopyConstructor(t);
    1794             :                         }
    1795             :                 } else {
    1796          37 :                         if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h))) {
    1797          26 :                                 t = zend_hash_index_update(target, p->h, &p->val);
    1798          26 :                                 if (t && pCopyConstructor) {
    1799          26 :                                         pCopyConstructor(t);
    1800             :                                 }
    1801             :                         }
    1802             :                 }
    1803             :         }
    1804      189516 :         if (target->nNumOfElements > 0) {
    1805      189514 :                 idx = 0;
    1806      568542 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1807           0 :                         idx++;
    1808             :                 }
    1809      189514 :                 target->nInternalPointer = idx;
    1810             :         }
    1811      189516 : }
    1812             : 
    1813             : 
    1814           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)
    1815             : {
    1816             :         zend_hash_key hash_key;
    1817             : 
    1818           0 :         hash_key.h = p->h;
    1819           0 :         hash_key.key = p->key;
    1820           0 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1821             : }
    1822             : 
    1823             : 
    1824           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)
    1825             : {
    1826             :         uint32_t idx;
    1827             :         Bucket *p;
    1828             :         zval *t;
    1829             : 
    1830             :         IS_CONSISTENT(source);
    1831             :         IS_CONSISTENT(target);
    1832             :         HT_ASSERT(GC_REFCOUNT(target) == 1);
    1833             : 
    1834           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1835           0 :                 p = source->arData + idx;
    1836           0 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    1837           0 :                 if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
    1838           0 :                         t = zend_hash_update(target, p->key, &p->val);
    1839           0 :                         if (t && pCopyConstructor) {
    1840           0 :                                 pCopyConstructor(t);
    1841             :                         }
    1842             :                 }
    1843             :         }
    1844           0 :         if (target->nNumOfElements > 0) {
    1845           0 :                 idx = 0;
    1846           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1847           0 :                         idx++;
    1848             :                 }
    1849           0 :                 target->nInternalPointer = idx;
    1850             :         }
    1851           0 : }
    1852             : 
    1853             : 
    1854             : /* Returns the hash table data if found and NULL if not. */
    1855    53473622 : ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
    1856             : {
    1857             :         Bucket *p;
    1858             : 
    1859             :         IS_CONSISTENT(ht);
    1860             : 
    1861    53473622 :         p = zend_hash_find_bucket(ht, key);
    1862    53473622 :         return p ? &p->val : NULL;
    1863             : }
    1864             : 
    1865     1976862 : ZEND_API zval* ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
    1866             : {
    1867             :         zend_ulong h;
    1868             :         Bucket *p;
    1869             : 
    1870             :         IS_CONSISTENT(ht);
    1871             : 
    1872     1976862 :         h = zend_inline_hash_func(str, len);
    1873     1976862 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1874     1976862 :         return p ? &p->val : NULL;
    1875             : }
    1876             : 
    1877     2689996 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_exists(const HashTable *ht, zend_string *key)
    1878             : {
    1879             :         Bucket *p;
    1880             : 
    1881             :         IS_CONSISTENT(ht);
    1882             : 
    1883     2689996 :         p = zend_hash_find_bucket(ht, key);
    1884     2689996 :         return p ? 1 : 0;
    1885             : }
    1886             : 
    1887      902123 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
    1888             : {
    1889             :         zend_ulong h;
    1890             :         Bucket *p;
    1891             : 
    1892             :         IS_CONSISTENT(ht);
    1893             : 
    1894      902123 :         h = zend_inline_hash_func(str, len);
    1895      902123 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1896      902123 :         return p ? 1 : 0;
    1897             : }
    1898             : 
    1899     6072895 : ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
    1900             : {
    1901             :         Bucket *p;
    1902             : 
    1903             :         IS_CONSISTENT(ht);
    1904             : 
    1905     6072895 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1906     4886411 :                 if (h < ht->nNumUsed) {
    1907     4633986 :                         p = ht->arData + h;
    1908     9267972 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1909     4633667 :                                 return &p->val;
    1910             :                         }
    1911             :                 }
    1912      252744 :                 return NULL;
    1913             :         }
    1914             : 
    1915     1186484 :         p = zend_hash_index_find_bucket(ht, h);
    1916     1186484 :         return p ? &p->val : NULL;
    1917             : }
    1918             : 
    1919             : 
    1920     1558020 : ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h)
    1921             : {
    1922             :         Bucket *p;
    1923             : 
    1924             :         IS_CONSISTENT(ht);
    1925             : 
    1926     1558020 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1927          82 :                 if (h < ht->nNumUsed) {
    1928         104 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    1929          51 :                                 return 1;
    1930             :                         }
    1931             :                 }
    1932          31 :                 return 0;
    1933             :         }
    1934             : 
    1935     1557938 :         p = zend_hash_index_find_bucket(ht, h);
    1936     1557938 :         return p ? 1 : 0;
    1937             : }
    1938             : 
    1939             : 
    1940       19246 : ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1941             : {
    1942             :     uint32_t idx;
    1943             : 
    1944             :         IS_CONSISTENT(ht);
    1945             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    1946             : 
    1947       19737 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1948       39172 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1949       19095 :                         *pos = idx;
    1950       19095 :                         return;
    1951             :                 }
    1952             :         }
    1953         151 :         *pos = HT_INVALID_IDX;
    1954             : }
    1955             : 
    1956             : 
    1957             : /* This function will be extremely optimized by remembering
    1958             :  * the end of the list
    1959             :  */
    1960          47 : ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1961             : {
    1962             :         uint32_t idx;
    1963             : 
    1964             :         IS_CONSISTENT(ht);
    1965             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    1966             : 
    1967          47 :         idx = ht->nNumUsed;
    1968          94 :         while (idx > 0) {
    1969          45 :                 idx--;
    1970          90 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1971          45 :                         *pos = idx;
    1972          45 :                         return;
    1973             :                 }
    1974             :         }
    1975           2 :         *pos = HT_INVALID_IDX;
    1976             : }
    1977             : 
    1978             : 
    1979       69126 : ZEND_API int ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    1980             : {
    1981       69126 :         uint32_t idx = *pos;
    1982             : 
    1983             :         IS_CONSISTENT(ht);
    1984             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    1985             : 
    1986       69126 :         if (idx != HT_INVALID_IDX) {
    1987             :                 while (1) {
    1988       69176 :                         idx++;
    1989       69176 :                         if (idx >= ht->nNumUsed) {
    1990       16294 :                                 *pos = HT_INVALID_IDX;
    1991       16294 :                                 return SUCCESS;
    1992             :                         }
    1993      105764 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1994       52797 :                                 *pos = idx;
    1995       52797 :                                 return SUCCESS;
    1996             :                         }
    1997          85 :                 }
    1998             :         } else {
    1999          35 :                 return FAILURE;
    2000             :         }
    2001             : }
    2002             : 
    2003          21 : ZEND_API int ZEND_FASTCALL zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    2004             : {
    2005          21 :         uint32_t idx = *pos;
    2006             : 
    2007             :         IS_CONSISTENT(ht);
    2008             :         HT_ASSERT(ht->nInternalPointer != &pos || GC_REFCOUNT(ht) == 1);
    2009             : 
    2010          21 :         if (idx != HT_INVALID_IDX) {
    2011          38 :                 while (idx > 0) {
    2012          14 :                         idx--;
    2013          28 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    2014          14 :                                 *pos = idx;
    2015          14 :                                 return SUCCESS;
    2016             :                         }
    2017             :                 }
    2018           5 :                 *pos = HT_INVALID_IDX;
    2019           5 :                 return SUCCESS;
    2020             :         } else {
    2021           2 :                 return FAILURE;
    2022             :         }
    2023             : }
    2024             : 
    2025             : 
    2026             : /* This function should be made binary safe  */
    2027       12773 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, HashPosition *pos)
    2028             : {
    2029       12773 :         uint32_t idx = *pos;
    2030             :         Bucket *p;
    2031             : 
    2032             :         IS_CONSISTENT(ht);
    2033       12773 :         if (idx != HT_INVALID_IDX) {
    2034       12342 :                 p = ht->arData + idx;
    2035       12342 :                 if (p->key) {
    2036       11008 :                         *str_index = p->key;
    2037       11008 :                         return HASH_KEY_IS_STRING;
    2038             :                 } else {
    2039        1334 :                         *num_index = p->h;
    2040        1334 :                         return HASH_KEY_IS_LONG;
    2041             :                 }
    2042             :         }
    2043         431 :         return HASH_KEY_NON_EXISTENT;
    2044             : }
    2045             : 
    2046        4403 : ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    2047             : {
    2048        4403 :         uint32_t idx = *pos;
    2049             :         Bucket *p;
    2050             : 
    2051             :         IS_CONSISTENT(ht);
    2052        4403 :         if (idx == HT_INVALID_IDX) {
    2053          52 :                 ZVAL_NULL(key);
    2054             :         } else {
    2055        4351 :                 p = ht->arData + idx;
    2056        4351 :                 if (p->key) {
    2057         670 :                         ZVAL_STR_COPY(key, p->key);
    2058             :                 } else {
    2059        3681 :                         ZVAL_LONG(key, p->h);
    2060             :                 }
    2061             :         }
    2062        4403 : }
    2063             : 
    2064       78645 : ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    2065             : {
    2066       78645 :     uint32_t idx = *pos;
    2067             :         Bucket *p;
    2068             : 
    2069             :         IS_CONSISTENT(ht);
    2070       78645 :         if (idx != HT_INVALID_IDX) {
    2071       63418 :                 p = ht->arData + idx;
    2072       63418 :                 if (p->key) {
    2073       60798 :                         return HASH_KEY_IS_STRING;
    2074             :                 } else {
    2075        2620 :                         return HASH_KEY_IS_LONG;
    2076             :                 }
    2077             :         }
    2078       15227 :         return HASH_KEY_NON_EXISTENT;
    2079             : }
    2080             : 
    2081             : 
    2082       67722 : ZEND_API zval* ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    2083             : {
    2084       67722 :         uint32_t idx = *pos;
    2085             :         Bucket *p;
    2086             : 
    2087             :         IS_CONSISTENT(ht);
    2088       67722 :         if (idx != HT_INVALID_IDX) {
    2089       66806 :                 p = ht->arData + idx;
    2090       66806 :                 return &p->val;
    2091             :         } else {
    2092         916 :                 return NULL;
    2093             :         }
    2094             : }
    2095             : 
    2096       86765 : ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q)
    2097             : {
    2098             :         zval val;
    2099             :         zend_ulong h;
    2100             :         zend_string *key;
    2101             : 
    2102       86765 :         ZVAL_COPY_VALUE(&val, &p->val);
    2103       86765 :         h = p->h;
    2104       86765 :         key = p->key;
    2105             : 
    2106       86765 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2107       86765 :         p->h = q->h;
    2108       86765 :         p->key = q->key;
    2109             : 
    2110       86765 :         ZVAL_COPY_VALUE(&q->val, &val);
    2111       86765 :         q->h = h;
    2112       86765 :         q->key = key;
    2113       86765 : }
    2114             : 
    2115       69193 : ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q)
    2116             : {
    2117             :         zval val;
    2118             : 
    2119       69193 :         ZVAL_COPY_VALUE(&val, &p->val);
    2120       69193 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2121       69193 :         ZVAL_COPY_VALUE(&q->val, &val);
    2122       69193 : }
    2123             : 
    2124        1082 : ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q)
    2125             : {
    2126             :         zval val;
    2127             :         zend_ulong h;
    2128             : 
    2129        1082 :         ZVAL_COPY_VALUE(&val, &p->val);
    2130        1082 :         h = p->h;
    2131             : 
    2132        1082 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    2133        1082 :         p->h = q->h;
    2134             : 
    2135        1082 :         ZVAL_COPY_VALUE(&q->val, &val);
    2136        1082 :         q->h = h;
    2137        1082 : }
    2138             : 
    2139       22749 : ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber)
    2140             : {
    2141             :         Bucket *p;
    2142             :         uint32_t i, j;
    2143             : 
    2144             :         IS_CONSISTENT(ht);
    2145             :         HT_ASSERT(GC_REFCOUNT(ht) == 1);
    2146             : 
    2147       22749 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    2148         293 :                 return SUCCESS;
    2149             :         }
    2150             : 
    2151       22456 :         if (ht->nNumUsed == ht->nNumOfElements) {
    2152       22363 :                 i = ht->nNumUsed;
    2153             :         } else {
    2154         679 :                 for (j = 0, i = 0; j < ht->nNumUsed; j++) {
    2155         586 :                         p = ht->arData + j;
    2156        1172 :                         if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    2157         475 :                         if (i != j) {
    2158         459 :                                 ht->arData[i] = *p;
    2159             :                         }
    2160         475 :                         i++;
    2161             :                 }
    2162             :         }
    2163             : 
    2164       44614 :         sort((void *)ht->arData, i, sizeof(Bucket), compar,
    2165             :                         (swap_func_t)(renumber? zend_hash_bucket_renum_swap :
    2166       22158 :                                 ((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
    2167             : 
    2168       22455 :         HANDLE_BLOCK_INTERRUPTIONS();
    2169       22455 :         ht->nNumUsed = i;
    2170       22455 :         ht->nInternalPointer = 0;
    2171             : 
    2172       22455 :         if (renumber) {
    2173       15915 :                 for (j = 0; j < i; j++) {
    2174       15618 :                         p = ht->arData + j;
    2175       15618 :                         p->h = j;
    2176       15618 :                         if (p->key) {
    2177         231 :                                 zend_string_release(p->key);
    2178         231 :                                 p->key = NULL;
    2179             :                         }
    2180             :                 }
    2181             : 
    2182         297 :                 ht->nNextFreeElement = i;
    2183             :         }
    2184       22455 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    2185         495 :                 if (!renumber) {
    2186         244 :                         zend_hash_packed_to_hash(ht);
    2187             :                 }
    2188             :         } else {
    2189       21960 :                 if (renumber) {
    2190          46 :                         void *old_data = HT_GET_DATA_ADDR(ht);
    2191          46 :                         Bucket *old_buckets = ht->arData;
    2192             : 
    2193          46 :                         ht->u.flags |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
    2194          46 :                         ht->nTableMask = HT_MIN_MASK;
    2195          92 :                         HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT & HASH_FLAG_PERSISTENT));
    2196          46 :                         memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
    2197          46 :                         pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT & HASH_FLAG_PERSISTENT);
    2198          46 :                         HT_HASH_RESET_PACKED(ht);
    2199             :                 } else {
    2200       21914 :                         zend_hash_rehash(ht);
    2201             :                 }
    2202             :         }
    2203             : 
    2204       22455 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2205             : 
    2206       22455 :         return SUCCESS;
    2207             : }
    2208             : 
    2209             : static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered) {
    2210             :         uint32_t idx1, idx2;
    2211             : 
    2212         893 :         if (ht1->nNumOfElements != ht2->nNumOfElements) {
    2213         305 :                 return ht1->nNumOfElements > ht2->nNumOfElements ? 1 : -1;
    2214             :         }
    2215             : 
    2216        4476 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    2217        4068 :                 Bucket *p1 = ht1->arData + idx1, *p2;
    2218             :                 zval *pData1, *pData2;
    2219             :                 int result;
    2220             : 
    2221        8136 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    2222        4055 :                 if (ordered) {
    2223             :                         while (1) {
    2224             :                                 ZEND_ASSERT(idx2 != ht2->nNumUsed);
    2225        1064 :                                 p2 = ht2->arData + idx2;
    2226        2128 :                                 if (Z_TYPE(p2->val) != IS_UNDEF) break;
    2227           1 :                                 idx2++;
    2228             :                         }
    2229        1063 :                         if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
    2230         331 :                                 if (p1->h != p2->h) {
    2231           2 :                                         return p1->h > p2->h ? 1 : -1;
    2232             :                                 }
    2233         732 :                         } else if (p1->key != NULL && p2->key != NULL) { /* string indices */
    2234         731 :                                 if (p1->key->len != p2->key->len) {
    2235           0 :                                         return p1->key->len > p2->key->len ? 1 : -1;
    2236             :                                 }
    2237             : 
    2238         731 :                                 result = memcmp(p1->key->val, p2->key->val, p1->key->len);
    2239         731 :                                 if (result != 0) {
    2240           0 :                                         return result;
    2241             :                                 }
    2242             :                         } else {
    2243             :                                 /* Mixed key types: A string key is considered as larger */
    2244           1 :                                 return p1->key != NULL ? 1 : -1;
    2245             :                         }
    2246        1060 :                         pData2 = &p2->val;
    2247        1060 :                         idx2++;
    2248             :                 } else {
    2249        2992 :                         if (p1->key == NULL) { /* numeric index */
    2250         485 :                                 pData2 = zend_hash_index_find(ht2, p1->h);
    2251         485 :                                 if (pData2 == NULL) {
    2252           2 :                                         return 1;
    2253             :                                 }
    2254             :                         } else { /* string index */
    2255        2507 :                                 pData2 = zend_hash_find(ht2, p1->key);
    2256        2507 :                                 if (pData2 == NULL) {
    2257          11 :                                         return 1;
    2258             :                                 }
    2259             :                         }
    2260             :                 }
    2261             : 
    2262        4039 :                 pData1 = &p1->val;
    2263        4039 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    2264         129 :                         pData1 = Z_INDIRECT_P(pData1);
    2265             :                 }
    2266        4039 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    2267         129 :                         pData2 = Z_INDIRECT_P(pData2);
    2268             :                 }
    2269             : 
    2270        4039 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    2271           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    2272           0 :                                 return -1;
    2273             :                         }
    2274        4039 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    2275           0 :                         return 1;
    2276             :                 } else {
    2277        4039 :                         result = compar(pData1, pData2);
    2278        4039 :                         if (result != 0) {
    2279         164 :                                 return result;
    2280             :                         }
    2281             :                 }
    2282             :         }
    2283             : 
    2284         408 :         return 0;
    2285             : }
    2286             : 
    2287         893 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
    2288             : {
    2289             :         int result;
    2290             :         IS_CONSISTENT(ht1);
    2291             :         IS_CONSISTENT(ht2);
    2292             : 
    2293         893 :         HASH_PROTECT_RECURSION(ht1);
    2294         893 :         HASH_PROTECT_RECURSION(ht2);
    2295        1786 :         result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
    2296         893 :         HASH_UNPROTECT_RECURSION(ht1);
    2297         893 :         HASH_UNPROTECT_RECURSION(ht2);
    2298             : 
    2299         893 :         return result;
    2300             : }
    2301             : 
    2302             : 
    2303          82 : ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
    2304             : {
    2305             :         uint32_t idx;
    2306             :         Bucket *p, *res;
    2307             : 
    2308             :         IS_CONSISTENT(ht);
    2309             : 
    2310          82 :         if (ht->nNumOfElements == 0 ) {
    2311           4 :                 return NULL;
    2312             :         }
    2313             : 
    2314          78 :         idx = 0;
    2315             :         while (1) {
    2316          78 :                 if (idx == ht->nNumUsed) {
    2317           0 :                         return NULL;
    2318             :                 }
    2319         156 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
    2320           0 :                 idx++;
    2321           0 :         }
    2322          78 :         res = ht->arData + idx;
    2323         376 :         for (; idx < ht->nNumUsed; idx++) {
    2324         298 :                 p = ht->arData + idx;
    2325         596 :                 if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
    2326             : 
    2327         298 :                 if (flag) {
    2328         229 :                         if (compar(res, p) < 0) { /* max */
    2329          20 :                                 res = p;
    2330             :                         }
    2331             :                 } else {
    2332          69 :                         if (compar(res, p) > 0) { /* min */
    2333           6 :                                 res = p;
    2334             :                         }
    2335             :                 }
    2336             :         }
    2337          78 :         return &res->val;
    2338             : }
    2339             : 
    2340      383118 : ZEND_API int ZEND_FASTCALL _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    2341             : {
    2342      383118 :         register const char *tmp = key;
    2343             : 
    2344      383118 :         const char *end = key + length;
    2345             :         ZEND_ASSERT(*end == '\0');
    2346             : 
    2347      383118 :         if (*tmp == '-') {
    2348          59 :                 tmp++;
    2349             :         }
    2350             : 
    2351      746095 :         if ((*tmp == '0' && length > 1) /* numbers with leading zeros */
    2352      362977 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    2353             :          || (SIZEOF_ZEND_LONG == 4 &&
    2354             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    2355             :              *tmp > '2')) { /* overflow */
    2356       20168 :                 return 0;
    2357             :         }
    2358      362950 :         *idx = (*tmp - '0');
    2359             :         while (1) {
    2360     1444635 :                 ++tmp;
    2361     1444635 :                 if (tmp == end) {
    2362      362687 :                         if (*key == '-') {
    2363          28 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    2364           0 :                                         return 0;
    2365             :                                 }
    2366          28 :                                 *idx = 0 - *idx;
    2367      362659 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    2368           0 :                                 return 0;
    2369             :                         }
    2370      362687 :                         return 1;
    2371             :                 }
    2372     2163633 :                 if (*tmp <= '9' && *tmp >= '0') {
    2373     1081685 :                         *idx = (*idx * 10) + (*tmp - '0');
    2374             :                 } else {
    2375         263 :                         return 0;
    2376             :                 }
    2377     1081685 :         }
    2378             : }
    2379             : 
    2380             : /*
    2381             :  * Local variables:
    2382             :  * tab-width: 4
    2383             :  * c-basic-offset: 4
    2384             :  * indent-tabs-mode: t
    2385             :  * End:
    2386             :  */

Generated by: LCOV version 1.10

Generated at Sat, 27 Jun 2015 09:41:07 +0000 (7 days ago)

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