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: 867 972 89.2 %
Date: 2014-12-13 Functions: 59 67 88.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 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             : #if ZEND_DEBUG
      27             : /*
      28             : #define HASH_MASK_CONSISTENCY   0x60
      29             : */
      30             : #define HT_OK                                   0x00
      31             : #define HT_IS_DESTROYING                0x20
      32             : #define HT_DESTROYED                    0x40
      33             : #define HT_CLEANING                             0x60
      34             : 
      35             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      36             : {
      37             :         if ((ht->u.flags & HASH_MASK_CONSISTENCY) == HT_OK) {
      38             :                 return;
      39             :         }
      40             :         switch ((ht->u.flags & HASH_MASK_CONSISTENCY)) {
      41             :                 case HT_IS_DESTROYING:
      42             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      43             :                         break;
      44             :                 case HT_DESTROYED:
      45             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      46             :                         break;
      47             :                 case HT_CLEANING:
      48             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      49             :                         break;
      50             :                 default:
      51             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      52             :                         break;
      53             :         }
      54             :         zend_bailout();
      55             : }
      56             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      57             : #define SET_INCONSISTENT(n) do { \
      58             :                 (ht)->u.flags |= n; \
      59             :         } while (0)
      60             : #else
      61             : #define IS_CONSISTENT(a)
      62             : #define SET_INCONSISTENT(n)
      63             : #endif
      64             : 
      65             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      66             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      67             :                 if ((ht)->u.flags >= (3 << 8)) {                                                                                            \
      68             :                         zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");\
      69             :                 }                                                                                                                                                               \
      70             :                 ZEND_HASH_INC_APPLY_COUNT(ht);                                                                                                  \
      71             :         }
      72             : 
      73             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      74             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      75             :                 ZEND_HASH_DEC_APPLY_COUNT(ht);                                                                                                  \
      76             :         }
      77             : 
      78             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
      79             :         if ((ht)->nNumUsed >= (ht)->nTableSize) {              \
      80             :                 zend_hash_do_resize(ht);                                        \
      81             :         }
      82             : 
      83             : static void zend_hash_do_resize(HashTable *ht);
      84             : 
      85             : #define CHECK_INIT(ht, packed) do {                                                                                             \
      86             :         if (UNEXPECTED((ht)->nTableMask == 0)) {                                                     \
      87             :                 if (packed) { \
      88             :                         (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT);        \
      89             :                         (ht)->u.flags |= HASH_FLAG_PACKED; \
      90             :                 } else { \
      91             :                         (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT);     \
      92             :                         (ht)->arHash = (uint32_t*)((ht)->arData + (ht)->nTableSize);   \
      93             :                         memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(uint32_t));   \
      94             :                 } \
      95             :                 (ht)->nTableMask = (ht)->nTableSize - 1;                                          \
      96             :         }                                                                                                                                       \
      97             : } while (0)
      98             :  
      99             : static const uint32_t uninitialized_bucket = {INVALID_IDX};
     100             : 
     101    16844286 : ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     102             : {
     103             :         /* Use big enough power of 2 */
     104             : #if defined(PHP_WIN32) && !defined(__clang__)
     105             :         if (nSize <= 8) {
     106             :                 ht->nTableSize = 8;
     107             :         } else if (nSize >= 0x80000000) {
     108             :                 /* prevent overflow */
     109             :                 ht->nTableSize = 0x80000000;
     110             :         } else {
     111             :                 ht->nTableSize = 1U << __lzcnt(nSize);
     112             :                 if (ht->nTableSize < nSize) {
     113             :                         ht->nTableSize <<= 1;
     114             :                 }
     115             :         }
     116             : #else
     117             :         /* size should be between 8 and 0x80000000 */
     118    16844286 :         nSize = (nSize <= 8 ? 8 : (nSize >= 0x80000000 ? 0x80000000 : nSize));
     119             : # if defined(__GNUC__)
     120    16844286 :         ht->nTableSize =  0x2 << (__builtin_clz(nSize - 1) ^ 0x1f);
     121             : # else
     122             :         nSize -= 1;
     123             :         nSize |= (nSize >> 1);
     124             :         nSize |= (nSize >> 2);
     125             :         nSize |= (nSize >> 4);
     126             :         nSize |= (nSize >> 8);
     127             :         nSize |= (nSize >> 16);
     128             :         ht->nTableSize = nSize + 1;
     129             : # endif
     130             : #endif
     131             : 
     132    16844286 :         ht->nTableMask = 0;  /* 0 means that ht->arBuckets is uninitialized */
     133    16844286 :         ht->nNumUsed = 0;
     134    16844286 :         ht->nNumOfElements = 0;
     135    16844286 :         ht->nNextFreeElement = 0;
     136    16844286 :         ht->arData = NULL;
     137    16844286 :         ht->arHash = (uint32_t*)&uninitialized_bucket;
     138    16844286 :         ht->pDestructor = pDestructor;
     139    16844286 :         ht->nInternalPointer = INVALID_IDX;
     140    16844286 :         ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION;
     141    16844286 : }
     142             : 
     143       37191 : static void zend_hash_packed_grow(HashTable *ht)
     144             : {
     145       37191 :         HANDLE_BLOCK_INTERRUPTIONS();
     146       37191 :         ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     147       37191 :         ht->nTableSize = (ht->nTableSize << 1);
     148       37191 :         ht->nTableMask = ht->nTableSize - 1;
     149       37191 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     150       37191 : }
     151             : 
     152       69397 : ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed)
     153             : {
     154             :         IS_CONSISTENT(ht);
     155             : 
     156       69397 :         CHECK_INIT(ht, packed);
     157       69397 : }
     158             : 
     159       27429 : ZEND_API void zend_hash_packed_to_hash(HashTable *ht)
     160             : {
     161       27429 :         HANDLE_BLOCK_INTERRUPTIONS();
     162       27429 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     163       27429 :         ht->arData = (Bucket *) safe_perealloc(ht->arData, ht->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     164       27429 :         ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
     165       27429 :         zend_hash_rehash(ht);
     166       27429 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     167       27429 : }
     168             : 
     169          15 : ZEND_API void zend_hash_to_packed(HashTable *ht)
     170             : {
     171          15 :         HANDLE_BLOCK_INTERRUPTIONS();
     172          15 :         ht->u.flags |= HASH_FLAG_PACKED;
     173          15 :         ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket));
     174          15 :         ht->arHash = (uint32_t*)&uninitialized_bucket;
     175          15 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     176          15 : }
     177             : 
     178    11219641 : ZEND_API void _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
     179             : {
     180    11219641 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_CC);
     181    11219641 :         if (!bApplyProtection) {
     182    11219641 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     183             :         }
     184    11219641 : }
     185             : 
     186             : 
     187           0 : ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     188             : {
     189           0 :         if (bApplyProtection) {
     190           0 :                 ht->u.flags |= HASH_FLAG_APPLY_PROTECTION;
     191             :         } else {
     192           0 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     193             :         }
     194           0 : }
     195             : 
     196             : static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
     197             : {
     198             :         zend_ulong h;
     199             :         uint32_t nIndex;
     200             :         uint32_t idx;
     201             :         Bucket *p;
     202             : 
     203   269116120 :         h = zend_string_hash_val(key);
     204   269116120 :         nIndex = h & ht->nTableMask;
     205   269116120 :         idx = ht->arHash[nIndex];
     206   417563037 :         while (idx != INVALID_IDX) {
     207   162440644 :                 p = ht->arData + idx;
     208   332103823 :                 if ((p->key == key) || /* check for the the same interned string */
     209   153749364 :                         (p->h == h &&
     210     5304605 :                          p->key &&
     211     5304605 :                          p->key->len == key->len &&
     212     5304605 :                          memcmp(p->key->val, key->val, key->len) == 0)) {
     213    13993727 :                         return p;
     214             :                 }
     215   148446917 :                 idx = Z_NEXT(p->val);
     216             :         }
     217   255122393 :         return NULL;
     218             : }
     219             : 
     220             : static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
     221             : {
     222             :         uint32_t nIndex;
     223             :         uint32_t idx;
     224             :         Bucket *p;
     225             : 
     226     3461751 :         nIndex = h & ht->nTableMask;
     227     3461751 :         idx = ht->arHash[nIndex];
     228     4273978 :         while (idx != INVALID_IDX) {
     229             :                 ZEND_ASSERT(idx < ht->nTableSize);
     230     3377710 :                 p = ht->arData + idx;
     231    11074210 :                 if ((p->h == h) 
     232             :                          && p->key
     233     5131000 :                          && (p->key->len == len)
     234     2565500 :                          && !memcmp(p->key->val, str, len)) {
     235     2565483 :                         return p;
     236             :                 }
     237      812227 :                 idx = Z_NEXT(p->val);
     238             :         }
     239      896268 :         return NULL;
     240             : }
     241             : 
     242             : static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
     243             : {
     244             :         uint32_t nIndex;
     245             :         uint32_t idx;
     246             :         Bucket *p;
     247             : 
     248     4093388 :         nIndex = h & ht->nTableMask;
     249     4093388 :         idx = ht->arHash[nIndex];
     250     5428200 :         while (idx != INVALID_IDX) {
     251             :                 ZEND_ASSERT(idx < ht->nTableSize);
     252     2335791 :                 p = ht->arData + idx;
     253     2335791 :                 if (p->h == h && !p->key) {
     254     1000979 :                         return p;
     255             :                 }
     256     1334812 :                 idx = Z_NEXT(p->val);
     257             :         }
     258     3092409 :         return NULL;
     259             : }
     260             : 
     261             : 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)
     262             : {
     263             :         zend_ulong h;
     264             :         uint32_t nIndex;
     265             :         uint32_t idx;
     266             :         Bucket *p;
     267             : #ifdef ZEND_SIGNALS
     268             :         TSRMLS_FETCH();
     269             : #endif
     270             : 
     271             :         IS_CONSISTENT(ht);
     272             : 
     273   252478390 :         if (UNEXPECTED(ht->nTableMask == 0)) {
     274     6733972 :                 CHECK_INIT(ht, 0);
     275             :                 goto add_to_hash; 
     276   245744418 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     277       26406 :                 zend_hash_packed_to_hash(ht);
     278   245718012 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     279   217329869 :                 p = zend_hash_find_bucket(ht, key);
     280             : 
     281   217329869 :                 if (p) {
     282             :                         zval *data;
     283             : 
     284     1030822 :                         if (flag & HASH_ADD) {
     285      257711 :                                 return NULL;
     286             :                         }
     287             :                         ZEND_ASSERT(&p->val != pData);
     288      773111 :                         data = &p->val;
     289      828246 :                         if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     290         258 :                                 data = Z_INDIRECT_P(data);
     291             :                         }
     292      773111 :                         HANDLE_BLOCK_INTERRUPTIONS();
     293      773111 :                         if (ht->pDestructor) {
     294      731495 :                                 ht->pDestructor(data);
     295             :                         }
     296      773111 :                         ZVAL_COPY_VALUE(data, pData);
     297      773111 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     298      773111 :                         return data;
     299             :                 }
     300             :         }
     301             :         
     302   244713596 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     303             : 
     304             : add_to_hash:
     305   251447568 :         HANDLE_BLOCK_INTERRUPTIONS();
     306   251447568 :         idx = ht->nNumUsed++;
     307   251447568 :         ht->nNumOfElements++;
     308   251447568 :         if (ht->nInternalPointer == INVALID_IDX) {
     309     6875953 :                 ht->nInternalPointer = idx;
     310             :         }
     311   251447568 :         p = ht->arData + idx; 
     312   251447568 :         p->h = h = zend_string_hash_val(key);
     313   251447568 :         p->key = key;
     314             :         zend_string_addref(key);
     315   251447568 :         ZVAL_COPY_VALUE(&p->val, pData);
     316   251447568 :         nIndex = h & ht->nTableMask;
     317   251447568 :         Z_NEXT(p->val) = ht->arHash[nIndex];
     318   251447568 :         ht->arHash[nIndex] = idx;
     319   251447568 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     320             : 
     321   251447568 :         return &p->val;
     322             : }
     323             : 
     324     3012311 : ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     325             : {
     326     3012311 :         return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     327             : }
     328             : 
     329   139836753 : ZEND_API zval *_zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     330             : {
     331   139836753 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     332             : }
     333             : 
     334    53446767 : ZEND_API zval *_zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     335             : {
     336    53446767 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     337             : }
     338             : 
     339        1136 : ZEND_API zval *_zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     340             : {
     341        1136 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     342             : }
     343             : 
     344    29471853 : ZEND_API zval *_zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     345             : {
     346    29471853 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     347             : }
     348             : 
     349           0 : ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     350             : {
     351           0 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     352           0 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_CC);
     353             :         zend_string_release(key);
     354           0 :         return ret;
     355             : }
     356             : 
     357    12721889 : ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     358             : {
     359    25443778 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     360    12721889 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC);
     361             :         zend_string_release(key);
     362    12721889 :         return ret;
     363             : }
     364             : 
     365     1282509 : ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     366             : {
     367     2565018 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     368     1282509 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC);
     369             :         zend_string_release(key);
     370     1282509 :         return ret;
     371             : }
     372             : 
     373    12702390 : ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     374             : {
     375    25404780 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     376    12702390 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC);
     377             :         zend_string_release(key);
     378    12702390 :         return ret;
     379             : }
     380             : 
     381        2782 : ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     382             : {
     383        5564 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     384        2782 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_CC);
     385             :         zend_string_release(key);
     386        2782 :         return ret;
     387             : }
     388             : 
     389           0 : ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     390             : {
     391             :         
     392             :         zval dummy;
     393             : 
     394           0 :         ZVAL_NULL(&dummy);
     395           0 :         return zend_hash_index_add(ht, h, &dummy);
     396             : }
     397             : 
     398         226 : ZEND_API zval *zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     399             : {
     400             :         
     401             :         zval dummy;
     402             : 
     403         226 :         ZVAL_NULL(&dummy);
     404         226 :         return zend_hash_add(ht, key, &dummy);
     405             : }
     406             : 
     407      517032 : ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
     408             : {
     409             :         
     410             :         zval dummy;
     411             : 
     412      517032 :         ZVAL_NULL(&dummy);
     413      517032 :         return zend_hash_str_add(ht, str, len, &dummy);
     414             : }
     415             : 
     416             : 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)
     417             : {
     418             :         uint32_t nIndex;
     419             :         uint32_t idx;
     420             :         Bucket *p;
     421             : #ifdef ZEND_SIGNALS
     422             :         TSRMLS_FETCH();
     423             : #endif
     424             : 
     425             :         IS_CONSISTENT(ht);
     426             : 
     427     7664150 :         if (UNEXPECTED(ht->nTableMask == 0)) {
     428     2043759 :                 CHECK_INIT(ht, h < ht->nTableSize);
     429     2043759 :                 if (h < ht->nTableSize) {
     430     1943115 :                         p = ht->arData + h;
     431             :                         goto add_to_packed;
     432             :                 }
     433             :                 goto add_to_hash;
     434     5620391 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     435     3720120 :                 if (h < ht->nNumUsed) {
     436        3800 :                         p = ht->arData + h;
     437        7600 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     438        3644 :                                 if (flag & HASH_ADD) {
     439          24 :                                         return NULL;
     440             :                                 }
     441        3620 :                                 if (ht->pDestructor) {
     442        3620 :                                         ht->pDestructor(&p->val);
     443             :                                 }
     444        3620 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     445        3620 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     446           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     447             :                                 }
     448        3620 :                                 return &p->val;
     449             :                         } else { /* we have to keep the order :( */
     450             :                                 goto convert_to_hash;
     451             :                         }
     452     3716320 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     453     3678523 :                         p = ht->arData + h;
     454       75518 :                 } else if (h < ht->nTableSize * 2 &&
     455       37721 :                                    ht->nTableSize - ht->nNumOfElements < ht->nTableSize / 2) {
     456       37191 :                         zend_hash_packed_grow(ht);
     457       37191 :                         p = ht->arData + h;
     458             :                 } else {
     459             :                         goto convert_to_hash;
     460             :                 }
     461             : 
     462             : add_to_packed:
     463     5658829 :                 HANDLE_BLOCK_INTERRUPTIONS();
     464             :                 /* incremental initialization of empty Buckets */
     465     5658829 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     466      452027 :                         ht->nNumUsed = h + 1;
     467     5206802 :                 } else if (h >= ht->nNumUsed) {
     468     5206802 :                         if (h > ht->nNumUsed) {
     469      896768 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     470     1798220 :                                 while (q != p) {
     471      901452 :                                         ZVAL_UNDEF(&q->val);
     472      901452 :                                         q++;
     473             :                                 }
     474             :                         }
     475     5206802 :                         ht->nNumUsed = h + 1;
     476             :                 }
     477     5658829 :                 ht->nNumOfElements++;
     478     5658829 :                 if (ht->nInternalPointer == INVALID_IDX) {
     479     1943139 :                         ht->nInternalPointer = h;
     480             :                 }
     481     5658829 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     482     5658817 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     483             :                 }
     484     5658829 :                 p->h = h;
     485     5658829 :                 p->key = NULL;
     486     5658829 :                 ZVAL_COPY_VALUE(&p->val, pData);
     487             : 
     488     5658829 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     489             : 
     490     5658829 :                 return &p->val;
     491             : 
     492             : convert_to_hash:
     493         762 :                 zend_hash_packed_to_hash(ht);
     494     1900271 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     495     1420179 :                 p = zend_hash_index_find_bucket(ht, h);
     496     1420179 :                 if (p) {
     497       10251 :                         if (flag & HASH_ADD) {
     498           5 :                                 return NULL;
     499             :                         }
     500             :                         ZEND_ASSERT(&p->val != pData);
     501       10246 :                         HANDLE_BLOCK_INTERRUPTIONS();
     502       10246 :                         if (ht->pDestructor) {
     503       10201 :                                 ht->pDestructor(&p->val);
     504             :                         }
     505       10246 :                         ZVAL_COPY_VALUE(&p->val, pData);
     506       10246 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     507       10246 :                         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     508           1 :                                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     509             :                         }
     510       10246 :                         return &p->val;
     511             :                 }
     512             :         }
     513             : 
     514     1890782 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     515             : 
     516             : add_to_hash:
     517     1991426 :         HANDLE_BLOCK_INTERRUPTIONS();
     518     1991426 :         idx = ht->nNumUsed++;
     519     1991426 :         ht->nNumOfElements++;
     520     1991426 :         if (ht->nInternalPointer == INVALID_IDX) {
     521      168715 :                 ht->nInternalPointer = idx;
     522             :         }
     523     1991426 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     524      615890 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     525             :         }
     526     1991426 :         p = ht->arData + idx;
     527     1991426 :         p->h = h;
     528     1991426 :         p->key = NULL;
     529     1991426 :         nIndex = h & ht->nTableMask;
     530     1991426 :         ZVAL_COPY_VALUE(&p->val, pData);
     531     1991426 :         Z_NEXT(p->val) = ht->arHash[nIndex];
     532     1991426 :         ht->arHash[nIndex] = idx;
     533     1991426 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     534             : 
     535     1991426 :         return &p->val;
     536             : }
     537             : 
     538           0 : ZEND_API zval *_zend_hash_index_add_or_update(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     539             : {
     540           0 :         return _zend_hash_index_add_or_update_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
     541             : }
     542             : 
     543         100 : ZEND_API zval *_zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     544             : {
     545         100 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     546             : }
     547             : 
     548      915073 : ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     549             : {
     550      915073 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     551             : }
     552             : 
     553     2431304 : ZEND_API zval *_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     554             : {
     555     2431304 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     556             : }
     557             : 
     558     3865382 : ZEND_API zval *_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     559             : {
     560     7730764 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     561             : }
     562             : 
     563      452291 : ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     564             : {
     565      904582 :         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);
     566             : }
     567             : 
     568     6318848 : static void zend_hash_do_resize(HashTable *ht)
     569             : {
     570             : #ifdef ZEND_SIGNALS
     571             :         TSRMLS_FETCH();
     572             : #endif
     573             : 
     574             :         IS_CONSISTENT(ht);
     575             : 
     576     6318848 :         if (ht->nNumUsed < ht->nNumOfElements) {
     577           0 :                 HANDLE_BLOCK_INTERRUPTIONS();
     578           0 :                 zend_hash_rehash(ht);
     579           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     580     6318848 :         } else if ((ht->nTableSize << 1) > 0) {     /* Let's double the table size */
     581     6318848 :                 HANDLE_BLOCK_INTERRUPTIONS();
     582     6318848 :                 ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     583     6318848 :                 ht->arHash = (uint32_t*)(ht->arData + (ht->nTableSize << 1));
     584     6318848 :                 ht->nTableSize = (ht->nTableSize << 1);
     585     6318848 :                 ht->nTableMask = ht->nTableSize - 1;
     586     6318848 :                 zend_hash_rehash(ht);
     587     6318848 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     588             :         }
     589     6318848 : }
     590             : 
     591     6429657 : ZEND_API int zend_hash_rehash(HashTable *ht)
     592             : {
     593             :         Bucket *p;
     594             :         uint32_t nIndex, i, j;
     595             : 
     596             :         IS_CONSISTENT(ht);
     597             : 
     598     6429657 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     599           3 :                 if (ht->nTableMask) {
     600           0 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     601             :                 }
     602           3 :                 return SUCCESS;
     603             :         }
     604             : 
     605     6429654 :         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     606   400071309 :         for (i = 0, j = 0; i < ht->nNumUsed; i++) {
     607   393641655 :                 p = ht->arData + i;
     608   787283310 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     609   393585978 :                 if (i != j) {
     610      128509 :                         ht->arData[j] = ht->arData[i];
     611      128509 :                         if (ht->nInternalPointer == i) {
     612        1063 :                                 ht->nInternalPointer = j;
     613             :                         }
     614             :                 }
     615   393585978 :                 nIndex = ht->arData[j].h & ht->nTableMask;
     616   393585978 :                 Z_NEXT(ht->arData[j].val) = ht->arHash[nIndex];
     617   393585978 :                 ht->arHash[nIndex] = j;
     618   393585978 :                 j++;
     619             :         }
     620     6429654 :         ht->nNumUsed = j;
     621     6429654 :         return SUCCESS;
     622             : }
     623             : 
     624             : static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
     625             : {
     626    53810436 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     627    53705515 :                 if (prev) {
     628     2994601 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     629             :                 } else {
     630    50710914 :                         ht->arHash[p->h & ht->nTableMask] = Z_NEXT(p->val);
     631             :                 }
     632             :         }
     633    53810436 :         if (ht->nNumUsed - 1 == idx) {
     634             :                 do {
     635     3706542 :                         ht->nNumUsed--;
     636     7242189 :                 } while (ht->nNumUsed > 0 && (Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF));
     637             :         }
     638    53810436 :         ht->nNumOfElements--;
     639    53810436 :         if (ht->nInternalPointer == idx) {
     640             :                 while (1) {
     641    47834880 :                         idx++;
     642    47834880 :                         if (idx >= ht->nNumUsed) {
     643      170886 :                                 ht->nInternalPointer = INVALID_IDX;
     644             :                                 break;
     645    95327988 :                         } else if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
     646     3028606 :                                 ht->nInternalPointer = idx;
     647             :                                 break;
     648             :                         }
     649             :                 }
     650             :         }
     651    53810436 :         if (p->key) {
     652    53538244 :                 zend_string_release(p->key);
     653             :         }
     654    53810436 :         if (ht->pDestructor) {
     655             :                 zval tmp;
     656    53017049 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     657    53017049 :                 ZVAL_UNDEF(&p->val);
     658    53017049 :                 ht->pDestructor(&tmp);
     659             :         } else {
     660      793387 :                 ZVAL_UNDEF(&p->val);
     661             :         }
     662             : }
     663             : 
     664             : static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
     665             : {
     666     7432205 :         Bucket *prev = NULL;
     667             : 
     668     7432205 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     669     7420176 :                 uint32_t nIndex = p->h & ht->nTableMask;
     670     7420176 :                 uint32_t i = ht->arHash[nIndex];
     671             : 
     672     7420176 :                 if (i != idx) {
     673      314939 :                         prev = ht->arData + i;
     674      356857 :                         while (Z_NEXT(prev->val) != idx) {
     675       41918 :                                 i = Z_NEXT(prev->val);
     676       41918 :                                 prev = ht->arData + i;
     677             :                         }
     678             :                 }
     679             :         }
     680             : 
     681             :         _zend_hash_del_el_ex(ht, idx, p, prev);
     682             : }
     683             : 
     684    46259338 : ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
     685             : {
     686             :         zend_ulong h;
     687             :         uint32_t nIndex;
     688             :         uint32_t idx;
     689             :         Bucket *p;
     690    46259338 :         Bucket *prev = NULL;
     691             : #ifdef ZEND_SIGNALS
     692             :         TSRMLS_FETCH();
     693             : #endif
     694             : 
     695             :         IS_CONSISTENT(ht);
     696             : 
     697    46259338 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     698           7 :                 return FAILURE;
     699             :         }
     700             : 
     701    46259331 :         h = zend_string_hash_val(key);
     702    46259331 :         nIndex = h & ht->nTableMask;
     703             : 
     704    46259331 :         idx = ht->arHash[nIndex];
     705    95339417 :         while (idx != INVALID_IDX) {
     706    48256488 :                 p = ht->arData + idx;
     707   232701045 :                 if ((p->key == key) ||
     708    48226671 :                         (p->h == h &&
     709    45405962 :                      p->key &&
     710    45405962 :                      p->key->len == key->len &&
     711    45405962 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     712    45435733 :                         HANDLE_BLOCK_INTERRUPTIONS();
     713             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     714    45435733 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     715    45435733 :                         return SUCCESS;
     716             :                 }
     717     2820755 :                 prev = p;
     718     2820755 :                 idx = Z_NEXT(p->val);
     719             :         }
     720      823598 :         return FAILURE;
     721             : }
     722             : 
     723         380 : ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key)
     724             : {
     725             :         zend_ulong h;
     726             :         uint32_t nIndex;
     727             :         uint32_t idx;
     728             :         Bucket *p;
     729         380 :         Bucket *prev = NULL;
     730             : #ifdef ZEND_SIGNALS
     731             :         TSRMLS_FETCH();
     732             : #endif
     733             : 
     734             :         IS_CONSISTENT(ht);
     735             : 
     736         380 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     737           0 :                 return FAILURE;
     738             :         }
     739             : 
     740         380 :         h = zend_string_hash_val(key);
     741         380 :         nIndex = h & ht->nTableMask;
     742             : 
     743         380 :         idx = ht->arHash[nIndex];
     744         769 :         while (idx != INVALID_IDX) {
     745         208 :                 p = ht->arData + idx;
     746         897 :                 if ((p->key == key) ||
     747         179 :                         (p->h == h &&
     748         170 :                      p->key &&
     749         170 :                      p->key->len == key->len &&
     750         170 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     751         398 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
     752          14 :                                 zval *data = Z_INDIRECT(p->val);
     753             : 
     754          14 :                                 if (Z_TYPE_P(data) == IS_UNDEF) {
     755           0 :                                         return FAILURE;
     756             :                                 } else {
     757          14 :                                         if (ht->pDestructor) {
     758          14 :                                                 ht->pDestructor(data);
     759             :                                         }
     760          14 :                                         ZVAL_UNDEF(data);
     761             :                                 }
     762             :                         } else {
     763         185 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     764             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
     765         185 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     766             :                         }
     767         199 :                         return SUCCESS;
     768             :                 }
     769           9 :                 prev = p;
     770           9 :                 idx = Z_NEXT(p->val);
     771             :         }
     772         181 :         return FAILURE;
     773             : }
     774             : 
     775      727807 : ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, size_t len)
     776             : {
     777             :         zend_ulong h;
     778             :         uint32_t nIndex;
     779             :         uint32_t idx;
     780             :         Bucket *p;
     781      727807 :         Bucket *prev = NULL;
     782             : #ifdef ZEND_SIGNALS
     783             :         TSRMLS_FETCH();
     784             : #endif
     785             : 
     786             :         IS_CONSISTENT(ht);
     787             : 
     788      727807 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     789           0 :                 return FAILURE;
     790             :         }
     791             : 
     792      727807 :         h = zend_inline_hash_func(str, len);
     793      727807 :         nIndex = h & ht->nTableMask;
     794             : 
     795      727807 :         idx = ht->arHash[nIndex];
     796     1497366 :         while (idx != INVALID_IDX) {
     797      745992 :                 p = ht->arData + idx;
     798     2858712 :                 if ((p->h == h) 
     799             :                          && p->key
     800     1408480 :                          && (p->key->len == len)
     801      704240 :                          && !memcmp(p->key->val, str, len)) {
     802     1408480 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
     803           0 :                                 zval *data = Z_INDIRECT(p->val);
     804             : 
     805           0 :                                 if (Z_TYPE_P(data) == IS_UNDEF) {
     806           0 :                                         return FAILURE;
     807             :                                 } else {
     808           0 :                                         if (ht->pDestructor) {
     809           0 :                                                 ht->pDestructor(data);
     810             :                                         }
     811           0 :                                         ZVAL_UNDEF(data);
     812             :                                 }
     813             :                         } else {
     814      704240 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     815             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
     816      704240 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     817             :                         }
     818      704240 :                         return SUCCESS;
     819             :                 }
     820       41752 :                 prev = p;
     821       41752 :                 idx = Z_NEXT(p->val);
     822             :         }
     823       23567 :         return FAILURE;
     824             : }
     825             : 
     826           0 : ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
     827             : {
     828             :         zend_ulong h;
     829             :         uint32_t nIndex;
     830             :         uint32_t idx;
     831             :         Bucket *p;
     832           0 :         Bucket *prev = NULL;
     833             : #ifdef ZEND_SIGNALS
     834             :         TSRMLS_FETCH();
     835             : #endif
     836             : 
     837             :         IS_CONSISTENT(ht);
     838             : 
     839           0 :         h = zend_inline_hash_func(str, len);
     840           0 :         nIndex = h & ht->nTableMask;
     841             : 
     842           0 :         idx = ht->arHash[nIndex];
     843           0 :         while (idx != INVALID_IDX) {
     844           0 :                 p = ht->arData + idx;
     845           0 :                 if ((p->h == h) 
     846             :                          && p->key
     847           0 :                          && (p->key->len == len)
     848           0 :                          && !memcmp(p->key->val, str, len)) {
     849           0 :                         HANDLE_BLOCK_INTERRUPTIONS();
     850             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     851           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     852           0 :                         return SUCCESS;
     853             :                 }
     854           0 :                 prev = p;
     855           0 :                 idx = Z_NEXT(p->val);
     856             :         }
     857           0 :         return FAILURE;
     858             : }
     859             : 
     860      245443 : ZEND_API int zend_hash_index_del(HashTable *ht, zend_ulong h)
     861             : {
     862             :         uint32_t nIndex;
     863             :         uint32_t idx;
     864             :         Bucket *p;
     865      245443 :         Bucket *prev = NULL;
     866             : #ifdef ZEND_SIGNALS
     867             :         TSRMLS_FETCH();
     868             : #endif
     869             : 
     870             :         IS_CONSISTENT(ht);
     871             : 
     872      245443 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     873       99059 :                 if (h < ht->nNumUsed) {
     874       92900 :                         p = ht->arData + h;
     875      185800 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     876       92892 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     877       92892 :                                 _zend_hash_del_el_ex(ht, h, p, NULL);
     878       92892 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     879       92892 :                                 return SUCCESS;
     880             :                         }
     881             :                 }
     882        6167 :                 return FAILURE;
     883             :         }
     884      146384 :         nIndex = h & ht->nTableMask;
     885             : 
     886      146384 :         idx = ht->arHash[nIndex];
     887      293027 :         while (idx != INVALID_IDX) {
     888      145440 :                 p = ht->arData + idx;
     889      145440 :                 if ((p->h == h) && (p->key == NULL)) {
     890      145181 :                         HANDLE_BLOCK_INTERRUPTIONS();
     891             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     892      145181 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     893      145181 :                         return SUCCESS;
     894             :                 }
     895         259 :                 prev = p;
     896         259 :                 idx = Z_NEXT(p->val);
     897             :         }
     898        1203 :         return FAILURE;
     899             : }
     900             : 
     901    14322842 : ZEND_API void zend_hash_destroy(HashTable *ht)
     902             : {
     903             :         Bucket *p, *end;
     904             : 
     905             :         IS_CONSISTENT(ht);
     906             : 
     907    14322842 :         if (ht->nNumUsed) {
     908     7496522 :                 p = ht->arData;
     909     7496522 :                 end = p + ht->nNumUsed;
     910     7496522 :                 if (ht->pDestructor) {
     911             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
     912             : 
     913     7201893 :                         if (ht->u.flags & HASH_FLAG_PACKED) {
     914             :                                 do {
     915     8171618 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     916     3215917 :                                                 ht->pDestructor(&p->val);
     917             :                                         }
     918     4085808 :                                 } while (++p != end);
     919             :                         } else {
     920             :                                 do {
     921   642435404 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     922   271245208 :                                                 ht->pDestructor(&p->val);
     923   271245208 :                                                 if (EXPECTED(p->key)) {
     924   270973768 :                                                         zend_string_release(p->key);
     925             :                                                 }
     926             :                                         }
     927   321217702 :                                 } while (++p != end);
     928             :                         }
     929             :                 
     930             :                         SET_INCONSISTENT(HT_DESTROYED);
     931             :                 } else {
     932      294629 :                         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     933             :                                 do {
     934    21321090 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     935    10577917 :                                                 if (EXPECTED(p->key)) {
     936     9313697 :                                                         zend_string_release(p->key);
     937             :                                                 }
     938             :                                         }
     939    10660545 :                                 } while (++p != end);
     940             :                         }
     941             :                 }
     942     6826320 :         } else if (EXPECTED(!ht->nTableMask)) {
     943     6756473 :                 return;
     944             :         }
     945     7566368 :         pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
     946             : }
     947             : 
     948     3744116 : ZEND_API void zend_array_destroy(HashTable *ht TSRMLS_DC)
     949             : {
     950             :         Bucket *p, *end;
     951             : 
     952             :         IS_CONSISTENT(ht);
     953             : 
     954     3744116 :         if (ht->nNumUsed) {
     955             :                 
     956             :                 /* In some rare cases destructors of regular arrays may be changed */
     957     2373428 :                 if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
     958          71 :                         zend_hash_destroy(ht);
     959          71 :                         return;
     960             :                 }
     961             :         
     962     2373357 :                 p = ht->arData;
     963     2373357 :                 end = p + ht->nNumUsed;
     964             :                 SET_INCONSISTENT(HT_IS_DESTROYING);
     965             : 
     966     2373357 :                 if (ht->u.flags & HASH_FLAG_PACKED) {
     967             :                         do {
     968    11407340 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     969     4830399 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC TSRMLS_CC);
     970             :                                 }
     971     5703668 :                         } while (++p != end);
     972             :                 } else {
     973             :                         do {
     974     9443786 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     975     4721139 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC TSRMLS_CC);
     976     4721139 :                                         if (EXPECTED(p->key)) {
     977     4392749 :                                                 zend_string_release(p->key);
     978             :                                         }
     979             :                                 }
     980     4721893 :                         } while (++p != end);
     981             :                 }
     982             :                 
     983             :                 SET_INCONSISTENT(HT_DESTROYED);
     984     1370688 :         } else if (EXPECTED(!ht->nTableMask)) {
     985     1370438 :                 return;
     986             :         }
     987     2373605 :         pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
     988             : }
     989             : 
     990       50359 : ZEND_API void zend_hash_clean(HashTable *ht)
     991             : {
     992             :         Bucket *p, *end;
     993             : 
     994             :         IS_CONSISTENT(ht);
     995             : 
     996       50359 :         if (ht->nNumUsed) {
     997        8624 :                 p = ht->arData;
     998        8624 :                 end = p + ht->nNumUsed;
     999        8624 :                 if (ht->pDestructor) {
    1000        3612 :                         if (ht->u.flags & HASH_FLAG_PACKED) {
    1001             :                                 do {
    1002         100 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1003          21 :                                                 ht->pDestructor(&p->val);
    1004             :                                         }
    1005          50 :                                 } while (++p != end);
    1006             :                         } else {
    1007             :                                 do {
    1008     3629076 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1009     1814537 :                                                 ht->pDestructor(&p->val);
    1010     1814537 :                                                 if (EXPECTED(p->key)) {
    1011     1814535 :                                                         zend_string_release(p->key);
    1012             :                                                 }
    1013             :                                         }
    1014     1814538 :                                 } while (++p != end);
    1015             :                         }
    1016             :                 } else {
    1017        5012 :                         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1018             :                                 do {
    1019       60746 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1020       30373 :                                                 if (EXPECTED(p->key)) {
    1021       27553 :                                                         zend_string_release(p->key);
    1022             :                                                 }
    1023             :                                         }
    1024       30373 :                                 } while (++p != end);
    1025             :                         }
    1026             :                 }
    1027             :         }
    1028       50359 :         ht->nNumUsed = 0;
    1029       50359 :         ht->nNumOfElements = 0;
    1030       50359 :         ht->nNextFreeElement = 0;
    1031       50359 :         ht->nInternalPointer = INVALID_IDX;
    1032       50359 :         if (ht->nTableMask) {
    1033        8637 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1034        8622 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));       
    1035             :                 }
    1036             :         }
    1037       50359 : }
    1038             : 
    1039       87831 : ZEND_API void zend_symtable_clean(HashTable *ht TSRMLS_DC)
    1040             : {
    1041             :         Bucket *p, *end;
    1042             : 
    1043             :         IS_CONSISTENT(ht);
    1044             : 
    1045       87831 :         if (ht->nNumUsed) {
    1046       87825 :                 p = ht->arData;
    1047       87825 :                 end = p + ht->nNumUsed;
    1048             :                 do {
    1049      355032 :                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1050      177515 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC TSRMLS_CC);
    1051      177515 :                                 if (EXPECTED(p->key)) {
    1052      177515 :                                         zend_string_release(p->key);
    1053             :                                 }
    1054             :                         }
    1055      177516 :                 } while (++p != end);
    1056             :         }
    1057       87831 :         ht->nNumUsed = 0;
    1058       87831 :         ht->nNumOfElements = 0;
    1059       87831 :         ht->nNextFreeElement = 0;
    1060       87831 :         ht->nInternalPointer = INVALID_IDX;
    1061       87831 :         if (ht->nTableMask) {
    1062       87826 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1063       87826 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));       
    1064             :                 }
    1065             :         }
    1066       87831 : }
    1067             : 
    1068             : /* This function is used by the various apply() functions.
    1069             :  * It deletes the passed bucket, and returns the address of the
    1070             :  * next bucket.  The hash *may* be altered during that time, the
    1071             :  * returned value will still be valid.
    1072             :  */
    1073     7432205 : static void zend_hash_apply_deleter(HashTable *ht, uint32_t idx, Bucket *p)
    1074             : {
    1075             : #ifdef ZEND_SIGNALS
    1076             :         TSRMLS_FETCH();
    1077             : #endif
    1078             : 
    1079     7432205 :         HANDLE_BLOCK_INTERRUPTIONS();
    1080             :         _zend_hash_del_el(ht, idx, p);
    1081     7432205 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1082     7432205 : }
    1083             : 
    1084             : 
    1085           0 : ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
    1086             : {
    1087             :         uint32_t idx;
    1088             :         Bucket *p;
    1089             : 
    1090             :         IS_CONSISTENT(ht);
    1091             : 
    1092           0 :         for (idx = 0; idx < ht->nNumUsed; idx++) {                
    1093           0 :                 p = ht->arData + idx;
    1094           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1095           0 :                 zend_hash_apply_deleter(ht, idx, p);
    1096             :         }
    1097           0 :         if (ht->nTableMask) {
    1098           0 :                 pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
    1099             :         }
    1100             : 
    1101             :         SET_INCONSISTENT(HT_DESTROYED);
    1102           0 : }
    1103             : 
    1104       82664 : ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
    1105             : {
    1106             :         uint32_t idx;
    1107             :         Bucket *p;
    1108             : 
    1109             :         IS_CONSISTENT(ht);
    1110             : 
    1111       82664 :         idx = ht->nNumUsed;
    1112     1933764 :         while (idx > 0) {
    1113     1768436 :                 idx--;
    1114     1768436 :                 p = ht->arData + idx;
    1115     3536872 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1116     1722639 :                 zend_hash_apply_deleter(ht, idx, p);
    1117             :         }
    1118             : 
    1119       82664 :         if (ht->nTableMask) {
    1120       62834 :                 pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
    1121             :         }
    1122             : 
    1123             :         SET_INCONSISTENT(HT_DESTROYED);
    1124       82664 : }
    1125             : 
    1126             : /* This is used to recurse elements and selectively delete certain entries 
    1127             :  * from a hashtable. apply_func() receives the data and decides if the entry 
    1128             :  * should be deleted or recursion should be stopped. The following three 
    1129             :  * return codes are possible:
    1130             :  * ZEND_HASH_APPLY_KEEP   - continue
    1131             :  * ZEND_HASH_APPLY_STOP   - stop iteration
    1132             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
    1133             :  */
    1134             : 
    1135       92234 : ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
    1136             : {
    1137             :         uint32_t idx;
    1138             :         Bucket *p;
    1139             :         int result;
    1140             : 
    1141             :         IS_CONSISTENT(ht);
    1142             : 
    1143       92234 :         HASH_PROTECT_RECURSION(ht);
    1144     1707804 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1145     1615572 :                 p = ht->arData + idx;
    1146     3231144 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1147             :                 
    1148     1615557 :                 result = apply_func(&p->val TSRMLS_CC);
    1149             :                 
    1150     1615555 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1151      108248 :                         zend_hash_apply_deleter(ht, idx, p);
    1152             :                 }
    1153     1615555 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1154           0 :                         break;
    1155             :                 }
    1156             :         }
    1157       92232 :         HASH_UNPROTECT_RECURSION(ht);
    1158       92232 : }
    1159             : 
    1160             : 
    1161      651029 : ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC)
    1162             : {
    1163             :     uint32_t idx;
    1164             :         Bucket *p;
    1165             :         int result;
    1166             : 
    1167             :         IS_CONSISTENT(ht);
    1168             : 
    1169      651029 :         HASH_PROTECT_RECURSION(ht);
    1170   190704281 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1171   190057433 :                 p = ht->arData + idx;
    1172   380114866 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1173             : 
    1174   149530220 :                 result = apply_func(&p->val, argument TSRMLS_CC);
    1175             :                 
    1176   149530220 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1177     5498171 :                         zend_hash_apply_deleter(ht, idx, p);
    1178             :                 }
    1179   149530220 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1180        4181 :                         break;
    1181             :                 }
    1182             :         }
    1183      651029 :         HASH_UNPROTECT_RECURSION(ht);
    1184      651029 : }
    1185             : 
    1186             : 
    1187         715 : ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...)
    1188             : {
    1189             :         uint32_t idx;
    1190             :         Bucket *p;
    1191             :         va_list args;
    1192             :         zend_hash_key hash_key;
    1193             :         int result;
    1194             : 
    1195             :         IS_CONSISTENT(ht);
    1196             : 
    1197         715 :         HASH_PROTECT_RECURSION(ht);
    1198             : 
    1199     1100503 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1200     1099788 :                 p = ht->arData + idx;
    1201     2199576 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1202     1099699 :                 va_start(args, num_args);
    1203     1099699 :                 hash_key.h = p->h;
    1204     1099699 :                 hash_key.key = p->key;
    1205             : 
    1206     1099699 :                 result = apply_func(&p->val TSRMLS_CC, num_args, args, &hash_key);
    1207             : 
    1208     1099699 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1209          24 :                         zend_hash_apply_deleter(ht, idx, p);
    1210             :                 }
    1211     1099699 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1212           0 :                         va_end(args);
    1213           0 :                         break;
    1214             :                 }
    1215     1099699 :                 va_end(args);
    1216             :         }
    1217             : 
    1218         715 :         HASH_UNPROTECT_RECURSION(ht);
    1219         715 : }
    1220             : 
    1221             : 
    1222      107820 : ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
    1223             : {
    1224             :         uint32_t idx;
    1225             :         Bucket *p;
    1226             :         int result;
    1227             : 
    1228             :         IS_CONSISTENT(ht);
    1229             : 
    1230      107820 :         HASH_PROTECT_RECURSION(ht);
    1231      107820 :         idx = ht->nNumUsed;
    1232      723124 :         while (idx > 0) {
    1233      569329 :                 idx--;
    1234      569329 :                 p = ht->arData + idx;
    1235     1138658 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1236             :                 
    1237      515451 :                 result = apply_func(&p->val TSRMLS_CC);
    1238             : 
    1239      515451 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1240      103123 :                         zend_hash_apply_deleter(ht, idx, p);
    1241             :                 }
    1242      515451 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1243       61845 :                         break;
    1244             :                 }
    1245             :         }
    1246      107820 :         HASH_UNPROTECT_RECURSION(ht);
    1247      107820 : }
    1248             : 
    1249             : 
    1250         464 : ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
    1251             : {
    1252             :     uint32_t idx;
    1253             :         Bucket *p;
    1254             :         zval *new_entry, *data;
    1255             :         zend_bool setTargetPointer;
    1256             : 
    1257             :         IS_CONSISTENT(source);
    1258             :         IS_CONSISTENT(target);
    1259             : 
    1260         464 :         setTargetPointer = (target->nInternalPointer == INVALID_IDX);
    1261       11928 :         for (idx = 0; idx < source->nNumUsed; idx++) {            
    1262       11464 :                 p = source->arData + idx;
    1263       22928 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1264             : 
    1265       11464 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1266         313 :                         target->nInternalPointer = INVALID_IDX;
    1267             :                 }
    1268             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1269       11464 :                 data = &p->val;
    1270       11464 :                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1271          96 :                         data = Z_INDIRECT_P(data);
    1272          96 :                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1273           0 :                                 continue;
    1274             :                         }
    1275             :                 }
    1276       11464 :                 if (p->key) {
    1277       11375 :                         new_entry = zend_hash_update(target, p->key, data);
    1278             :                 } else {
    1279          89 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1280             :                 }
    1281       11464 :                 if (pCopyConstructor) {
    1282         412 :                         pCopyConstructor(new_entry);
    1283             :                 }
    1284             :         }
    1285         464 :         if (target->nInternalPointer == INVALID_IDX && target->nNumOfElements > 0) {
    1286           0 :                 idx = 0;
    1287           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1288           0 :                         idx++;
    1289             :                 }
    1290           0 :                 target->nInternalPointer = idx;
    1291             :         }
    1292         464 : }
    1293             : 
    1294             : 
    1295     1296239 : ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
    1296             : {
    1297             :     uint32_t idx, target_idx;
    1298             :         uint32_t nIndex;
    1299             :         Bucket *p, *q;
    1300             :         zval *data;
    1301             : 
    1302             :         IS_CONSISTENT(source);
    1303             :         
    1304     1296239 :         target->nTableMask = source->nTableMask;
    1305     1296239 :         target->nTableSize = source->nTableSize;
    1306     1296239 :         target->pDestructor = source->pDestructor;
    1307     1296239 :         target->nInternalPointer = INVALID_IDX;
    1308     1296239 :         target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1309             : 
    1310     1296239 :         target_idx = 0;
    1311     1296239 :         if (target->nTableMask) {
    1312     1134537 :                 if (target->u.flags & HASH_FLAG_PACKED) {
    1313     1077029 :                         target->nNumUsed = source->nNumUsed;
    1314     1077029 :                         target->nNumOfElements = source->nNumOfElements;
    1315     1077029 :                         target->nNextFreeElement = source->nNextFreeElement;
    1316     1077029 :                         target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket), 0, 0);
    1317     1077029 :                         target->arHash = (uint32_t*)&uninitialized_bucket;
    1318     1077029 :                         target->nInternalPointer = source->nInternalPointer;
    1319             : 
    1320     4472323 :                         for (idx = 0; idx < source->nNumUsed; idx++) {            
    1321     3395294 :                                 p = source->arData + idx;
    1322     3395294 :                                 q = target->arData + idx;
    1323     6790588 :                                 if (Z_TYPE(p->val) == IS_UNDEF) {
    1324      849638 :                                         ZVAL_UNDEF(&q->val);
    1325      849638 :                                         continue;
    1326             :                                 }
    1327             :                                 /* INDIRECT element may point to UNDEF-ined slots */
    1328     2545656 :                                 data = &p->val;
    1329     2545656 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1330           0 :                                         data = Z_INDIRECT_P(data);
    1331           0 :                                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1332           0 :                                                 ZVAL_UNDEF(&q->val);
    1333           0 :                                                 continue;
    1334             :                                         }
    1335             :                                 }
    1336             : 
    1337     2545656 :                                 q->h = p->h;
    1338     2545656 :                                 q->key = NULL;
    1339     2545656 :                                 if (Z_OPT_REFCOUNTED_P(data)) {
    1340     2414585 :                                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
    1341           1 :                                                 ZVAL_COPY(&q->val, Z_REFVAL_P(data));
    1342             :                                         } else {
    1343     2414562 :                                                 ZVAL_COPY(&q->val, data);
    1344             :                                         }
    1345             :                                 } else {
    1346      131093 :                                         ZVAL_COPY_VALUE(&q->val, data);
    1347             :                                 }
    1348             :                         }
    1349     2154058 :                         if (target->nNumOfElements > 0 &&
    1350     1077029 :                             target->nInternalPointer == INVALID_IDX) {
    1351          41 :                                 idx = 0;
    1352         145 :                                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1353          11 :                                         idx++;
    1354             :                                 }
    1355          41 :                                 target->nInternalPointer = idx;
    1356             :                         }
    1357             :                 } else {
    1358       57508 :                         target->nNextFreeElement = source->nNextFreeElement;
    1359       57508 :                         target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, 0);
    1360       57508 :                         target->arHash = (uint32_t*)(target->arData + target->nTableSize);
    1361       57508 :                         memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(uint32_t));
    1362             : 
    1363      777318 :                         for (idx = 0; idx < source->nNumUsed; idx++) {            
    1364      719810 :                                 p = source->arData + idx;
    1365     1439620 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1366             :                                 /* INDIRECT element may point to UNDEF-ined slots */
    1367      719806 :                                 data = &p->val;
    1368      719806 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1369       29526 :                                         data = Z_INDIRECT_P(data);
    1370       29526 :                                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1371        5179 :                                                 continue;
    1372             :                                         }
    1373             :                                 }
    1374             : 
    1375      714627 :                                 if (source->nInternalPointer == idx) {
    1376       44416 :                                         target->nInternalPointer = target_idx;
    1377             :                                 }
    1378             : 
    1379      714627 :                                 q = target->arData + target_idx;
    1380      714627 :                                 q->h = p->h;
    1381      714627 :                                 q->key = p->key;
    1382      714627 :                                 if (q->key) {
    1383      708988 :                                         zend_string_addref(q->key);
    1384             :                                 }
    1385      714627 :                                 nIndex = q->h & target->nTableMask;
    1386      714627 :                                 Z_NEXT(q->val) = target->arHash[nIndex];
    1387      714627 :                                 target->arHash[nIndex] = target_idx;
    1388      714627 :                                 if (Z_OPT_REFCOUNTED_P(data)) {
    1389      637437 :                                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
    1390          97 :                                                 ZVAL_COPY(&q->val, Z_REFVAL_P(data));
    1391             :                                         } else {
    1392      636697 :                                                 ZVAL_COPY(&q->val, data);
    1393             :                                         }
    1394             :                                 } else {
    1395       77833 :                                         ZVAL_COPY_VALUE(&q->val, data);
    1396             :                                 }
    1397      714627 :                                 target_idx++;
    1398             :                         }
    1399       57508 :                         target->nNumUsed = target_idx;
    1400       57508 :                         target->nNumOfElements = target_idx;
    1401      114996 :                         if (target->nNumOfElements > 0 &&
    1402       57488 :                             target->nInternalPointer == INVALID_IDX) {
    1403       13072 :                                 target->nInternalPointer = 0;
    1404             :                         }
    1405             :                 }
    1406             :         } else {
    1407      161702 :                 target->nNumUsed = 0;
    1408      161702 :                 target->nNumOfElements = 0;
    1409      161702 :                 target->nNextFreeElement = 0;
    1410      161702 :                 target->arData = NULL;
    1411      161702 :                 target->arHash = (uint32_t*)&uninitialized_bucket;
    1412             :         }
    1413     1296239 : }
    1414             : 
    1415             : 
    1416      185675 : ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
    1417             : {
    1418             :     uint32_t idx;
    1419             :         Bucket *p;
    1420             :         zval *t;
    1421      185675 :         uint32_t mode = (overwrite?HASH_UPDATE:HASH_ADD);
    1422             : 
    1423             :         IS_CONSISTENT(source);
    1424             :         IS_CONSISTENT(target);
    1425             : 
    1426     3198002 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1427     3012327 :                 p = source->arData + idx;
    1428     6024654 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1429     3012327 :                 if (p->key) {
    1430     3012311 :                         t = _zend_hash_add_or_update(target, p->key, &p->val, mode ZEND_FILE_LINE_RELAY_CC);
    1431     3012311 :                         if (t && pCopyConstructor) {
    1432     3011729 :                                 pCopyConstructor(t);
    1433             :                         }
    1434             :                 } else {
    1435          16 :                         if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h))) {
    1436           6 :                                 t = zend_hash_index_update(target, p->h, &p->val);
    1437           6 :                                 if (t && pCopyConstructor) {
    1438           6 :                                         pCopyConstructor(t);
    1439             :                                 }
    1440             :                         }
    1441             :                 }
    1442             :         }
    1443      185675 :         if (target->nNumOfElements > 0) {
    1444      185673 :                 idx = 0;
    1445      557019 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1446           0 :                         idx++;
    1447             :                 }
    1448      185673 :                 target->nInternalPointer = idx;
    1449             :         }
    1450      185675 : }
    1451             : 
    1452             : 
    1453           0 : static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, zval *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func)
    1454             : {
    1455             :         zend_hash_key hash_key;
    1456             : 
    1457           0 :         hash_key.h = p->h;
    1458           0 :         hash_key.key = p->key;
    1459           0 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1460             : }
    1461             : 
    1462             : 
    1463           0 : ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
    1464             : {
    1465             :         uint32_t idx;
    1466             :         Bucket *p;
    1467             :         zval *t;
    1468             : 
    1469             :         IS_CONSISTENT(source);
    1470             :         IS_CONSISTENT(target);
    1471             : 
    1472           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1473           0 :                 p = source->arData + idx;
    1474           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1475           0 :                 if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
    1476           0 :                         t = zend_hash_update(target, p->key, &p->val);
    1477           0 :                         if (t && pCopyConstructor) {
    1478           0 :                                 pCopyConstructor(t);
    1479             :                         }
    1480             :                 }
    1481             :         }
    1482           0 :         if (target->nNumOfElements > 0) {
    1483           0 :                 idx = 0;
    1484           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1485           0 :                         idx++;
    1486             :                 }
    1487           0 :                 target->nInternalPointer = idx;
    1488             :         }
    1489           0 : }
    1490             : 
    1491             : 
    1492             : /* Returns SUCCESS if found and FAILURE if not. The pointer to the
    1493             :  * data is returned in pData. The reason is that there's no reason
    1494             :  * someone using the hash table might not want to have NULL data
    1495             :  */
    1496    51229610 : ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key)
    1497             : {
    1498             :         Bucket *p;
    1499             : 
    1500             :         IS_CONSISTENT(ht);
    1501             : 
    1502    51229610 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1503         797 :                 return NULL;
    1504             :         }
    1505             : 
    1506    51228813 :         p = zend_hash_find_bucket(ht, key);
    1507    51228813 :         return p ? &p->val : NULL;
    1508             : }
    1509             : 
    1510     2607355 : ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
    1511             : {
    1512             :         zend_ulong h;
    1513             :         Bucket *p;
    1514             : 
    1515             :         IS_CONSISTENT(ht);
    1516             : 
    1517     2607355 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1518         171 :                 return NULL;
    1519             :         }
    1520             : 
    1521     2607184 :         h = zend_inline_hash_func(str, len);
    1522     2607184 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1523     2607184 :         return p ? &p->val : NULL;
    1524             : }
    1525             : 
    1526      557493 : ZEND_API zend_bool zend_hash_exists(const HashTable *ht, zend_string *key)
    1527             : {
    1528             :         Bucket *p;
    1529             : 
    1530             :         IS_CONSISTENT(ht);
    1531             : 
    1532      557493 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1533          55 :                 return 0;
    1534             :         }
    1535             : 
    1536      557438 :         p = zend_hash_find_bucket(ht, key);
    1537      557438 :         return p ? 1 : 0;
    1538             : }
    1539             : 
    1540      854567 : ZEND_API zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
    1541             : {
    1542             :         zend_ulong h;
    1543             :         Bucket *p;
    1544             : 
    1545             :         IS_CONSISTENT(ht);
    1546             : 
    1547      854567 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1548           0 :                 return 0;
    1549             :         }
    1550             : 
    1551      854567 :         h = zend_inline_hash_func(str, len);
    1552      854567 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1553      854567 :         return p ? 1 : 0;
    1554             : }
    1555             : 
    1556     6167374 : ZEND_API zval *zend_hash_index_find(const HashTable *ht, zend_ulong h)
    1557             : {
    1558             :         Bucket *p;
    1559             : 
    1560             :         IS_CONSISTENT(ht);
    1561             : 
    1562     6167374 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1563     5020505 :                 if (h < ht->nNumUsed) {
    1564     4769060 :                         p = ht->arData + h;
    1565     9538120 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1566     4768535 :                                 return &p->val;
    1567             :                         }
    1568             :                 }
    1569      251970 :                 return NULL;
    1570             :         }
    1571             : 
    1572     1146869 :         p = zend_hash_index_find_bucket(ht, h);
    1573     1146869 :         return p ? &p->val : NULL;
    1574             : }
    1575             : 
    1576             : 
    1577     1526396 : ZEND_API zend_bool zend_hash_index_exists(const HashTable *ht, zend_ulong h)
    1578             : {
    1579             :         Bucket *p;
    1580             : 
    1581             :         IS_CONSISTENT(ht);
    1582             : 
    1583     1526396 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1584          56 :                 if (h < ht->nNumUsed) {
    1585         102 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    1586          50 :                                 return 1;
    1587             :                         }
    1588             :                 }
    1589           6 :                 return 0;
    1590             :         }
    1591             : 
    1592     1526340 :         p = zend_hash_index_find_bucket(ht, h);
    1593     1526340 :         return p ? 1 : 0;
    1594             : }
    1595             : 
    1596             : 
    1597       21637 : ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1598             : {
    1599             :     uint32_t idx;
    1600             :         
    1601             :         IS_CONSISTENT(ht);
    1602       22145 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1603       42570 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1604       20777 :                         *pos = idx;
    1605       20777 :                         return;
    1606             :                 }
    1607             :         }
    1608         860 :         *pos = INVALID_IDX;
    1609             : }
    1610             : 
    1611             : 
    1612             : /* This function will be extremely optimized by remembering 
    1613             :  * the end of the list
    1614             :  */
    1615          47 : ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1616             : {
    1617             :         uint32_t idx;
    1618             :         
    1619             :         IS_CONSISTENT(ht);
    1620             : 
    1621          47 :         idx = ht->nNumUsed;
    1622          94 :         while (idx > 0) {
    1623          45 :                 idx--;
    1624          90 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1625          45 :                         *pos = idx;
    1626          45 :                         return;
    1627             :                 }
    1628             :         }
    1629           2 :         *pos = INVALID_IDX;
    1630             : }
    1631             : 
    1632             : 
    1633       81542 : ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    1634             : {
    1635       81542 :         uint32_t idx = *pos;
    1636             : 
    1637             :         IS_CONSISTENT(ht);
    1638             : 
    1639       81542 :         if (idx != INVALID_IDX) {
    1640             :                 while (1) {
    1641       81598 :                         idx++;
    1642       81598 :                         if (idx >= ht->nNumUsed) {
    1643       17073 :                                 *pos = INVALID_IDX;
    1644       17073 :                                 return SUCCESS;
    1645             :                         }
    1646      129050 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1647       64445 :                                 *pos = idx;
    1648       64445 :                                 return SUCCESS;
    1649             :                         }
    1650          80 :                 }
    1651             :         } else {
    1652          24 :                 return FAILURE;
    1653             :         }
    1654             : }
    1655             : 
    1656          21 : ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    1657             : {
    1658          21 :         uint32_t idx = *pos;
    1659             : 
    1660             :         IS_CONSISTENT(ht);
    1661             : 
    1662          21 :         if (idx != INVALID_IDX) {
    1663          38 :                 while (idx > 0) {
    1664          14 :                         idx--;
    1665          28 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1666          14 :                                 *pos = idx;
    1667          14 :                                 return SUCCESS;
    1668             :                         }
    1669             :                 }
    1670           5 :                 *pos = INVALID_IDX;
    1671           5 :                 return SUCCESS;
    1672             :         } else {
    1673           2 :                 return FAILURE;
    1674             :         }
    1675             : }
    1676             : 
    1677             : 
    1678             : /* This function should be made binary safe  */
    1679       23244 : ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, zend_bool duplicate, HashPosition *pos)
    1680             : {
    1681       23244 :         uint32_t idx = *pos;
    1682             :         Bucket *p;
    1683             : 
    1684             :         IS_CONSISTENT(ht);
    1685       23244 :         if (idx != INVALID_IDX) {
    1686       22320 :                 p = ht->arData + idx;
    1687       22320 :                 if (p->key) {
    1688       20856 :                         if (duplicate) {
    1689           0 :                                 *str_index = zend_string_copy(p->key);
    1690             :                         } else {
    1691       20856 :                                 *str_index = p->key;
    1692             :                         }
    1693       20856 :                         return HASH_KEY_IS_STRING;
    1694             :                 } else {
    1695        1464 :                         *num_index = p->h;
    1696        1464 :                         return HASH_KEY_IS_LONG;
    1697             :                 }
    1698             :         }
    1699         924 :         return HASH_KEY_NON_EXISTENT;
    1700             : }
    1701             : 
    1702        3565 : ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    1703             : {
    1704        3565 :         uint32_t idx = *pos;
    1705             :         Bucket *p;
    1706             : 
    1707             :         IS_CONSISTENT(ht);
    1708        3565 :         if (idx == INVALID_IDX) {
    1709          57 :                 ZVAL_NULL(key);
    1710             :         } else {
    1711        3508 :                 p = ht->arData + idx;
    1712        3508 :                 if (p->key) {
    1713         669 :                         ZVAL_STR_COPY(key, p->key);
    1714             :                 } else {
    1715        2839 :                         ZVAL_LONG(key, p->h);
    1716             :                 }
    1717             :         }
    1718        3565 : }
    1719             : 
    1720       68695 : ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    1721             : {
    1722       68695 :     uint32_t idx = *pos;
    1723             :         Bucket *p;
    1724             : 
    1725             :         IS_CONSISTENT(ht);
    1726       68695 :         if (idx != INVALID_IDX) {
    1727       53532 :                 p = ht->arData + idx;
    1728       53532 :                 if (p->key) {
    1729       51006 :                         return HASH_KEY_IS_STRING;
    1730             :                 } else {
    1731        2526 :                         return HASH_KEY_IS_LONG;
    1732             :                 }
    1733             :         }
    1734       15163 :         return HASH_KEY_NON_EXISTENT;
    1735             : }
    1736             : 
    1737             : 
    1738       74851 : ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    1739             : {
    1740       74851 :         uint32_t idx = *pos;
    1741             :         Bucket *p;
    1742             : 
    1743             :         IS_CONSISTENT(ht);
    1744       74851 :         if (idx != INVALID_IDX) {
    1745       73674 :                 p = ht->arData + idx;
    1746       73674 :                 return &p->val;
    1747             :         } else {
    1748        1177 :                 return NULL;
    1749             :         }
    1750             : }
    1751             : 
    1752       22332 : ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
    1753             :                                                         compare_func_t compar, zend_bool renumber TSRMLS_DC)
    1754             : {
    1755             :         Bucket *p;
    1756             :         uint32_t i, j;
    1757             : 
    1758             :         IS_CONSISTENT(ht);
    1759             : 
    1760       22332 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    1761         288 :                 return SUCCESS;
    1762             :         }
    1763             : 
    1764       22044 :         if (ht->nNumUsed == ht->nNumOfElements) {
    1765       21934 :                 i = ht->nNumUsed;
    1766             :         } else {
    1767         787 :                 for (j = 0, i = 0; j < ht->nNumUsed; j++) {
    1768         677 :                         p = ht->arData + j;
    1769        1354 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1770         520 :                         if (i != j) {
    1771         504 :                                 ht->arData[i] = *p;
    1772             :                         }
    1773         520 :                         i++;
    1774             :                 }
    1775             :         }
    1776             : 
    1777       22044 :         (*sort_func)((void *) ht->arData, i, sizeof(Bucket), compar TSRMLS_CC);
    1778             : 
    1779       22043 :         HANDLE_BLOCK_INTERRUPTIONS();
    1780       22043 :         ht->nNumUsed = i;
    1781       22043 :         ht->nInternalPointer = 0;
    1782             : 
    1783       22043 :         if (renumber) {
    1784       15380 :                 for (j = 0; j < i; j++) {
    1785       15090 :                         p = ht->arData + j;
    1786       15090 :                         p->h = j;
    1787       15090 :                         if (p->key) {
    1788         288 :                                 zend_string_release(p->key);
    1789         288 :                                 p->key = NULL;
    1790             :                         }
    1791             :                 }
    1792             : 
    1793         290 :                 ht->nNextFreeElement = i;
    1794             :         }
    1795       22043 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1796         503 :                 if (!renumber) {
    1797         261 :                         zend_hash_packed_to_hash(ht);
    1798             :                 }
    1799             :         } else {
    1800       21540 :                 if (renumber) {
    1801          48 :                         ht->u.flags |= HASH_FLAG_PACKED;
    1802          48 :                         ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket));
    1803          48 :                         ht->arHash = (uint32_t*)&uninitialized_bucket;
    1804             :                 } else {
    1805       21492 :                         zend_hash_rehash(ht);
    1806             :                 }
    1807             :         }
    1808             : 
    1809       22043 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1810             : 
    1811       22043 :         return SUCCESS;
    1812             : }
    1813             : 
    1814             : 
    1815        1119 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC)
    1816             : {
    1817             :         uint32_t idx1, idx2;
    1818        1119 :         Bucket *p1, *p2 = NULL;
    1819             :         int result;
    1820             :         zval *pData1, *pData2;
    1821             : 
    1822             :         IS_CONSISTENT(ht1);
    1823             :         IS_CONSISTENT(ht2);
    1824             : 
    1825        1119 :         HASH_PROTECT_RECURSION(ht1); 
    1826        1119 :         HASH_PROTECT_RECURSION(ht2); 
    1827             : 
    1828        1119 :         result = ht1->nNumOfElements - ht2->nNumOfElements;
    1829        1119 :         if (result!=0) {
    1830         531 :                 HASH_UNPROTECT_RECURSION(ht1); 
    1831         531 :                 HASH_UNPROTECT_RECURSION(ht2); 
    1832         531 :                 return result;
    1833             :         }
    1834             : 
    1835        4164 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    1836        3750 :                 p1 = ht1->arData + idx1;
    1837        7500 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    1838             : 
    1839        3737 :                 if (ordered) {
    1840             :                         while (1) {
    1841        1140 :                                 p2 = ht2->arData + idx2;
    1842        1140 :                                 if (idx2 == ht2->nNumUsed) {
    1843           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1844           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1845           0 :                                         return 1; /* That's not supposed to happen */
    1846             :                                 }
    1847        2280 :                                 if (Z_TYPE(p2->val) != IS_UNDEF) break;
    1848           1 :                                 idx2++;
    1849           1 :                         }                                               
    1850        1506 :                         if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
    1851         368 :                                 result = p1->h - p2->h;
    1852         368 :                                 if (result != 0) {
    1853           1 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1854           1 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1855           1 :                                         return result;
    1856             :                                 }
    1857             :                         } else { /* string indices */
    1858         771 :                                 size_t len0 = (p1->key ? p1->key->len : 0);
    1859         771 :                                 size_t len1 = (p2->key ? p2->key->len : 0);
    1860         771 :                                 if (len0 != len1) {
    1861           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1862           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1863           0 :                                         return len0 > len1 ? 1 : -1;
    1864             :                                 }
    1865         771 :                                 result = memcmp(p1->key->val, p2->key->val, p1->key->len);
    1866         771 :                                 if (result != 0) {
    1867           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1868           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1869           0 :                                         return result;
    1870             :                                 }
    1871             :                         }
    1872        1138 :                         pData2 = &p2->val;
    1873             :                 } else {
    1874        2598 :                         if (p1->key == NULL) { /* numeric index */
    1875         219 :                                 pData2 = zend_hash_index_find(ht2, p1->h);
    1876         219 :                                 if (pData2 == NULL) {
    1877           4 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1878           4 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1879           4 :                                         return 1;
    1880             :                                 }
    1881             :                         } else { /* string index */
    1882        2379 :                                 pData2 = zend_hash_find(ht2, p1->key);
    1883        2379 :                                 if (pData2 == NULL) {
    1884          24 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1885          24 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1886          24 :                                         return 1;
    1887             :                                 }
    1888             :                         }
    1889             :                 }
    1890        3708 :                 pData1 = &p1->val;
    1891        3708 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    1892         118 :                         pData1 = Z_INDIRECT_P(pData1);
    1893             :                 }
    1894        3708 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    1895         118 :                         pData2 = Z_INDIRECT_P(pData2);
    1896             :                 }
    1897        3708 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    1898           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    1899           0 :                                 return -1;
    1900             :                         }
    1901        3708 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    1902           0 :                         return 1;
    1903             :                 } else {
    1904        3708 :                         result = compar(pData1, pData2 TSRMLS_CC);
    1905             :                 }
    1906        3708 :                 if (result != 0) {
    1907         145 :                         HASH_UNPROTECT_RECURSION(ht1); 
    1908         145 :                         HASH_UNPROTECT_RECURSION(ht2); 
    1909         145 :                         return result;
    1910             :                 }
    1911        3563 :                 if (ordered) {
    1912        1134 :                         idx2++;
    1913             :                 }
    1914             :         }
    1915             :         
    1916         414 :         HASH_UNPROTECT_RECURSION(ht1); 
    1917         414 :         HASH_UNPROTECT_RECURSION(ht2); 
    1918         414 :         return 0;
    1919             : }
    1920             : 
    1921             : 
    1922          82 : ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag TSRMLS_DC)
    1923             : {
    1924             :         uint32_t idx;
    1925             :         Bucket *p, *res;
    1926             : 
    1927             :         IS_CONSISTENT(ht);
    1928             : 
    1929          82 :         if (ht->nNumOfElements == 0 ) {
    1930           4 :                 return NULL;
    1931             :         }
    1932             : 
    1933          78 :         idx = 0;
    1934             :         while (1) {
    1935          78 :                 if (idx == ht->nNumUsed) {
    1936           0 :                         return NULL;
    1937             :                 }
    1938         156 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
    1939           0 :                 idx++;
    1940           0 :         }
    1941          78 :         res = ht->arData + idx;
    1942         376 :         for (; idx < ht->nNumUsed; idx++) {
    1943         298 :                 p = ht->arData + idx;
    1944         596 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1945             :                 
    1946         298 :                 if (flag) {
    1947         229 :                         if (compar(res, p TSRMLS_CC) < 0) { /* max */
    1948          20 :                                 res = p;
    1949             :                         }
    1950             :                 } else {
    1951          69 :                         if (compar(res, p TSRMLS_CC) > 0) { /* min */
    1952           6 :                                 res = p;
    1953             :                         }
    1954             :                 }
    1955             :         }
    1956          78 :         return &res->val;
    1957             : }
    1958             : 
    1959      383132 : ZEND_API int _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    1960             : {
    1961      383132 :         register const char *tmp = key;
    1962             :         const char *end;
    1963             : 
    1964      383132 :         if (*tmp > '9') {
    1965           0 :                 return 0;
    1966      383132 :         } else if (*tmp < '0') {
    1967          59 :                 if (*tmp != '-') {
    1968           0 :                         return 0;
    1969             :                 }
    1970          59 :                 tmp++;
    1971          59 :                 if (*tmp > '9' || *tmp < '0') {
    1972           0 :                         return 0;
    1973             :                 }
    1974             :         }
    1975             : 
    1976             :         /* possibly a numeric index */
    1977      383132 :         end = key + length;
    1978             : 
    1979     1129254 :         if ((*end != '\0') /* not a null terminated string */
    1980      383132 :          || (*tmp == '0' && length > 1) /* numbers with leading zeros */
    1981      362990 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    1982             :          || (SIZEOF_ZEND_LONG == 4 &&
    1983             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    1984             :              *tmp > '2')) { /* overflow */
    1985       20169 :                 return 0;
    1986             :         }
    1987      362963 :         *idx = (*tmp - '0');
    1988             :         while (1) {
    1989     1444687 :                 ++tmp;
    1990     1444687 :                 if (tmp == end) {
    1991      362700 :                         if (*key == '-') {
    1992          28 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    1993           0 :                                         return 0;
    1994             :                                 }
    1995          28 :                                 *idx = 0 - *idx;
    1996      362672 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    1997           0 :                                 return 0;
    1998             :                         }
    1999      362700 :                         return 1;
    2000             :                 }
    2001     2163711 :                 if (*tmp <= '9' && *tmp >= '0') {
    2002     1081724 :                         *idx = (*idx * 10) + (*tmp - '0');
    2003             :                 } else {
    2004         263 :                         return 0;
    2005             :                 }
    2006     1081724 :         }
    2007             : }
    2008             : 
    2009             : /*
    2010             :  * Local variables:
    2011             :  * tab-width: 4
    2012             :  * c-basic-offset: 4
    2013             :  * indent-tabs-mode: t
    2014             :  * End:
    2015             :  */

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:10 +0000 (6 days ago)

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