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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_HEAD/Zend - zend_alloc.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 772
Code covered: 66.8 % Executed lines: 516
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 2.00 of the Zend license,     |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.zend.com/license/2_00.txt.                                |
      11                 :    | If you did not receive a copy of the Zend license and are unable to  |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@zend.com so we can mail you a copy immediately.              |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Zeev Suraski <zeev@zend.com>                                |
      17                 :    |          Dmitry Stogov <dmitry@zend.com>                             |
      18                 :    +----------------------------------------------------------------------+
      19                 : */
      20                 : 
      21                 : /* $Id: zend_alloc.c 287992 2009-09-03 14:33:11Z dmitry $ */
      22                 : 
      23                 : #include "zend.h"
      24                 : #include "zend_alloc.h"
      25                 : #include "zend_globals.h"
      26                 : #include "zend_operators.h"
      27                 : #include "zend_unicode.h"
      28                 : #ifdef HAVE_SIGNAL_H
      29                 : # include <signal.h>
      30                 : #endif
      31                 : #ifdef HAVE_UNISTD_H
      32                 : # include <unistd.h>
      33                 : #endif
      34                 : 
      35                 : #ifdef ZEND_WIN32
      36                 : # include <wincrypt.h>
      37                 : # include <process.h>
      38                 : #endif
      39                 : 
      40                 : #ifndef ZEND_MM_HEAP_PROTECTION
      41                 : # define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG
      42                 : #endif
      43                 : 
      44                 : #ifndef ZEND_MM_SAFE_UNLINKING
      45                 : # define ZEND_MM_SAFE_UNLINKING 1
      46                 : #endif
      47                 : 
      48                 : #ifndef ZEND_MM_COOKIES
      49                 : # define ZEND_MM_COOKIES ZEND_DEBUG
      50                 : #endif
      51                 : 
      52                 : #ifdef _WIN64
      53                 : # define PTR_FMT "0x%0.16I64x"
      54                 : /*
      55                 : #elif sizeof(long) == 8
      56                 : # define PTR_FMT "0x%0.16lx"
      57                 : */
      58                 : #else
      59                 : # define PTR_FMT "0x%0.8lx"
      60                 : #endif
      61                 : 
      62                 : #if ZEND_DEBUG
      63                 : void zend_debug_alloc_output(char *format, ...) /* {{{ */
      64                 : {
      65                 :         char output_buf[256];
      66                 :         va_list args;
      67                 : 
      68                 :         va_start(args, format);
      69                 :         vsprintf(output_buf, format, args);
      70                 :         va_end(args);
      71                 : 
      72                 : #ifdef ZEND_WIN32
      73                 :         OutputDebugString(output_buf);
      74                 : #else
      75                 :         fprintf(stderr, "%s", output_buf);
      76                 : #endif
      77                 : }
      78                 : /* }}} */
      79                 : #endif
      80                 : 
      81                 : #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
      82                 : static void zend_mm_panic(const char *message) __attribute__ ((noreturn));
      83                 : #endif
      84                 : 
      85                 : static void zend_mm_panic(const char *message) /* {{{ */
      86               0 : {
      87               0 :         fprintf(stderr, "%s\n", message);
      88                 : #if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID)
      89                 :         kill(getpid(), SIGSEGV);
      90                 : #endif
      91               0 :         exit(1);
      92                 : }
      93                 : /* }}} */
      94                 : 
      95                 : /*******************/
      96                 : /* Storage Manager */
      97                 : /*******************/
      98                 : 
      99                 : #ifdef ZEND_WIN32
     100                 : #  define HAVE_MEM_WIN32    /* use VirtualAlloc() to allocate memory     */
     101                 : #endif
     102                 : #define HAVE_MEM_MALLOC     /* use malloc() to allocate segments         */
     103                 : 
     104                 : #include <sys/types.h>
     105                 : #include <sys/stat.h>
     106                 : #if HAVE_LIMITS_H
     107                 : #include <limits.h>
     108                 : #endif
     109                 : #include <fcntl.h>
     110                 : #include <errno.h>
     111                 : 
     112                 : #if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
     113                 : # ifdef HAVE_MREMAP
     114                 : #  ifndef _GNU_SOURCE
     115                 : #   define _GNU_SOURCE
     116                 : #  endif
     117                 : #  ifndef __USE_GNU
     118                 : #   define __USE_GNU
     119                 : #  endif
     120                 : # endif
     121                 : # include <sys/mman.h>
     122                 : # ifndef MAP_ANON
     123                 : #  ifdef MAP_ANONYMOUS
     124                 : #   define MAP_ANON MAP_ANONYMOUS
     125                 : #  endif
     126                 : # endif
     127                 : # ifndef MREMAP_MAYMOVE
     128                 : #  define MREMAP_MAYMOVE 0
     129                 : # endif
     130                 : # ifndef MAP_FAILED
     131                 : #  define MAP_FAILED ((void*)-1)
     132                 : # endif
     133                 : #endif
     134                 : 
     135                 : static zend_mm_storage* zend_mm_mem_dummy_init(void *params) /* {{{ */
     136           17007 : {
     137           17007 :         return malloc(sizeof(zend_mm_storage));
     138                 : }
     139                 : /* }}} */
     140                 : 
     141                 : static void zend_mm_mem_dummy_dtor(zend_mm_storage *storage) /* {{{ */
     142           17039 : {
     143           17039 :         free(storage);
     144           17039 : }
     145                 : /* }}} */
     146                 : 
     147                 : static void zend_mm_mem_dummy_compact(zend_mm_storage *storage) /* {{{ */
     148               1 : {
     149               1 : }
     150                 : /* }}} */
     151                 : 
     152                 : #if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO)
     153                 : 
     154                 : static zend_mm_segment* zend_mm_mem_mmap_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size) /* {{{ */
     155               0 : {
     156                 :         zend_mm_segment *ret;
     157                 : #ifdef HAVE_MREMAP
     158                 : #if defined(__NetBSD__)
     159                 :         /* NetBSD 5 supports mremap but takes an extra newp argument */
     160                 :         ret = (zend_mm_segment*)mremap(segment, segment->size, segment, size, MREMAP_MAYMOVE);
     161                 : #else
     162               0 :         ret = (zend_mm_segment*)mremap(segment, segment->size, size, MREMAP_MAYMOVE);
     163                 : #endif
     164               0 :         if (ret == MAP_FAILED) {
     165                 : #endif
     166               0 :                 ret = storage->handlers->_alloc(storage, size);
     167               0 :                 if (ret) {
     168               0 :                         memcpy(ret, segment, size > segment->size ? segment->size : size);
     169               0 :                         storage->handlers->_free(storage, segment);
     170                 :                 }
     171                 : #ifdef HAVE_MREMAP
     172                 :         }
     173                 : #endif
     174               0 :         return ret;
     175                 : }
     176                 : /* }}} */
     177                 : 
     178                 : static void zend_mm_mem_mmap_free(zend_mm_storage *storage, zend_mm_segment* segment) /* {{{ */
     179               0 : {
     180               0 :         munmap((void*)segment, segment->size);
     181               0 : }
     182                 : /* }}} */
     183                 : 
     184                 : #endif
     185                 : 
     186                 : #ifdef HAVE_MEM_MMAP_ANON
     187                 : 
     188                 : static zend_mm_segment* zend_mm_mem_mmap_anon_alloc(zend_mm_storage *storage, size_t size) /* {{{ */
     189               0 : {
     190               0 :         zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
     191               0 :         if (ret == MAP_FAILED) {
     192               0 :                 ret = NULL;
     193                 :         }
     194               0 :         return ret;
     195                 : }
     196                 : /* }}} */
     197                 : 
     198                 : # define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
     199                 : 
     200                 : #endif
     201                 : 
     202                 : #ifdef HAVE_MEM_MMAP_ZERO
     203                 : 
     204                 : static int zend_mm_dev_zero_fd = -1;
     205                 : 
     206                 : static zend_mm_storage* zend_mm_mem_mmap_zero_init(void *params) /* {{{ */
     207               0 : {
     208               0 :         if (zend_mm_dev_zero_fd != -1) {
     209               0 :                 zend_mm_dev_zero_fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
     210                 :         }
     211               0 :         if (zend_mm_dev_zero_fd >= 0) {
     212               0 :                 return malloc(sizeof(zend_mm_storage));
     213                 :         } else {
     214               0 :                 return NULL;
     215                 :         }
     216                 : }
     217                 : /* }}} */
     218                 : 
     219                 : static void zend_mm_mem_mmap_zero_dtor(zend_mm_storage *storage) /* {{{ */
     220               0 : {
     221               0 :         close(zend_mm_dev_zero_fd);
     222               0 :         free(storage);
     223               0 : }
     224                 : /* }}} */
     225                 : 
     226                 : static zend_mm_segment* zend_mm_mem_mmap_zero_alloc(zend_mm_storage *storage, size_t size) /* {{{ */
     227               0 : {
     228               0 :         zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0);
     229               0 :         if (ret == MAP_FAILED) {
     230               0 :                 ret = NULL;
     231                 :         }
     232               0 :         return ret;
     233                 : }
     234                 : /* }}} */
     235                 : 
     236                 : # define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}
     237                 : 
     238                 : #endif
     239                 : 
     240                 : #ifdef HAVE_MEM_WIN32
     241                 : 
     242                 : static zend_mm_storage* zend_mm_mem_win32_init(void *params) /* {{{ */
     243                 : {
     244                 :         HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
     245                 :         zend_mm_storage* storage;
     246                 : 
     247                 :         if (heap == NULL) {
     248                 :                 return NULL;
     249                 :         }
     250                 :         storage = (zend_mm_storage*)malloc(sizeof(zend_mm_storage));
     251                 :         storage->data = (void*) heap;
     252                 :         return storage;
     253                 : }
     254                 : /* }}} */
     255                 : 
     256                 : static void zend_mm_mem_win32_dtor(zend_mm_storage *storage) /* {{{ */
     257                 : {
     258                 :         HeapDestroy((HANDLE)storage->data);
     259                 :         free(storage);
     260                 : }
     261                 : /* }}} */
     262                 : 
     263                 : static void zend_mm_mem_win32_compact(zend_mm_storage *storage) /* {{{ */
     264                 : {
     265                 :     HeapDestroy((HANDLE)storage->data);
     266                 :     storage->data = (void*)HeapCreate(HEAP_NO_SERIALIZE, 0, 0);
     267                 : }
     268                 : /* }}} */
     269                 : 
     270                 : static zend_mm_segment* zend_mm_mem_win32_alloc(zend_mm_storage *storage, size_t size) /* {{{ */
     271                 : {
     272                 :         return (zend_mm_segment*) HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size);
     273                 : }
     274                 : /* }}} */
     275                 : 
     276                 : static void zend_mm_mem_win32_free(zend_mm_storage *storage, zend_mm_segment* segment) /* {{{ */
     277                 : {
     278                 :         HeapFree((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment);
     279                 : }
     280                 : /* }}} */
     281                 : 
     282                 : static zend_mm_segment* zend_mm_mem_win32_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size) /* {{{ */
     283                 : {
     284                 :         return (zend_mm_segment*) HeapReAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment, size);
     285                 : }
     286                 : /* }}} */
     287                 : 
     288                 : # define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free}
     289                 : 
     290                 : #endif
     291                 : 
     292                 : #ifdef HAVE_MEM_MALLOC
     293                 : 
     294                 : static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size) /* {{{ */
     295           57540 : {
     296           57540 :         return (zend_mm_segment*)malloc(size);
     297                 : }
     298                 : /* }}} */
     299                 : 
     300                 : static zend_mm_segment* zend_mm_mem_malloc_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size) /* {{{ */
     301               8 : {
     302               8 :         return (zend_mm_segment*)realloc(ptr, size);
     303                 : }
     304                 : /* }}} */
     305                 : 
     306                 : static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr) /* {{{ */
     307           57572 : {
     308           57572 :         free(ptr);
     309           57572 : }
     310                 : /* }}} */
     311                 : 
     312                 : # define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}
     313                 : 
     314                 : #endif
     315                 : 
     316                 : static const zend_mm_mem_handlers mem_handlers[] = {
     317                 : #ifdef HAVE_MEM_WIN32
     318                 :         ZEND_MM_MEM_WIN32_DSC,
     319                 : #endif
     320                 : #ifdef HAVE_MEM_MALLOC
     321                 :         ZEND_MM_MEM_MALLOC_DSC,
     322                 : #endif
     323                 : #ifdef HAVE_MEM_MMAP_ANON
     324                 :         ZEND_MM_MEM_MMAP_ANON_DSC,
     325                 : #endif
     326                 : #ifdef HAVE_MEM_MMAP_ZERO
     327                 :         ZEND_MM_MEM_MMAP_ZERO_DSC,
     328                 : #endif
     329                 :         {NULL, NULL, NULL, NULL, NULL, NULL}
     330                 : };
     331                 : 
     332                 : # define ZEND_MM_STORAGE_DTOR()                                         heap->storage->handlers->dtor(heap->storage)
     333                 : # define ZEND_MM_STORAGE_ALLOC(size)                            heap->storage->handlers->_alloc(heap->storage, size)
     334                 : # define ZEND_MM_STORAGE_REALLOC(ptr, size)                     heap->storage->handlers->_realloc(heap->storage, ptr, size)
     335                 : # define ZEND_MM_STORAGE_FREE(ptr)                                      heap->storage->handlers->_free(heap->storage, ptr)
     336                 : 
     337                 : /****************/
     338                 : /* Heap Manager */
     339                 : /****************/
     340                 : 
     341                 : #define MEM_BLOCK_VALID  0x7312F8DC
     342                 : #define MEM_BLOCK_FREED  0x99954317
     343                 : #define MEM_BLOCK_CACHED 0xFB8277DC
     344                 : #define MEM_BLOCK_GUARD  0x2A8FCC84
     345                 : #define MEM_BLOCK_LEAK   0x6C5E8F2D
     346                 : 
     347                 : /* mm block type */
     348                 : typedef struct _zend_mm_block_info {
     349                 : #if ZEND_MM_COOKIES
     350                 :         size_t _cookie;
     351                 : #endif
     352                 :         size_t _size;
     353                 :         size_t _prev;
     354                 : } zend_mm_block_info;
     355                 : 
     356                 : #if ZEND_DEBUG
     357                 : 
     358                 : typedef struct _zend_mm_debug_info {
     359                 :         char *filename;
     360                 :         uint lineno;
     361                 :         char *orig_filename;
     362                 :         uint orig_lineno;
     363                 :         size_t size;
     364                 : #if ZEND_MM_HEAP_PROTECTION
     365                 :         unsigned int start_magic;
     366                 : #endif
     367                 : } zend_mm_debug_info;
     368                 : 
     369                 : #elif ZEND_MM_HEAP_PROTECTION
     370                 : 
     371                 : typedef struct _zend_mm_debug_info {
     372                 :         size_t size;
     373                 :         unsigned int start_magic;
     374                 : } zend_mm_debug_info;
     375                 : 
     376                 : #endif
     377                 : 
     378                 : typedef struct _zend_mm_block {
     379                 :         zend_mm_block_info info;
     380                 : #if ZEND_DEBUG
     381                 :         unsigned int magic;
     382                 : # ifdef ZTS
     383                 :         THREAD_T thread_id;
     384                 : # endif
     385                 :         zend_mm_debug_info debug;
     386                 : #elif ZEND_MM_HEAP_PROTECTION
     387                 :         zend_mm_debug_info debug;
     388                 : #endif
     389                 : } zend_mm_block;
     390                 : 
     391                 : typedef struct _zend_mm_small_free_block {
     392                 :         zend_mm_block_info info;
     393                 : #if ZEND_DEBUG
     394                 :         unsigned int magic;
     395                 : # ifdef ZTS
     396                 :         THREAD_T thread_id;
     397                 : # endif
     398                 : #endif
     399                 :         struct _zend_mm_free_block *prev_free_block;
     400                 :         struct _zend_mm_free_block *next_free_block;
     401                 : } zend_mm_small_free_block;
     402                 : 
     403                 : typedef struct _zend_mm_free_block {
     404                 :         zend_mm_block_info info;
     405                 : #if ZEND_DEBUG
     406                 :         unsigned int magic;
     407                 : # ifdef ZTS
     408                 :         THREAD_T thread_id;
     409                 : # endif
     410                 : #endif
     411                 :         struct _zend_mm_free_block *prev_free_block;
     412                 :         struct _zend_mm_free_block *next_free_block;
     413                 : 
     414                 :         struct _zend_mm_free_block **parent;
     415                 :         struct _zend_mm_free_block *child[2];
     416                 : } zend_mm_free_block;
     417                 : 
     418                 : #define ZEND_MM_NUM_BUCKETS (sizeof(size_t) << 3)
     419                 : 
     420                 : #define ZEND_MM_CACHE 1
     421                 : #define ZEND_MM_CACHE_SIZE (ZEND_MM_NUM_BUCKETS * 4 * 1024)
     422                 : 
     423                 : #ifndef ZEND_MM_CACHE_STAT
     424                 : # define ZEND_MM_CACHE_STAT 0
     425                 : #endif
     426                 : 
     427                 : struct _zend_mm_heap {
     428                 :         int                 use_zend_alloc;
     429                 :         void               *(*_malloc)(size_t);
     430                 :         void                (*_free)(void*);
     431                 :         void               *(*_realloc)(void*, size_t);
     432                 :         size_t              free_bitmap;
     433                 :         size_t              large_free_bitmap;
     434                 :         size_t              block_size;
     435                 :         size_t              compact_size;
     436                 :         zend_mm_segment    *segments_list;
     437                 :         zend_mm_storage    *storage;
     438                 :         size_t              real_size;
     439                 :         size_t              real_peak;
     440                 :         size_t              limit;
     441                 :         size_t              size;
     442                 :         size_t              peak;
     443                 :         size_t              reserve_size;
     444                 :         void               *reserve;
     445                 :         int                 overflow;
     446                 :         int                 internal;
     447                 : #if ZEND_MM_CACHE
     448                 :         unsigned int        cached;
     449                 :         zend_mm_free_block *cache[ZEND_MM_NUM_BUCKETS];
     450                 : #endif
     451                 :         zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2];
     452                 :         zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS];
     453                 :         zend_mm_free_block *rest_buckets[2];
     454                 : #if ZEND_MM_CACHE_STAT
     455                 :         struct {
     456                 :                 int count;
     457                 :                 int max_count;
     458                 :                 int hit;
     459                 :                 int miss;
     460                 :         } cache_stat[ZEND_MM_NUM_BUCKETS+1];
     461                 : #endif
     462                 : };
     463                 : 
     464                 : #define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \
     465                 :         (zend_mm_free_block*) ((char*)&heap->free_buckets[index * 2] + \
     466                 :                 sizeof(zend_mm_free_block*) * 2 - \
     467                 :                 sizeof(zend_mm_small_free_block))
     468                 : 
     469                 : #define ZEND_MM_REST_BUCKET(heap) \
     470                 :         (zend_mm_free_block*)((char*)&heap->rest_buckets[0] + \
     471                 :                 sizeof(zend_mm_free_block*) * 2 - \
     472                 :                 sizeof(zend_mm_small_free_block))
     473                 : 
     474                 : #if ZEND_MM_COOKIES
     475                 : 
     476                 : static unsigned int _zend_mm_cookie = 0;
     477                 : 
     478                 : # define ZEND_MM_COOKIE(block) \
     479                 :         (((size_t)(block)) ^ _zend_mm_cookie)
     480                 : # define ZEND_MM_SET_COOKIE(block) \
     481                 :         (block)->info._cookie = ZEND_MM_COOKIE(block)
     482                 : # define ZEND_MM_CHECK_COOKIE(block) \
     483                 :         if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \
     484                 :                 zend_mm_panic("zend_mm_heap corrupted"); \
     485                 :         }
     486                 : #else
     487                 : # define ZEND_MM_SET_COOKIE(block)
     488                 : # define ZEND_MM_CHECK_COOKIE(block)
     489                 : #endif
     490                 : 
     491                 : /* Default memory segment size */
     492                 : #define ZEND_MM_SEG_SIZE   (256 * 1024)
     493                 : 
     494                 : /* Reserved space for error reporting in case of memory overflow */
     495                 : #define ZEND_MM_RESERVE_SIZE            (8*1024)
     496                 : 
     497                 : #ifdef _WIN64
     498                 : # define ZEND_MM_LONG_CONST(x)  (x##i64)
     499                 : #else
     500                 : # define ZEND_MM_LONG_CONST(x)  (x##L)
     501                 : #endif
     502                 : 
     503                 : #define ZEND_MM_TYPE_MASK               ZEND_MM_LONG_CONST(0x3)
     504                 : 
     505                 : #define ZEND_MM_FREE_BLOCK              ZEND_MM_LONG_CONST(0x0)
     506                 : #define ZEND_MM_USED_BLOCK              ZEND_MM_LONG_CONST(0x1)
     507                 : #define ZEND_MM_GUARD_BLOCK             ZEND_MM_LONG_CONST(0x3)
     508                 : 
     509                 : #define ZEND_MM_BLOCK(b, type, size)    do { \
     510                 :                                                                                         size_t _size = (size); \
     511                 :                                                                                         (b)->info._size = (type) | _size; \
     512                 :                                                                                         ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \
     513                 :                                                                                         ZEND_MM_SET_COOKIE(b); \
     514                 :                                                                                 } while (0);
     515                 : #define ZEND_MM_LAST_BLOCK(b)                   do { \
     516                 :                 (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \
     517                 :                 ZEND_MM_SET_MAGIC(b, MEM_BLOCK_GUARD); \
     518                 :         } while (0);
     519                 : #define ZEND_MM_BLOCK_SIZE(b)                   ((b)->info._size & ~ZEND_MM_TYPE_MASK)
     520                 : #define ZEND_MM_IS_FREE_BLOCK(b)                (!((b)->info._size & ZEND_MM_USED_BLOCK))
     521                 : #define ZEND_MM_IS_USED_BLOCK(b)                ((b)->info._size & ZEND_MM_USED_BLOCK)
     522                 : #define ZEND_MM_IS_GUARD_BLOCK(b)               (((b)->info._size & ZEND_MM_TYPE_MASK) == ZEND_MM_GUARD_BLOCK)
     523                 : 
     524                 : #define ZEND_MM_NEXT_BLOCK(b)                   ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b))
     525                 : #define ZEND_MM_PREV_BLOCK(b)                   ZEND_MM_BLOCK_AT(b, -(int)((b)->info._prev & ~ZEND_MM_TYPE_MASK))
     526                 : 
     527                 : #define ZEND_MM_PREV_BLOCK_IS_FREE(b)   (!((b)->info._prev & ZEND_MM_USED_BLOCK))
     528                 : 
     529                 : #define ZEND_MM_MARK_FIRST_BLOCK(b)             ((b)->info._prev = ZEND_MM_GUARD_BLOCK)
     530                 : #define ZEND_MM_IS_FIRST_BLOCK(b)               ((b)->info._prev == ZEND_MM_GUARD_BLOCK)
     531                 : 
     532                 : /* optimized access */
     533                 : #define ZEND_MM_FREE_BLOCK_SIZE(b)              (b)->info._size
     534                 : 
     535                 : /* Aligned header size */
     536                 : #define ZEND_MM_ALIGNED_HEADER_SIZE                     ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
     537                 : #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE        ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block))
     538                 : #define ZEND_MM_MIN_ALLOC_BLOCK_SIZE            ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE)
     539                 : #define ZEND_MM_ALIGNED_MIN_HEADER_SIZE         (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE)
     540                 : #define ZEND_MM_ALIGNED_SEGMENT_SIZE            ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
     541                 : 
     542                 : #define ZEND_MM_MIN_SIZE                                        ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)):0)
     543                 : 
     544                 : #define ZEND_MM_MAX_SMALL_SIZE                          ((ZEND_MM_NUM_BUCKETS<<ZEND_MM_ALIGNMENT_LOG2)+ZEND_MM_ALIGNED_MIN_HEADER_SIZE)
     545                 : 
     546                 : #define ZEND_MM_TRUE_SIZE(size)                         ((size<ZEND_MM_MIN_SIZE)?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE):(ZEND_MM_ALIGNED_SIZE(size+ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)))
     547                 : 
     548                 : #define ZEND_MM_BUCKET_INDEX(true_size)         ((true_size>>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2))
     549                 : 
     550                 : #define ZEND_MM_SMALL_SIZE(true_size)           (true_size < ZEND_MM_MAX_SMALL_SIZE)
     551                 : 
     552                 : /* Memory calculations */
     553                 : #define ZEND_MM_BLOCK_AT(blk, offset)   ((zend_mm_block *) (((char *) (blk))+(offset)))
     554                 : #define ZEND_MM_DATA_OF(p)                              ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE))
     555                 : #define ZEND_MM_HEADER_OF(blk)                  ZEND_MM_BLOCK_AT(blk, -(int)ZEND_MM_ALIGNED_HEADER_SIZE)
     556                 : 
     557                 : /* Debug output */
     558                 : #if ZEND_DEBUG
     559                 : 
     560                 : # ifdef ZTS
     561                 : #  define ZEND_MM_SET_THREAD_ID(block) \
     562                 :         ((zend_mm_block*)(block))->thread_id = tsrm_thread_id()
     563                 : #  define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id())
     564                 : # else
     565                 : #  define ZEND_MM_SET_THREAD_ID(block)
     566                 : #  define ZEND_MM_BAD_THREAD_ID(block) 0
     567                 : # endif
     568                 : 
     569                 : # define ZEND_MM_VALID_PTR(block) \
     570                 :         zend_mm_check_ptr(heap, block, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
     571                 : 
     572                 : # define ZEND_MM_SET_MAGIC(block, val) do { \
     573                 :                 (block)->magic = (val); \
     574                 :         } while (0)
     575                 : 
     576                 : # define ZEND_MM_CHECK_MAGIC(block, val) do { \
     577                 :                 if ((block)->magic != (val)) { \
     578                 :                         zend_mm_panic("zend_mm_heap corrupted"); \
     579                 :                 } \
     580                 :         } while (0)
     581                 : 
     582                 : # define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \
     583                 :                 ((zend_mm_block*)(block))->debug.filename = __zend_filename; \
     584                 :                 ((zend_mm_block*)(block))->debug.lineno = __zend_lineno; \
     585                 :                 ((zend_mm_block*)(block))->debug.orig_filename = __zend_orig_filename; \
     586                 :                 ((zend_mm_block*)(block))->debug.orig_lineno = __zend_orig_lineno; \
     587                 :                 ZEND_MM_SET_BLOCK_SIZE(block, __size); \
     588                 :                 if (set_valid) { \
     589                 :                         ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \
     590                 :                 } \
     591                 :                 if (set_thread) { \
     592                 :                         ZEND_MM_SET_THREAD_ID(block); \
     593                 :                 } \
     594                 :         } while (0)
     595                 : 
     596                 : #else
     597                 : 
     598                 : # define ZEND_MM_VALID_PTR(ptr) EXPECTED(ptr != NULL)
     599                 : 
     600                 : # define ZEND_MM_SET_MAGIC(block, val)
     601                 : 
     602                 : # define ZEND_MM_CHECK_MAGIC(block, val)
     603                 : 
     604                 : # define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size)
     605                 : 
     606                 : #endif
     607                 : 
     608                 : 
     609                 : #if ZEND_MM_HEAP_PROTECTION
     610                 : 
     611                 : # define ZEND_MM_CHECK_PROTECTION(block) \
     612                 :         do { \
     613                 :                 if ((block)->debug.start_magic != _mem_block_start_magic || \
     614                 :                     memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \
     615                 :                     zend_mm_panic("zend_mm_heap corrupted"); \
     616                 :                 } \
     617                 :         } while (0)
     618                 : 
     619                 : # define ZEND_MM_END_MAGIC_PTR(block) \
     620                 :         (((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->debug.size)
     621                 : 
     622                 : # define END_MAGIC_SIZE sizeof(unsigned int)
     623                 : 
     624                 : # define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \
     625                 :                 char *p; \
     626                 :                 ((zend_mm_block*)(block))->debug.size = (__size); \
     627                 :                 p = ZEND_MM_END_MAGIC_PTR(block); \
     628                 :                 ((zend_mm_block*)(block))->debug.start_magic = _mem_block_start_magic; \
     629                 :                 memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \
     630                 :         } while (0)
     631                 : 
     632                 : static unsigned int _mem_block_start_magic = 0;
     633                 : static unsigned int _mem_block_end_magic   = 0;
     634                 : 
     635                 : #else
     636                 : 
     637                 : # if ZEND_DEBUG
     638                 : #  define ZEND_MM_SET_BLOCK_SIZE(block, _size) \
     639                 :         ((zend_mm_block*)(block))->debug.size = (_size)
     640                 : # else
     641                 : #  define ZEND_MM_SET_BLOCK_SIZE(block, _size)
     642                 : # endif
     643                 : 
     644                 : # define ZEND_MM_CHECK_PROTECTION(block)
     645                 : 
     646                 : # define END_MAGIC_SIZE 0
     647                 : 
     648                 : #endif
     649                 : 
     650                 : #if ZEND_MM_SAFE_UNLINKING
     651                 : # define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \
     652                 :         if (UNEXPECTED((block)->info._size != ZEND_MM_BLOCK_AT(block, ZEND_MM_FREE_BLOCK_SIZE(block))->info._prev) || \
     653                 :                 UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \
     654                 :             UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \
     655                 :             zend_mm_panic("zend_mm_heap corrupted"); \
     656                 :         }
     657                 : #define ZEND_MM_CHECK_TREE(block) \
     658                 :         if (UNEXPECTED(*((block)->parent) != (block))) { \
     659                 :                 zend_mm_panic("zend_mm_heap corrupted"); \
     660                 :         }
     661                 : #else
     662                 : # define ZEND_MM_CHECK_BLOCK_LINKAGE(block)
     663                 : # define ZEND_MM_CHECK_TREE(block)
     664                 : #endif
     665                 : 
     666                 : #define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S)
     667                 : 
     668                 : static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
     669                 : static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
     670                 : static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
     671                 : 
     672                 : static inline unsigned int zend_mm_high_bit(size_t _size) /* {{{ */
     673        60072752 : {
     674                 : #if defined(__GNUC__) && defined(i386)
     675                 :         unsigned int n;
     676                 : 
     677        60072752 :         __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm"  (_size));
     678        60072752 :         return n;
     679                 : #elif defined(__GNUC__) && defined(__x86_64__)
     680                 :         unsigned long n;
     681                 : 
     682                 :         __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm"  (_size));
     683                 :         return (unsigned int)n;
     684                 : #elif defined(_MSC_VER) && defined(_M_IX86)
     685                 :         __asm {
     686                 :                 bsr eax, _size
     687                 :         }
     688                 : #else
     689                 :         unsigned int n = 0;
     690                 :         while (_size != 0) {
     691                 :                 _size = _size >> 1;
     692                 :                 n++;
     693                 :         }
     694                 :         return n-1;
     695                 : #endif
     696                 : }
     697                 : /* }}} */
     698                 : 
     699                 : static inline unsigned int zend_mm_low_bit(size_t _size) /* {{{ */
     700        48117238 : {
     701                 : #if defined(__GNUC__) && defined(i386)
     702                 :         unsigned int n;
     703                 : 
     704        48117238 :         __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm"  (_size));
     705        48117238 :         return n;
     706                 : #elif defined(__GNUC__) && defined(__x86_64__)
     707                 :         unsigned long n;
     708                 : 
     709                 :         __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm"  (_size));
     710                 :         return (unsigned int)n;
     711                 : #elif defined(_MSC_VER) && defined(_M_IX86)
     712                 :         __asm {
     713                 :                 bsf eax, _size
     714                 :    }
     715                 : #else
     716                 :         static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
     717                 :         unsigned int n;
     718                 :         unsigned int index = 0;
     719                 : 
     720                 :         n = offset[_size & 15];
     721                 :         while (n == 4) {
     722                 :                 _size >>= 4;
     723                 :                 index += n;
     724                 :                 n = offset[_size & 15];
     725                 :         }
     726                 : 
     727                 :         return index + n;
     728                 : #endif
     729                 : }
     730                 : /* }}} */
     731                 : 
     732                 : static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) /* {{{ */
     733           52651 : {
     734                 :         zend_mm_free_block *prev, *next;
     735                 : 
     736                 :         ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
     737                 : 
     738           52651 :         if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
     739           52626 :                 mm_block->parent = NULL;
     740                 :         }
     741                 : 
     742           52651 :         prev = heap->rest_buckets[0];
     743           52651 :         next = prev->next_free_block;
     744           52651 :         mm_block->prev_free_block = prev;
     745           52651 :         mm_block->next_free_block = next;
     746           52651 :         prev->next_free_block = next->prev_free_block = mm_block;
     747           52651 : }
     748                 : /* }}} */
     749                 : 
     750                 : static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) /* {{{ */
     751        75572891 : {
     752                 :         size_t size;
     753                 :         size_t index;
     754                 : 
     755                 :         ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
     756                 : 
     757        75572891 :         size = ZEND_MM_FREE_BLOCK_SIZE(mm_block);
     758        75572891 :         if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) {
     759                 :                 zend_mm_free_block **p;
     760                 : 
     761        25288961 :                 index = ZEND_MM_LARGE_BUCKET_INDEX(size);
     762        25288961 :                 p = &heap->large_free_buckets[index];
     763        25288961 :                 mm_block->child[0] = mm_block->child[1] = NULL;
     764        25288961 :                 if (!*p) {
     765        15190087 :                         *p = mm_block;
     766        15190087 :                         mm_block->parent = p;
     767        15190087 :                         mm_block->prev_free_block = mm_block->next_free_block = mm_block;
     768        15190087 :                         heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
     769                 :                 } else {
     770                 :                         size_t m;
     771                 : 
     772        23788233 :                         for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
     773        23788233 :                                 zend_mm_free_block *prev = *p;
     774                 : 
     775        23788233 :                                 if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) {
     776        22642025 :                                         p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1];
     777        22642025 :                                         if (!*p) {
     778         8952666 :                                                 *p = mm_block;
     779         8952666 :                                                 mm_block->parent = p;
     780         8952666 :                                                 mm_block->prev_free_block = mm_block->next_free_block = mm_block;
     781         8952666 :                                                 break;
     782                 :                                         }
     783                 :                                 } else {
     784         1146208 :                                         zend_mm_free_block *next = prev->next_free_block;
     785                 : 
     786         1146208 :                                         prev->next_free_block = next->prev_free_block = mm_block;
     787         1146208 :                                         mm_block->next_free_block = next;
     788         1146208 :                                         mm_block->prev_free_block = prev;
     789         1146208 :                                         mm_block->parent = NULL;
     790         1146208 :                                         break;
     791                 :                                 }
     792        13689359 :                         }
     793                 :                 }
     794                 :         } else {
     795                 :                 zend_mm_free_block *prev, *next;
     796                 : 
     797        50283930 :                 index = ZEND_MM_BUCKET_INDEX(size);
     798                 : 
     799        50283930 :                 prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
     800        50283930 :                 if (prev->prev_free_block == prev) {
     801        20811709 :                         heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
     802                 :                 }
     803        50283930 :                 next = prev->next_free_block;
     804                 : 
     805        50283930 :                 mm_block->prev_free_block = prev;
     806        50283930 :                 mm_block->next_free_block = next;
     807        50283930 :                 prev->next_free_block = next->prev_free_block = mm_block;
     808                 :         }
     809        75572891 : }
     810                 : /* }}} */
     811                 : 
     812                 : static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) /* {{{ */
     813        75570710 : {
     814        75570710 :         zend_mm_free_block *prev = mm_block->prev_free_block;
     815        75570710 :         zend_mm_free_block *next = mm_block->next_free_block;
     816                 : 
     817                 :         ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
     818                 : 
     819        75570710 :         if (EXPECTED(prev == mm_block)) {
     820                 :                 zend_mm_free_block **rp, **cp;
     821                 : 
     822                 : #if ZEND_MM_SAFE_UNLINKING
     823        24090520 :                 if (UNEXPECTED(next != mm_block)) {
     824               0 :                         zend_mm_panic("zend_mm_heap corrupted");
     825                 :                 }
     826                 : #endif
     827                 : 
     828        24090520 :                 rp = &mm_block->child[mm_block->child[1] != NULL];
     829        24090520 :                 prev = *rp;
     830        24090520 :                 if (EXPECTED(prev == NULL)) {
     831        19774960 :                         size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
     832                 : 
     833        19774960 :                         ZEND_MM_CHECK_TREE(mm_block);
     834        19774960 :                         *mm_block->parent = NULL;
     835        19774960 :                         if (mm_block->parent == &heap->large_free_buckets[index]) {
     836        15139014 :                                 heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
     837                 :                     }
     838                 :                 } else {
     839        13037284 :                         while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) {
     840         4406164 :                                 prev = *cp;
     841         4406164 :                                 rp = cp;
     842                 :                         }
     843         4315560 :                         *rp = NULL;
     844                 : 
     845         4393034 : subst_block:
     846         4393034 :                         ZEND_MM_CHECK_TREE(mm_block);
     847         4393034 :                         *mm_block->parent = prev;
     848         4393034 :                         prev->parent = mm_block->parent;
     849         4393034 :                         if ((prev->child[0] = mm_block->child[0])) {
     850         2362605 :                                 ZEND_MM_CHECK_TREE(prev->child[0]);
     851         2362605 :                                 prev->child[0]->parent = &prev->child[0];
     852                 :                         }
     853         4393034 :                         if ((prev->child[1] = mm_block->child[1])) {
     854          284142 :                                 ZEND_MM_CHECK_TREE(prev->child[1]);
     855          284142 :                                 prev->child[1]->parent = &prev->child[1];
     856                 :                         }
     857                 :                 }
     858                 :         } else {
     859                 : 
     860                 : #if ZEND_MM_SAFE_UNLINKING
     861        51480190 :                 if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
     862               0 :                         zend_mm_panic("zend_mm_heap corrupted");
     863                 :                 }
     864                 : #endif
     865                 : 
     866        51480190 :                 prev->next_free_block = next;
     867        51480190 :                 next->prev_free_block = prev;
     868                 : 
     869        51480190 :                 if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
     870        50283579 :                         if (EXPECTED(prev == next)) {
     871        20811682 :                                 size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
     872                 : 
     873        20811682 :                                 if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) {
     874        20811679 :                                         heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
     875                 :                                 }
     876                 :                         }
     877         1196611 :                 } else if (UNEXPECTED(mm_block->parent != NULL)) {
     878           77474 :                         goto subst_block;
     879                 :                 }
     880                 :         }
     881        75570710 : }
     882                 : /* }}} */
     883                 : 
     884                 : static inline void zend_mm_init(zend_mm_heap *heap) /* {{{ */
     885           51039 : {
     886                 :         zend_mm_free_block* p;
     887                 :         int i;
     888                 : 
     889           51039 :         heap->free_bitmap = 0;
     890           51039 :         heap->large_free_bitmap = 0;
     891                 : #if ZEND_MM_CACHE
     892           51039 :         heap->cached = 0;
     893           51039 :         memset(heap->cache, 0, sizeof(heap->cache));
     894                 : #endif
     895                 : #if ZEND_MM_CACHE_STAT
     896                 :         for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
     897                 :                 heap->cache_stat[i].count = 0;
     898                 :         }
     899                 : #endif
     900           51039 :         p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
     901         1684287 :         for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
     902         1633248 :                 p->next_free_block = p;
     903         1633248 :                 p->prev_free_block = p;
     904         1633248 :                 p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
     905         1633248 :                 heap->large_free_buckets[i] = NULL;
     906                 :         }
     907           51039 :         heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
     908           51039 : }
     909                 : /* }}} */
     910                 : 
     911                 : static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment) /* {{{ */
     912            6464 : {
     913            6464 :         zend_mm_segment **p = &heap->segments_list;
     914                 : 
     915           13241 :         while (*p != segment) {
     916             313 :                 p = &(*p)->next_segment;
     917                 :         }
     918            6464 :         *p = segment->next_segment;
     919            6464 :         heap->real_size -= segment->size;
     920            6464 :         ZEND_MM_STORAGE_FREE(segment);
     921            6464 : }
     922                 : /* }}} */
     923                 : 
     924                 : #if ZEND_MM_CACHE
     925                 : static void zend_mm_free_cache(zend_mm_heap *heap) /* {{{ */
     926               0 : {
     927                 :         int i;
     928                 : 
     929               0 :         for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
     930               0 :                 if (heap->cache[i]) {
     931               0 :                         zend_mm_free_block *mm_block = heap->cache[i];
     932                 : 
     933               0 :                         while (mm_block) {
     934               0 :                                 size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
     935               0 :                                 zend_mm_free_block *q = mm_block->prev_free_block;
     936               0 :                                 zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
     937                 : 
     938               0 :                                 heap->cached -= size;
     939                 : 
     940               0 :                                 if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
     941               0 :                                         mm_block = (zend_mm_free_block*)ZEND_MM_PREV_BLOCK(mm_block);
     942               0 :                                         size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
     943               0 :                                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) mm_block);
     944                 :                                 }
     945               0 :                                 if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
     946               0 :                                         size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
     947               0 :                                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
     948                 :                                 }
     949               0 :                                 ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
     950                 : 
     951               0 :                                 if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
     952                 :                                     ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) {
     953               0 :                                         zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
     954                 :                                 } else {
     955               0 :                                         zend_mm_add_to_free_list(heap, (zend_mm_free_block *) mm_block);
     956                 :                                 }
     957                 : 
     958               0 :                                 mm_block = q;
     959                 :                         }
     960               0 :                         heap->cache[i] = NULL;
     961                 : #if ZEND_MM_CACHE_STAT
     962                 :                         heap->cache_stat[i].count = 0;
     963                 : #endif
     964                 :                 }
     965                 :         }
     966               0 : }
     967                 : /* }}} */
     968                 : #endif
     969                 : 
     970                 : #if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES
     971                 : static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
     972                 : {
     973                 :         size_t i = 0;
     974                 :         unsigned char t;
     975                 : 
     976                 : #ifdef ZEND_WIN32
     977                 :         HCRYPTPROV   hCryptProv;
     978                 : 
     979                 :         if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
     980                 :                 do {
     981                 :                         BOOL ret = CryptGenRandom(hCryptProv, size, buf);
     982                 :                         CryptReleaseContext(hCryptProv, 0);
     983                 :                         if (ret) {
     984                 :                                 while (i < size && buf[i] != 0) {
     985                 :                                         i++;
     986                 :                                 }
     987                 :                                 if (i == size) {
     988                 :                                     return;
     989                 :                                 }
     990                 :                    }
     991                 :                 } while (0);
     992                 :         }
     993                 : #elif defined(HAVE_DEV_URANDOM)
     994                 :         int fd = open("/dev/urandom", 0);
     995                 : 
     996                 :         if (fd >= 0) {
     997                 :                 if (read(fd, buf, size) == size) {
     998                 :                         while (i < size && buf[i] != 0) {
     999                 :                                 i++;
    1000                 :                         }
    1001                 :                         if (i == size) {
    1002                 :                                 close(fd);
    1003                 :                             return;
    1004                 :                         }
    1005                 :                 }
    1006                 :                 close(fd);
    1007                 :         }
    1008                 : #endif
    1009                 :         t = (unsigned char)getpid();
    1010                 :         while (i < size) {
    1011                 :                 do {
    1012                 :                         buf[i] = ((unsigned char)rand()) ^ t;
    1013                 :                 } while (buf[i] == 0);
    1014                 :                 t = buf[i++] << 1;
    1015                 :     }
    1016                 : }
    1017                 : /* }}} */
    1018                 : #endif
    1019                 : 
    1020                 : /* Notes:
    1021                 :  * - This function may alter the block_sizes values to match platform alignment
    1022                 :  * - This function does *not* perform sanity checks on the arguments
    1023                 :  */
    1024                 : ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params) /* {{{ */
    1025           17007 : {
    1026                 :         zend_mm_storage *storage;
    1027                 :         zend_mm_heap    *heap;
    1028                 : 
    1029                 : #if 0
    1030                 :         int i;
    1031                 : 
    1032                 :         printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE);
    1033                 :         printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE);
    1034                 :         printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE);
    1035                 :         printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
    1036                 :         printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE);
    1037                 :         printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE);
    1038                 :         printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1039                 :         for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) {
    1040                 :                 printf("%3d%c: %3ld %d %2ld\n", i, (i == ZEND_MM_MIN_SIZE?'*':' '), (long)ZEND_MM_TRUE_SIZE(i), ZEND_MM_SMALL_SIZE(ZEND_MM_TRUE_SIZE(i)), (long)ZEND_MM_BUCKET_INDEX(ZEND_MM_TRUE_SIZE(i)));
    1041                 :         }
    1042                 :         exit(0);
    1043                 : #endif
    1044                 : 
    1045                 : #if ZEND_MM_HEAP_PROTECTION
    1046                 :         if (_mem_block_start_magic == 0) {
    1047                 :                 zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic));
    1048                 :         }
    1049                 :         if (_mem_block_end_magic == 0) {
    1050                 :                 zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic));
    1051                 :         }
    1052                 : #endif
    1053                 : #if ZEND_MM_COOKIES
    1054                 :         if (_zend_mm_cookie == 0) {
    1055                 :                 zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie));
    1056                 :         }
    1057                 : #endif
    1058                 : 
    1059           17007 :         if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
    1060               0 :                 fprintf(stderr, "'block_size' must be a power of two\n");
    1061               0 :                 exit(255);
    1062                 :         }
    1063           17007 :         storage = handlers->init(params);
    1064           17007 :         if (!storage) {
    1065               0 :                 fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
    1066               0 :                 exit(255);
    1067                 :         }
    1068           17007 :         storage->handlers = handlers;
    1069                 : 
    1070           17007 :         heap = malloc(sizeof(struct _zend_mm_heap));
    1071                 : 
    1072           17007 :         heap->storage = storage;
    1073           17007 :         heap->block_size = block_size;
    1074           17007 :         heap->compact_size = 0;
    1075           17007 :         heap->segments_list = NULL;
    1076           17007 :         zend_mm_init(heap);
    1077                 : # if ZEND_MM_CACHE_STAT
    1078                 :         memset(heap->cache_stat, 0, sizeof(heap->cache_stat));
    1079                 : # endif
    1080                 : 
    1081           17007 :         heap->use_zend_alloc = 1;
    1082           17007 :         heap->real_size = 0;
    1083           17007 :         heap->overflow = 0;
    1084           17007 :         heap->real_peak = 0;
    1085           17007 :         heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
    1086           17007 :         heap->size = 0;
    1087           17007 :         heap->peak = 0;
    1088           17007 :         heap->internal = internal;
    1089           17007 :         heap->reserve = NULL;
    1090           17007 :         heap->reserve_size = reserve_size;
    1091           17007 :         if (reserve_size > 0) {
    1092           17007 :                 heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1093                 :         }
    1094           17007 :         if (internal) {
    1095                 :                 int i;
    1096                 :                 zend_mm_free_block *p, *q, *orig;
    1097               0 :                 zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap)  ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1098                 : 
    1099               0 :                 *mm_heap = *heap;
    1100                 : 
    1101               0 :                 p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0);
    1102               0 :                 orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
    1103               0 :                 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
    1104               0 :                         q = p;
    1105               0 :                         while (q->prev_free_block != orig) {
    1106               0 :                                 q = q->prev_free_block;
    1107                 :                         }
    1108               0 :                         q->prev_free_block = p;
    1109               0 :                         q = p;
    1110               0 :                         while (q->next_free_block != orig) {
    1111               0 :                                 q = q->next_free_block;
    1112                 :                         }
    1113               0 :                         q->next_free_block = p;
    1114               0 :                         p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
    1115               0 :                         orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2);
    1116               0 :                         if (mm_heap->large_free_buckets[i]) {
    1117               0 :                                 mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
    1118                 :                         }
    1119                 :                 }
    1120               0 :                 mm_heap->rest_buckets[0]->next_free_block = mm_heap->rest_buckets[1]->prev_free_block = ZEND_MM_REST_BUCKET(mm_heap);
    1121                 : 
    1122               0 :                 free(heap);
    1123               0 :                 heap = mm_heap;
    1124                 :         }
    1125           17007 :         return heap;
    1126                 : }
    1127                 : /* }}} */
    1128                 : 
    1129                 : ZEND_API zend_mm_heap *zend_mm_startup(void) /* {{{ */
    1130           17007 : {
    1131                 :         int i;
    1132                 :         size_t seg_size;
    1133           17007 :         char *mem_type = getenv("ZEND_MM_MEM_TYPE");
    1134                 :         char *tmp;
    1135                 :         const zend_mm_mem_handlers *handlers;
    1136                 :         zend_mm_heap *heap;
    1137                 : 
    1138           17007 :         if (mem_type == NULL) {
    1139           17007 :                 i = 0;
    1140                 :         } else {
    1141               0 :                 for (i = 0; mem_handlers[i].name; i++) {
    1142               0 :                         if (strcmp(mem_handlers[i].name, mem_type) == 0) {
    1143               0 :                                 break;
    1144                 :                         }
    1145                 :                 }
    1146               0 :                 if (!mem_handlers[i].name) {
    1147               0 :                         fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);
    1148               0 :                         fprintf(stderr, "  supported types:\n");
    1149               0 :                         for (i = 0; mem_handlers[i].name; i++) {
    1150               0 :                                 fprintf(stderr, "    '%s'\n", mem_handlers[i].name);
    1151                 :                         }
    1152               0 :                         exit(255);
    1153                 :                 }
    1154                 :         }
    1155           17007 :         handlers = &mem_handlers[i];
    1156                 : 
    1157           17007 :         tmp = getenv("ZEND_MM_SEG_SIZE");
    1158           17007 :         if (tmp) {
    1159               0 :                 seg_size = zend_atoi(tmp, 0);
    1160               0 :                 if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {
    1161               0 :                         fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");
    1162               0 :                         exit(255);
    1163               0 :                 } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {
    1164               0 :                         fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");
    1165               0 :                         exit(255);
    1166                 :                 }
    1167                 :         } else {
    1168           17007 :                 seg_size = ZEND_MM_SEG_SIZE;
    1169                 :         }
    1170                 : 
    1171           17007 :         heap = zend_mm_startup_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL);
    1172           17007 :         if (heap) {
    1173           17007 :                 tmp = getenv("ZEND_MM_COMPACT");
    1174           17007 :                 if (tmp) {
    1175               0 :                         heap->compact_size = zend_atoi(tmp, 0);
    1176                 :                 } else {
    1177           17007 :                         heap->compact_size = 2 * 1024 * 1024;
    1178                 :                 }
    1179                 :         }
    1180           17007 :         return heap;
    1181                 : }
    1182                 : /* }}} */
    1183                 : 
    1184                 : #if ZEND_DEBUG
    1185                 : static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b) /* {{{ */
    1186                 : {
    1187                 :         long leaks = 0;
    1188                 :         zend_mm_block *p, *q;
    1189                 : 
    1190                 :         p = ZEND_MM_NEXT_BLOCK(b);
    1191                 :         while (1) {
    1192                 :                 if (ZEND_MM_IS_GUARD_BLOCK(p)) {
    1193                 :                         ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD);
    1194                 :                         segment = segment->next_segment;
    1195                 :                         if (!segment) {
    1196                 :                                 break;
    1197                 :                         }
    1198                 :                         p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1199                 :                         continue;
    1200                 :                 }
    1201                 :                 q = ZEND_MM_NEXT_BLOCK(p);
    1202                 :                 if (q <= p ||
    1203                 :                     (char*)q > (char*)segment + segment->size ||
    1204                 :                     p->info._size != q->info._prev) {
    1205                 :                     zend_mm_panic("zend_mm_heap corrupted");
    1206                 :                 }
    1207                 :                 if (!ZEND_MM_IS_FREE_BLOCK(p)) {
    1208                 :                         if (p->magic == MEM_BLOCK_VALID) {
    1209                 :                                 if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) {
    1210                 :                                         ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
    1211                 :                                         leaks++;
    1212                 :                                 }
    1213                 : #if ZEND_MM_CACHE
    1214                 :                         } else if (p->magic == MEM_BLOCK_CACHED) {
    1215                 :                                 /* skip it */
    1216                 : #endif
    1217                 :                         } else if (p->magic != MEM_BLOCK_LEAK) {
    1218                 :                             zend_mm_panic("zend_mm_heap corrupted");
    1219                 :                         }
    1220                 :                 }
    1221                 :                 p = q;
    1222                 :         }
    1223                 :         return leaks;
    1224                 : }
    1225                 : /* }}} */
    1226                 : 
    1227                 : static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC) /* {{{ */
    1228                 : {
    1229                 :         zend_mm_segment *segment = heap->segments_list;
    1230                 :         zend_mm_block *p, *q;
    1231                 :         zend_uint total = 0;
    1232                 : 
    1233                 :         if (!segment) {
    1234                 :                 return;
    1235                 :         }
    1236                 :         p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1237                 :         while (1) {
    1238                 :                 q = ZEND_MM_NEXT_BLOCK(p);
    1239                 :                 if (q <= p ||
    1240                 :                     (char*)q > (char*)segment + segment->size ||
    1241                 :                     p->info._size != q->info._prev) {
    1242                 :                         zend_mm_panic("zend_mm_heap corrupted");
    1243                 :                 }
    1244                 :                 if (!ZEND_MM_IS_FREE_BLOCK(p)) {
    1245                 :                         if (p->magic == MEM_BLOCK_VALID) {
    1246                 :                                 long repeated;
    1247                 :                                 zend_leak_info leak;
    1248                 : 
    1249                 :                                 ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
    1250                 : 
    1251                 :                                 leak.addr = ZEND_MM_DATA_OF(p);
    1252                 :                                 leak.size = p->debug.size;
    1253                 :                                 leak.filename = p->debug.filename;
    1254                 :                                 leak.lineno = p->debug.lineno;
    1255                 :                                 leak.orig_filename = p->debug.orig_filename;
    1256                 :                                 leak.orig_lineno = p->debug.orig_lineno;
    1257                 : 
    1258                 :                                 zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
    1259                 :                                 zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
    1260                 :                                 repeated = zend_mm_find_leaks(segment, p);
    1261                 :                                 total += 1 + repeated;
    1262                 :                                 if (repeated) {
    1263                 :                                         zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
    1264                 :                                 }
    1265                 : #if ZEND_MM_CACHE
    1266                 :                         } else if (p->magic == MEM_BLOCK_CACHED) {
    1267                 :                                 /* skip it */
    1268                 : #endif
    1269                 :                         } else if (p->magic != MEM_BLOCK_LEAK) {
    1270                 :                                 zend_mm_panic("zend_mm_heap corrupted");
    1271                 :                         }
    1272                 :                 }
    1273                 :                 if (ZEND_MM_IS_GUARD_BLOCK(q)) {
    1274                 :                         segment = segment->next_segment;
    1275                 :                         if (!segment) {
    1276                 :                                 break;
    1277                 :                         }
    1278                 :                         q = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1279                 :                 }
    1280                 :                 p = q;
    1281                 :         }
    1282                 :         if (total) {
    1283                 :                 zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
    1284                 :         }
    1285                 : }
    1286                 : /* }}} */
    1287                 : 
    1288                 : static int zend_mm_check_ptr(zend_mm_heap *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    1289                 : {
    1290                 :         zend_mm_block *p;
    1291                 :         int no_cache_notice = 0;
    1292                 :         int had_problems = 0;
    1293                 :         int valid_beginning = 1;
    1294                 : 
    1295                 :         if (silent==2) {
    1296                 :                 silent = 1;
    1297                 :                 no_cache_notice = 1;
    1298                 :         } else if (silent==3) {
    1299                 :                 silent = 0;
    1300                 :                 no_cache_notice = 1;
    1301                 :         }
    1302                 :         if (!silent) {
    1303                 :                 TSRMLS_FETCH();
    1304                 : 
    1305                 :                 zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
    1306                 :                 zend_debug_alloc_output("---------------------------------------\n");
    1307                 :                 zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
    1308                 :                 if (__zend_orig_filename) {
    1309                 :                         zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
    1310                 :                 }
    1311                 :                 if (!ptr) {
    1312                 :                         zend_debug_alloc_output("NULL\n");
    1313                 :                         zend_debug_alloc_output("---------------------------------------\n");
    1314                 :                         return 0;
    1315                 :                 }
    1316                 :         }
    1317                 : 
    1318                 :         if (!ptr) {
    1319                 :                 if (silent) {
    1320                 :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1321                 :                 }
    1322                 :         }
    1323                 : 
    1324                 :         p = ZEND_MM_HEADER_OF(ptr);
    1325                 : 
    1326                 : #ifdef ZTS
    1327                 :         if (ZEND_MM_BAD_THREAD_ID(p)) {
    1328                 :                 if (!silent) {
    1329                 :                         zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id());
    1330                 :                         had_problems = 1;
    1331                 :                 } else {
    1332                 :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1333                 :                 }
    1334                 :         }
    1335                 : #endif
    1336                 : 
    1337                 :         if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) {
    1338                 :                 if (!silent) {
    1339                 :                         zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev);
    1340                 :                         had_problems = 1;
    1341                 :                 } else {
    1342                 :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1343                 :                 }
    1344                 :         }
    1345                 :         if (p->info._prev != ZEND_MM_GUARD_BLOCK &&
    1346                 :             ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) {
    1347                 :                 if (!silent) {
    1348                 :                         zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size);
    1349                 :                         had_problems = 1;
    1350                 :                 } else {
    1351                 :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1352                 :                 }
    1353                 :         }
    1354                 : 
    1355                 :         if (had_problems) {
    1356                 :                 zend_debug_alloc_output("---------------------------------------\n");
    1357                 :                 return 0;
    1358                 :         }
    1359                 : 
    1360                 :         if (!silent) {
    1361                 :                 zend_debug_alloc_output("%10s\t","Beginning:  ");
    1362                 :         }
    1363                 : 
    1364                 :         if (!ZEND_MM_IS_USED_BLOCK(p)) {
    1365                 :                 if (!silent) {
    1366                 :                         if (p->magic != MEM_BLOCK_FREED) {
    1367                 :                                 zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
    1368                 :                         } else {
    1369                 :                                 zend_debug_alloc_output("Freed\n");
    1370                 :                         }
    1371                 :                         had_problems = 1;
    1372                 :                 } else {
    1373                 :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1374                 :                 }
    1375                 :         } else if (ZEND_MM_IS_GUARD_BLOCK(p)) {
    1376                 :                 if (!silent) {
    1377                 :                         if (p->magic != MEM_BLOCK_FREED) {
    1378                 :                                 zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
    1379                 :                         } else {
    1380                 :                                 zend_debug_alloc_output("Guard\n");
    1381                 :                         }
    1382                 :                         had_problems = 1;
    1383                 :                 } else {
    1384                 :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1385                 :                 }
    1386                 :         } else {
    1387                 :                 switch (p->magic) {
    1388                 :                         case MEM_BLOCK_VALID:
    1389                 :                         case MEM_BLOCK_LEAK:
    1390                 :                                 if (!silent) {
    1391                 :                                         zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size);
    1392                 :                                 }
    1393                 :                                 break; /* ok */
    1394                 :                         case MEM_BLOCK_CACHED:
    1395                 :                                 if (!no_cache_notice) {
    1396                 :                                         if (!silent) {
    1397                 :                                                 zend_debug_alloc_output("Cached\n");
    1398                 :                                                 had_problems = 1;
    1399                 :                                         } else {
    1400                 :                                                 return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1401                 :                                         }
    1402                 :                                 }
    1403                 :                         case MEM_BLOCK_FREED:
    1404                 :                                 if (!silent) {
    1405                 :                                         zend_debug_alloc_output("Freed (invalid)\n");
    1406                 :                                         had_problems = 1;
    1407                 :                                 } else {
    1408                 :                                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1409                 :                                 }
    1410                 :                                 break;
    1411                 :                         case MEM_BLOCK_GUARD:
    1412                 :                                 if (!silent) {
    1413                 :                                         zend_debug_alloc_output("Guard (invalid)\n");
    1414                 :                                         had_problems = 1;
    1415                 :                                 } else {
    1416                 :                                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1417                 :                                 }
    1418                 :                                 break;
    1419                 :                         default:
    1420                 :                                 if (!silent) {
    1421                 :                                         zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID);
    1422                 :                                         had_problems = 1;
    1423                 :                                         valid_beginning = 0;
    1424                 :                                 } else {
    1425                 :                                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1426                 :                                 }
    1427                 :                                 break;
    1428                 :                 }
    1429                 :         }
    1430                 : 
    1431                 : #if ZEND_MM_HEAP_PROTECTION
    1432                 :         if (!valid_beginning) {
    1433                 :                 if (!silent) {
    1434                 :                         zend_debug_alloc_output("%10s\t", "Start:");
    1435                 :                         zend_debug_alloc_output("Unknown\n");
    1436                 :                         zend_debug_alloc_output("%10s\t", "End:");
    1437                 :                         zend_debug_alloc_output("Unknown\n");
    1438                 :                 }
    1439                 :         } else {
    1440                 :                 char *end_magic = ZEND_MM_END_MAGIC_PTR(p);
    1441                 : 
    1442                 :                 if (p->debug.start_magic == _mem_block_start_magic) {
    1443                 :                         if (!silent) {
    1444                 :                                 zend_debug_alloc_output("%10s\t", "Start:");
    1445                 :                                 zend_debug_alloc_output("OK\n");
    1446                 :                         }
    1447                 :                 } else {
    1448                 :                         char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
    1449                 :                         int overflows=0;
    1450                 :                         int i;
    1451                 : 
    1452                 :                         if (silent) {
    1453                 :                                 return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1454                 :                         }
    1455                 :                         had_problems = 1;
    1456                 :                         overflow_ptr = (char *) &p->debug.start_magic;
    1457                 :                         i = END_MAGIC_SIZE;
    1458                 :                         while (--i >= 0) {
    1459                 :                                 if (overflow_ptr[i]!=magic_ptr[i]) {
    1460                 :                                         overflows++;
    1461                 :                                 }
    1462                 :                         }
    1463                 :                         zend_debug_alloc_output("%10s\t", "Start:");
    1464                 :                         zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
    1465                 :                         zend_debug_alloc_output("%10s\t","");
    1466                 :                         if (overflows >= END_MAGIC_SIZE) {
    1467                 :                                 zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
    1468                 :                         } else {
    1469                 :                                 zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
    1470                 :                         }
    1471                 :                 }
    1472                 :                 if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
    1473                 :                         if (!silent) {
    1474                 :                                 zend_debug_alloc_output("%10s\t", "End:");
    1475                 :                                 zend_debug_alloc_output("OK\n");
    1476                 :                         }
    1477                 :                 } else {
    1478                 :                         char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
    1479                 :                         int overflows=0;
    1480                 :                         int i;
    1481                 : 
    1482                 :                         if (silent) {
    1483                 :                                 return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1484                 :                         }
    1485                 :                         had_problems = 1;
    1486                 :                         overflow_ptr = (char *) end_magic;
    1487                 : 
    1488                 :                         for (i=0; i < END_MAGIC_SIZE; i++) {
    1489                 :                                 if (overflow_ptr[i]!=magic_ptr[i]) {
    1490                 :                                         overflows++;
    1491                 :                                 }
    1492                 :                         }
    1493                 : 
    1494                 :                         zend_debug_alloc_output("%10s\t", "End:");
    1495                 :                         zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
    1496                 :                         zend_debug_alloc_output("%10s\t","");
    1497                 :                         if (overflows >= END_MAGIC_SIZE) {
    1498                 :                                 zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
    1499                 :                         } else {
    1500                 :                                 zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
    1501                 :                         }
    1502                 :                 }
    1503                 :         }
    1504                 : #endif
    1505                 : 
    1506                 :         if (!silent) {
    1507                 :                 zend_debug_alloc_output("---------------------------------------\n");
    1508                 :         }
    1509                 :         return ((!had_problems) ? 1 : 0);
    1510                 : }
    1511                 : /* }}} */
    1512                 : 
    1513                 : static int zend_mm_check_heap(zend_mm_heap *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    1514                 : {
    1515                 :         zend_mm_segment *segment = heap->segments_list;
    1516                 :         zend_mm_block *p, *q;
    1517                 :         int errors = 0;
    1518                 : 
    1519                 :         if (!segment) {
    1520                 :                 return 0;
    1521                 :         }
    1522                 :         p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1523                 :         while (1) {
    1524                 :                 q = ZEND_MM_NEXT_BLOCK(p);
    1525                 :                 if (q <= p ||
    1526                 :                     (char*)q > (char*)segment + segment->size ||
    1527                 :                     p->info._size != q->info._prev) {
    1528                 :                         zend_mm_panic("zend_mm_heap corrupted");
    1529                 :                 }
    1530                 :                 if (!ZEND_MM_IS_FREE_BLOCK(p)) {
    1531                 :                         if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) {
    1532                 :                                 if (!zend_mm_check_ptr(heap, ZEND_MM_DATA_OF(p), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) {
    1533                 :                                         errors++;
    1534                 :                                 }
    1535                 : #if ZEND_MM_CACHE
    1536                 :                         } else if (p->magic == MEM_BLOCK_CACHED) {
    1537                 :                                 /* skip it */
    1538                 : #endif
    1539                 :                         } else if (p->magic != MEM_BLOCK_LEAK) {
    1540                 :                                 zend_mm_panic("zend_mm_heap corrupted");
    1541                 :                         }
    1542                 :                 }
    1543                 :                 if (ZEND_MM_IS_GUARD_BLOCK(q)) {
    1544                 :                         segment = segment->next_segment;
    1545                 :                         if (!segment) {
    1546                 :                                 return errors;
    1547                 :                         }
    1548                 :                         q = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1549                 :                 }
    1550                 :                 p = q;
    1551                 :         }
    1552                 : }
    1553                 : /* }}} */
    1554                 : #endif
    1555                 : 
    1556                 : ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC) /* {{{ */
    1557           51071 : {
    1558                 :         zend_mm_storage *storage;
    1559                 :         zend_mm_segment *segment;
    1560                 :         zend_mm_segment *prev;
    1561                 :         int internal;
    1562                 : 
    1563           51071 :         if (heap->reserve) {
    1564                 : #if ZEND_DEBUG
    1565                 :                 if (!silent) {
    1566                 :                         _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1567                 :                 }
    1568                 : #endif
    1569           51071 :                 heap->reserve = NULL;
    1570                 :         }
    1571                 : 
    1572                 : #if ZEND_MM_CACHE_STAT
    1573                 :         if (full_shutdown) {
    1574                 :                 FILE *f;
    1575                 : 
    1576                 :                 f = fopen("zend_mm.log", "w");
    1577                 :                 if (f) {
    1578                 :                         int i,j;
    1579                 :                         size_t size, true_size, min_size, max_size;
    1580                 :                         int hit = 0, miss = 0;
    1581                 : 
    1582                 :                         fprintf(f, "\nidx min_size max_size true_size  max_len     hits   misses\n");
    1583                 :                         size = 0;
    1584                 :                         while (1) {
    1585                 :                                 true_size = ZEND_MM_TRUE_SIZE(size);
    1586                 :                                 if (ZEND_MM_SMALL_SIZE(true_size)) {
    1587                 :                                         min_size = size;
    1588                 :                                         i = ZEND_MM_BUCKET_INDEX(true_size);
    1589                 :                                         size++;
    1590                 :                                         while (1) {
    1591                 :                                                 true_size = ZEND_MM_TRUE_SIZE(size);
    1592                 :                                                 if (ZEND_MM_SMALL_SIZE(true_size)) {
    1593                 :                                                         j = ZEND_MM_BUCKET_INDEX(true_size);
    1594                 :                                                         if (j > i) {
    1595                 :                                                                 max_size = size-1;
    1596                 :                                                                 break;
    1597                 :                                                         }
    1598                 :                                                 } else {
    1599                 :                                                         max_size = size-1;
    1600                 :                                                         break;
    1601                 :                                                 }
    1602                 :                                                 size++;
    1603                 :                                         }
    1604                 :                                         hit += heap->cache_stat[i].hit;
    1605                 :                                         miss += heap->cache_stat[i].miss;
    1606                 :                                         fprintf(f, "%2d %8d %8d %9d %8d %8d %8d\n", i, (int)min_size, (int)max_size, ZEND_MM_TRUE_SIZE(max_size), heap->cache_stat[i].max_count, heap->cache_stat[i].hit, heap->cache_stat[i].miss);
    1607                 :                                 } else {
    1608                 :                                         break;
    1609                 :                                 }
    1610                 :                         }
    1611                 :                         fprintf(f, "                                        %8d %8d\n", hit, miss);
    1612                 :                         fprintf(f, "                                        %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss);
    1613                 :                         fclose(f);
    1614                 :                 }
    1615                 :         }
    1616                 : #endif
    1617                 : 
    1618                 : #if ZEND_DEBUG
    1619                 :         if (!silent) {
    1620                 :                 zend_mm_check_leaks(heap TSRMLS_CC);
    1621                 :         }
    1622                 : #endif
    1623                 : 
    1624           51071 :         internal = heap->internal;
    1625           51071 :         storage = heap->storage;
    1626           51071 :         segment = heap->segments_list;
    1627          153250 :         while (segment) {
    1628           51108 :                 prev = segment;
    1629           51108 :                 segment = segment->next_segment;
    1630           51108 :                 ZEND_MM_STORAGE_FREE(prev);
    1631                 :         }
    1632           51071 :         if (full_shutdown) {
    1633           17039 :                 storage->handlers->dtor(storage);
    1634           17039 :                 if (!internal) {
    1635           17039 :                         free(heap);
    1636                 :                 }
    1637                 :         } else {
    1638           34032 :                 if (heap->compact_size &&
    1639                 :                     heap->real_peak > heap->compact_size) {
    1640               1 :                         storage->handlers->compact(storage);
    1641                 :                 }
    1642           34032 :                 heap->segments_list = NULL;
    1643           34032 :                 zend_mm_init(heap);
    1644           34032 :                 heap->real_size = 0;
    1645           34032 :                 heap->real_peak = 0;
    1646           34032 :                 heap->size = 0;
    1647           34032 :                 heap->peak = 0;
    1648           34032 :                 if (heap->reserve_size) {
    1649           34032 :                         heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size  ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1650                 :                 }
    1651           34032 :                 heap->overflow = 0;
    1652                 :         }
    1653           51071 : }
    1654                 : /* }}} */
    1655                 : 
    1656                 : static void zend_mm_safe_error(zend_mm_heap *heap,
    1657                 :         const char *format,
    1658                 :         size_t limit,
    1659                 : #if ZEND_DEBUG
    1660                 :         const char *filename,
    1661                 :         uint lineno,
    1662                 : #endif
    1663                 :         size_t size) /* {{{ */
    1664               0 : {
    1665               0 :         if (heap->reserve) {
    1666               0 :                 _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1667               0 :                 heap->reserve = NULL;
    1668                 :         }
    1669               0 :         if (heap->overflow == 0) {
    1670                 :                 char *error_filename;
    1671                 :                 uint error_lineno;
    1672                 :                 TSRMLS_FETCH();
    1673               0 :                 if (zend_is_compiling(TSRMLS_C)) {
    1674               0 :                         error_filename = zend_get_compiled_filename(TSRMLS_C);
    1675               0 :                         error_lineno = zend_get_compiled_lineno(TSRMLS_C);
    1676               0 :                 } else if (EG(in_execution)) {
    1677               0 :                         error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
    1678               0 :                         error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
    1679                 :                 } else {
    1680               0 :                         error_filename = NULL;
    1681               0 :                         error_lineno = 0;
    1682                 :                 }
    1683               0 :                 if (!error_filename) {
    1684               0 :                         error_filename = "Unknown";
    1685                 :                 }
    1686               0 :                 heap->overflow = 1;
    1687               0 :                 zend_try {
    1688               0 :                         zend_error_noreturn(E_ERROR,
    1689                 :                                 format,
    1690                 :                                 limit,
    1691                 : #if ZEND_DEBUG
    1692                 :                                 filename,
    1693                 :                                 lineno,
    1694                 : #endif
    1695                 :                                 size);
    1696               0 :                 } zend_catch {
    1697               0 :                         if (heap->overflow == 2) {
    1698               0 :                                 fprintf(stderr, "\nFatal error: ");
    1699               0 :                                 fprintf(stderr,
    1700                 :                                         format,
    1701                 :                                         limit,
    1702                 : #if ZEND_DEBUG
    1703                 :                                         filename,
    1704                 :                                         lineno,
    1705                 : #endif
    1706                 :                                         size);
    1707               0 :                                 fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
    1708                 :                         }
    1709               0 :                 } zend_end_try();
    1710                 :         } else {
    1711               0 :                 heap->overflow = 2;
    1712                 :         }
    1713               0 :         zend_bailout();
    1714               0 : }
    1715                 : /* }}} */
    1716                 : 
    1717                 : static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size) /* {{{ */
    1718        14991824 : {
    1719                 :         zend_mm_free_block *best_fit;
    1720        14991824 :         size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size);
    1721        14991824 :         size_t bitmap = heap->large_free_bitmap >> index;
    1722                 :         zend_mm_free_block *p;
    1723                 : 
    1724        14991824 :         if (bitmap == 0) {
    1725           56755 :                 return NULL;
    1726                 :         }
    1727                 : 
    1728        14935069 :         if (UNEXPECTED((bitmap & 1) != 0)) {
    1729                 :                 /* Search for best "large" free block */
    1730         2870695 :                 zend_mm_free_block *rst = NULL;
    1731                 :                 size_t m;
    1732         2870695 :                 size_t best_size = -1;
    1733                 : 
    1734         2870695 :                 best_fit = NULL;
    1735         2870695 :                 p = heap->large_free_buckets[index];
    1736         5795949 :                 for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
    1737         5795949 :                         if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
    1738          659946 :                                 return p->next_free_block;
    1739         5136003 :                         } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
    1740                 :                                    ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
    1741         2704377 :                                 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
    1742         2704377 :                                 best_fit = p;
    1743                 :                         }
    1744         5136003 :                         if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) {
    1745         3394032 :                                 if (p->child[1]) {
    1746          839794 :                                         rst = p->child[1];
    1747                 :                                 }
    1748         3394032 :                                 if (p->child[0]) {
    1749         2096625 :                                         p = p->child[0];
    1750                 :                                 } else {
    1751         1297407 :                                         break;
    1752                 :                                 }
    1753         1741971 :                         } else if (p->child[1]) {
    1754          828629 :                                 p = p->child[1];
    1755                 :                         } else {
    1756          913342 :                                 break;
    1757                 :                         }
    1758         2925254 :                 }
    1759                 : 
    1760         2784019 :                 for (p = rst; p; p = p->child[p->child[0] != NULL]) {
    1761          573270 :                         if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
    1762               0 :                                 return p->next_free_block;
    1763          573270 :                         } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
    1764                 :                                    ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
    1765          161837 :                                 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
    1766          161837 :                                 best_fit = p;
    1767                 :                         }
    1768                 :                 }
    1769                 : 
    1770         2210749 :                 if (best_fit) {
    1771         1396790 :                         return best_fit->next_free_block;
    1772                 :                 }
    1773          813959 :                 bitmap = bitmap >> 1;
    1774          813959 :                 if (!bitmap) {
    1775             785 :                         return NULL;
    1776                 :                 }
    1777          813174 :                 index++;
    1778                 :         }
    1779                 : 
    1780                 :         /* Search for smallest "large" free block */
    1781        12877548 :         best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)];
    1782        27237709 :         while ((p = p->child[p->child[0] != NULL])) {
    1783         1482613 :                 if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
    1784         1007722 :                         best_fit = p;
    1785                 :                 }
    1786                 :         }
    1787        12877548 :         return best_fit->next_free_block;
    1788                 : }
    1789                 : /* }}} */
    1790                 : 
    1791                 : static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    1792       142709250 : {
    1793                 :         zend_mm_free_block *best_fit;
    1794       142709250 :         size_t true_size = ZEND_MM_TRUE_SIZE(size);
    1795                 :         size_t block_size;
    1796                 :         size_t remaining_size;
    1797                 :         size_t segment_size;
    1798                 :         zend_mm_segment *segment;
    1799       142709250 :         int keep_rest = 0;
    1800                 : 
    1801       142709250 :         if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
    1802       138005086 :                 size_t index = ZEND_MM_BUCKET_INDEX(true_size);
    1803                 :                 size_t bitmap;
    1804                 : 
    1805       138005086 :                 if (UNEXPECTED(true_size < size)) {
    1806               0 :                         goto out_of_memory;
    1807                 :                 }
    1808                 : #if ZEND_MM_CACHE
    1809       138005086 :                 if (EXPECTED(heap->cache[index] != NULL)) {
    1810                 :                         /* Get block from cache */
    1811                 : #if ZEND_MM_CACHE_STAT
    1812                 :                         heap->cache_stat[index].count--;
    1813                 :                         heap->cache_stat[index].hit++;
    1814                 : #endif
    1815        92494743 :                         best_fit = heap->cache[index];
    1816        92494743 :                         heap->cache[index] = best_fit->prev_free_block;
    1817        92494743 :                         heap->cached -= true_size;
    1818                 :                         ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
    1819                 :                         ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
    1820        92494743 :                         return ZEND_MM_DATA_OF(best_fit);
    1821                 :                 }
    1822                 : #if ZEND_MM_CACHE_STAT
    1823                 :                 heap->cache_stat[index].miss++;
    1824                 : #endif
    1825                 : #endif
    1826                 : 
    1827        45510343 :                 bitmap = heap->free_bitmap >> index;
    1828        45510343 :                 if (bitmap) {
    1829                 :                         /* Found some "small" free block that can be used */
    1830        35222683 :                         index += zend_mm_low_bit(bitmap);
    1831        35222683 :                         best_fit = heap->free_buckets[index*2];
    1832                 : #if ZEND_MM_CACHE_STAT
    1833                 :                         heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
    1834                 : #endif
    1835        35222683 :                         goto zend_mm_finished_searching_for_block;
    1836                 :                 }
    1837                 :         }
    1838                 : 
    1839                 : #if ZEND_MM_CACHE_STAT
    1840                 :         heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++;
    1841                 : #endif
    1842                 : 
    1843        14991824 :         best_fit = zend_mm_search_large_block(heap, true_size);
    1844                 : 
    1845        14991824 :         if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
    1846               0 :                 zend_mm_free_block *p = heap->rest_buckets[0];
    1847               0 :                 size_t best_size = -1;
    1848                 : 
    1849               0 :                 while (p != ZEND_MM_REST_BUCKET(heap)) {
    1850               0 :                         if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
    1851               0 :                                 best_fit = p;
    1852               0 :                                 goto zend_mm_finished_searching_for_block;
    1853               0 :                         } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
    1854                 :                                    ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
    1855               0 :                                 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
    1856               0 :                                 best_fit = p;
    1857                 :                         }
    1858               0 :                         p = p->prev_free_block;
    1859                 :                 }
    1860                 :         }
    1861                 : 
    1862        14991824 :         if (!best_fit) {
    1863           57540 :                 if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
    1864                 :                         /* Make sure we add a memory block which is big enough,
    1865                 :                            segment must have header "size" and trailer "guard" block */
    1866              21 :                         segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
    1867              21 :                         segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
    1868              21 :                         keep_rest = 1;
    1869                 :                 } else {
    1870           57519 :                         segment_size = heap->block_size;
    1871                 :                 }
    1872                 : 
    1873           57540 :                 HANDLE_BLOCK_INTERRUPTIONS();
    1874                 : 
    1875           57540 :                 if (segment_size < true_size ||
    1876                 :                     heap->real_size + segment_size > heap->limit) {
    1877                 :                         /* Memory limit overflow */
    1878                 : #if ZEND_MM_CACHE
    1879               0 :                         zend_mm_free_cache(heap);
    1880                 : #endif
    1881               0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1882                 : #if ZEND_DEBUG
    1883                 :                         zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size);
    1884                 : #else
    1885               0 :                         zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
    1886                 : #endif
    1887                 :                 }
    1888                 : 
    1889           57540 :                 segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
    1890                 : 
    1891           57540 :                 if (!segment) {
    1892                 :                         /* Storage manager cannot allocate memory */
    1893                 : #if ZEND_MM_CACHE
    1894               0 :                         zend_mm_free_cache(heap);
    1895                 : #endif
    1896               0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1897               0 : out_of_memory:
    1898                 : #if ZEND_DEBUG
    1899                 :                         zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
    1900                 : #else
    1901               0 :                         zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
    1902                 : #endif
    1903               0 :                         return NULL;
    1904                 :                 }
    1905                 : 
    1906           57540 :                 heap->real_size += segment_size;
    1907           57540 :                 if (heap->real_size > heap->real_peak) {
    1908           51089 :                         heap->real_peak = heap->real_size;
    1909                 :                 }
    1910                 : 
    1911           57540 :                 segment->size = segment_size;
    1912           57540 :                 segment->next_segment = heap->segments_list;
    1913           57540 :                 heap->segments_list = segment;
    1914                 : 
    1915           57540 :                 best_fit = (zend_mm_free_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1916           57540 :                 ZEND_MM_MARK_FIRST_BLOCK(best_fit);
    1917                 : 
    1918           57540 :                 block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
    1919                 : 
    1920           57540 :                 ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size));
    1921                 : 
    1922                 :         } else {
    1923        50156967 : zend_mm_finished_searching_for_block:
    1924                 :                 /* remove from free list */
    1925        50156967 :                 HANDLE_BLOCK_INTERRUPTIONS();
    1926                 :                 ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
    1927                 :                 ZEND_MM_CHECK_COOKIE(best_fit);
    1928        50156967 :                 ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
    1929        50156967 :                 zend_mm_remove_from_free_list(heap, best_fit);
    1930                 : 
    1931        50156967 :                 block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit);
    1932                 :         }
    1933                 : 
    1934        50214507 :         remaining_size = block_size - true_size;
    1935                 : 
    1936        50214507 :         if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    1937        26736331 :                 true_size = block_size;
    1938        26736331 :                 ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
    1939                 :         } else {
    1940                 :                 zend_mm_free_block *new_free_block;
    1941                 : 
    1942                 :                 /* prepare new free block */
    1943        23478176 :                 ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
    1944        23478176 :                 new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(best_fit, true_size);
    1945        23478176 :                 ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    1946                 : 
    1947                 :                 /* add the new free block to the free list */
    1948        23478176 :                 if (EXPECTED(!keep_rest)) {
    1949        23478155 :                         zend_mm_add_to_free_list(heap, new_free_block);
    1950                 :                 } else {
    1951              21 :                         zend_mm_add_to_rest_list(heap, new_free_block);
    1952                 :                 }
    1953                 :         }
    1954                 : 
    1955                 :         ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
    1956                 : 
    1957        50214507 :         heap->size += true_size;
    1958        50214507 :         if (heap->peak < heap->size) {
    1959          186362 :                 heap->peak = heap->size;
    1960                 :         }
    1961                 : 
    1962        50214507 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1963                 : 
    1964        50214507 :         return ZEND_MM_DATA_OF(best_fit);
    1965                 : }
    1966                 : /* }}} */
    1967                 : 
    1968                 : static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    1969       142657762 : {
    1970                 :         zend_mm_block *mm_block;
    1971                 :         zend_mm_block *next_block;
    1972                 :         size_t size;
    1973                 : 
    1974       142657762 :         if (!ZEND_MM_VALID_PTR(p)) {
    1975               0 :                 return;
    1976                 :         }
    1977       142657762 :         mm_block = ZEND_MM_HEADER_OF(p);
    1978       142657762 :         size = ZEND_MM_BLOCK_SIZE(mm_block);
    1979                 :         ZEND_MM_CHECK_PROTECTION(mm_block);
    1980                 : 
    1981                 : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    1982                 :         memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
    1983                 : #endif
    1984                 : 
    1985                 : #if ZEND_MM_CACHE
    1986       142657762 :         if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
    1987        92500088 :                 size_t index = ZEND_MM_BUCKET_INDEX(size);
    1988        92500088 :                 zend_mm_free_block **cache = &heap->cache[index];
    1989                 : 
    1990        92500088 :                 ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
    1991        92500088 :                 *cache = (zend_mm_free_block*)mm_block;
    1992        92500088 :                 heap->cached += size;
    1993                 :                 ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
    1994                 : #if ZEND_MM_CACHE_STAT
    1995                 :                 if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
    1996                 :                         heap->cache_stat[index].max_count = heap->cache_stat[index].count;
    1997                 :                 }
    1998                 : #endif
    1999        92500088 :                 return;
    2000                 :         }
    2001                 : #endif
    2002                 : 
    2003        50157674 :         HANDLE_BLOCK_INTERRUPTIONS();
    2004                 : 
    2005        50157674 :         heap->size -= size;
    2006                 : 
    2007        50157674 :         next_block = ZEND_MM_BLOCK_AT(mm_block, size);
    2008        50157674 :         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2009        16485596 :                 zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2010        16485596 :                 size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
    2011                 :         }
    2012        50157674 :         if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
    2013         6924481 :                 mm_block = ZEND_MM_PREV_BLOCK(mm_block);
    2014         6924481 :                 zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) mm_block);
    2015         6924481 :                 size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
    2016                 :         }
    2017        50164138 :         if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
    2018                 :             ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) {
    2019            6464 :                 zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
    2020                 :         } else {
    2021        50151210 :                 ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
    2022        50151210 :                 zend_mm_add_to_free_list(heap, (zend_mm_free_block *) mm_block);
    2023                 :         }
    2024        50157674 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2025                 : }
    2026                 : /* }}} */
    2027                 : 
    2028                 : static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2029        30917187 : {
    2030        30917187 :         zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p);
    2031                 :         zend_mm_block *next_block;
    2032                 :         size_t true_size;
    2033                 :         size_t orig_size;
    2034                 :         void *ptr;
    2035                 : 
    2036        30917187 :         if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
    2037        20900006 :                 return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2038                 :         }
    2039        10017181 :         mm_block = ZEND_MM_HEADER_OF(p);
    2040        10017181 :         true_size = ZEND_MM_TRUE_SIZE(size);
    2041        10017181 :         orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
    2042                 :         ZEND_MM_CHECK_PROTECTION(mm_block);
    2043                 : 
    2044        10017181 :         if (UNEXPECTED(true_size < size)) {
    2045               0 :                 goto out_of_memory;
    2046                 :         }
    2047                 : 
    2048        10017181 :         if (true_size <= orig_size) {
    2049         1533811 :                 size_t remaining_size = orig_size - true_size;
    2050                 : 
    2051         1533811 :                 if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2052                 :                         zend_mm_free_block *new_free_block;
    2053                 : 
    2054           65359 :                         HANDLE_BLOCK_INTERRUPTIONS();
    2055           65359 :                         next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
    2056           65359 :                         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2057           24317 :                                 remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
    2058           24317 :                                 zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2059                 :                         }
    2060                 : 
    2061                 :                         /* prepare new free block */
    2062           65359 :                         ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2063           65359 :                         new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
    2064                 : 
    2065           65359 :                         ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2066                 : 
    2067                 :                         /* add the new free block to the free list */
    2068           65359 :                         zend_mm_add_to_free_list(heap, new_free_block);
    2069           65359 :                         heap->size += (true_size - orig_size);
    2070           65359 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2071                 :                 }
    2072                 :                 ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
    2073         1533811 :                 return p;
    2074                 :         }
    2075                 : 
    2076                 : #if ZEND_MM_CACHE
    2077         8483370 :         if (ZEND_MM_SMALL_SIZE(true_size)) {
    2078         5899975 :                 size_t index = ZEND_MM_BUCKET_INDEX(true_size);
    2079                 :                 
    2080         5899975 :                 if (heap->cache[index] != NULL) {
    2081                 :                         zend_mm_free_block *best_fit;
    2082                 :                         zend_mm_free_block **cache;
    2083                 : 
    2084                 : #if ZEND_MM_CACHE_STAT
    2085                 :                         heap->cache_stat[index].count--;
    2086                 :                         heap->cache_stat[index].hit++;
    2087                 : #endif
    2088         5093279 :                         best_fit = heap->cache[index];
    2089         5093279 :                         heap->cache[index] = best_fit->prev_free_block;
    2090                 :                         ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
    2091                 :                         ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
    2092                 :         
    2093         5093279 :                         ptr = ZEND_MM_DATA_OF(best_fit);
    2094                 : 
    2095                 : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2096                 :                         memcpy(ptr, p, mm_block->debug.size);
    2097                 : #else
    2098         5093279 :                         memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
    2099                 : #endif
    2100                 : 
    2101         5093279 :                         heap->cached -= true_size - orig_size;
    2102                 : 
    2103         5093279 :                         index = ZEND_MM_BUCKET_INDEX(orig_size);
    2104         5093279 :                         cache = &heap->cache[index];
    2105                 : 
    2106         5093279 :                         ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
    2107         5093279 :                         *cache = (zend_mm_free_block*)mm_block;
    2108                 :                         ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
    2109                 : #if ZEND_MM_CACHE_STAT
    2110                 :                         if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
    2111                 :                                 heap->cache_stat[index].max_count = heap->cache_stat[index].count;
    2112                 :                         }
    2113                 : #endif
    2114                 : 
    2115         5093279 :                         return ptr;
    2116                 :                 }
    2117                 :         }
    2118                 : #endif
    2119                 : 
    2120         3390091 :         next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
    2121                 : 
    2122         3390091 :         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2123                 :                 ZEND_MM_CHECK_COOKIE(next_block);
    2124         2155495 :                 ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
    2125         2155495 :                 if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
    2126         1979343 :                         size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
    2127         1979343 :                         size_t remaining_size = block_size - true_size;
    2128                 : 
    2129         1979343 :                         HANDLE_BLOCK_INTERRUPTIONS();
    2130         1979343 :                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2131                 : 
    2132         1979343 :                         if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2133           48554 :                                 true_size = block_size;
    2134           48554 :                                 ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2135                 :                         } else {
    2136                 :                                 zend_mm_free_block *new_free_block;
    2137                 : 
    2138                 :                                 /* prepare new free block */
    2139         1930789 :                                 ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2140         1930789 :                                 new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
    2141         1930789 :                                 ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2142                 : 
    2143                 :                                 /* add the new free block to the free list */
    2144         1983411 :                                 if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
    2145                 :                                     ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) {
    2146           52622 :                                         zend_mm_add_to_rest_list(heap, new_free_block);
    2147                 :                                 } else {
    2148         1878167 :                                         zend_mm_add_to_free_list(heap, new_free_block);
    2149                 :                                 }
    2150                 :                         }
    2151                 :                         ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
    2152         1979343 :                         heap->size = heap->size + true_size - orig_size;
    2153         1979343 :                         if (heap->peak < heap->size) {
    2154           28610 :                                 heap->peak = heap->size;
    2155                 :                         }
    2156         1979343 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2157         1979343 :                         return p;
    2158          176152 :                 } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
    2159                 :                                    ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
    2160               6 :                         HANDLE_BLOCK_INTERRUPTIONS();
    2161               6 :                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2162               6 :                         goto realloc_segment;
    2163                 :                 }
    2164         1234596 :         } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) {
    2165                 :                 zend_mm_segment *segment;
    2166                 :                 zend_mm_segment *segment_copy;
    2167                 :                 size_t segment_size;
    2168                 :                 size_t block_size;
    2169                 :                 size_t remaining_size;
    2170                 : 
    2171               2 :                 HANDLE_BLOCK_INTERRUPTIONS();
    2172               8 : realloc_segment:
    2173                 :                 /* segment size, size of block and size of guard block */
    2174               8 :                 if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
    2175               8 :                         segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE;
    2176               8 :                         segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
    2177                 :                 } else {
    2178               0 :                         segment_size = heap->block_size;
    2179                 :                 }
    2180                 : 
    2181               8 :                 segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
    2182               8 :                 if (segment_size < true_size ||
    2183                 :                     heap->real_size + segment_size - segment_copy->size > heap->limit) {
    2184               0 :                         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2185               0 :                                 zend_mm_add_to_free_list(heap, (zend_mm_free_block *) next_block);
    2186                 :                         }
    2187                 : #if ZEND_MM_CACHE
    2188               0 :                         zend_mm_free_cache(heap);
    2189                 : #endif
    2190               0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2191                 : #if ZEND_DEBUG
    2192                 :                         zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size);
    2193                 : #else
    2194               0 :                         zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
    2195                 : #endif
    2196               0 :                         return NULL;
    2197                 :                 }
    2198                 : 
    2199               8 :                 segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
    2200               8 :                 if (!segment) {
    2201                 : #if ZEND_MM_CACHE
    2202               0 :                         zend_mm_free_cache(heap);
    2203                 : #endif
    2204               0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2205               0 : out_of_memory:
    2206                 : #if ZEND_DEBUG
    2207                 :                         zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size);
    2208                 : #else
    2209               0 :                         zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
    2210                 : #endif
    2211               0 :                         return NULL;
    2212                 :                 }
    2213               8 :                 heap->real_size += segment_size - segment->size;
    2214               8 :                 if (heap->real_size > heap->real_peak) {
    2215               4 :                         heap->real_peak = heap->real_size;
    2216                 :                 }
    2217                 : 
    2218               8 :                 segment->size = segment_size;
    2219                 : 
    2220               8 :                 if (segment != segment_copy) {
    2221               5 :                         zend_mm_segment **seg = &heap->segments_list;
    2222              10 :                         while (*seg != segment_copy) {
    2223               0 :                                 seg = &(*seg)->next_segment;
    2224                 :                         }
    2225               5 :                         *seg = segment;
    2226               5 :                         mm_block = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    2227               5 :                         ZEND_MM_MARK_FIRST_BLOCK(mm_block);
    2228                 :                 }
    2229                 : 
    2230               8 :                 block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
    2231               8 :                 remaining_size = block_size - true_size;
    2232                 : 
    2233                 :                 /* setup guard block */
    2234               8 :                 ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size));
    2235                 : 
    2236               8 :                 if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2237               0 :                         true_size = block_size;
    2238               0 :                         ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2239                 :                 } else {
    2240                 :                         zend_mm_free_block *new_free_block;
    2241                 : 
    2242                 :                         /* prepare new free block */
    2243               8 :                         ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2244               8 :                         new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
    2245               8 :                         ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2246                 : 
    2247                 :                         /* add the new free block to the free list */
    2248               8 :                         zend_mm_add_to_rest_list(heap, new_free_block);
    2249                 :                 }
    2250                 : 
    2251                 :                 ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
    2252                 : 
    2253               8 :                 heap->size = heap->size + true_size - orig_size;
    2254               8 :                 if (heap->peak < heap->size) {
    2255               3 :                         heap->peak = heap->size;
    2256                 :                 }
    2257                 : 
    2258               8 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2259               8 :                 return ZEND_MM_DATA_OF(mm_block);
    2260                 :         }
    2261                 : 
    2262         1410740 :         ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2263                 : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2264                 :         memcpy(ptr, p, mm_block->debug.size);
    2265                 : #else
    2266         1410740 :         memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
    2267                 : #endif
    2268         1410740 :         _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2269         1410740 :         return ptr;
    2270                 : }
    2271                 : /* }}} */
    2272                 : 
    2273                 : ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2274               0 : {
    2275               0 :         return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2276                 : }
    2277                 : /* }}} */
    2278                 : 
    2279                 : ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2280               0 : {
    2281               0 :         _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2282               0 : }
    2283                 : /* }}} */
    2284                 : 
    2285                 : ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2286               0 : {
    2287               0 :         return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2288                 : }
    2289                 : /* }}} */
    2290                 : 
    2291                 : ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2292               0 : {
    2293                 :         zend_mm_block *mm_block;
    2294                 : 
    2295               0 :         if (!ZEND_MM_VALID_PTR(p)) {
    2296               0 :                 return 0;
    2297                 :         }
    2298               0 :         mm_block = ZEND_MM_HEADER_OF(p);
    2299                 :         ZEND_MM_CHECK_PROTECTION(mm_block);
    2300                 : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2301                 :         return mm_block->debug.size;
    2302                 : #else
    2303               0 :         return ZEND_MM_BLOCK_SIZE(mm_block);
    2304                 : #endif
    2305                 : }
    2306                 : /* }}} */
    2307                 : 
    2308                 : /**********************/
    2309                 : /* Allocation Manager */
    2310                 : /**********************/
    2311                 : 
    2312                 : typedef struct _zend_alloc_globals {
    2313                 :         zend_mm_heap *mm_heap;
    2314                 : } zend_alloc_globals;
    2315                 : 
    2316                 : #ifdef ZTS
    2317                 : static int alloc_globals_id;
    2318                 : # define AG(v) TSRMG(alloc_globals_id, zend_alloc_globals *, v)
    2319                 : #else
    2320                 : # define AG(v) (alloc_globals.v)
    2321                 : static zend_alloc_globals alloc_globals;
    2322                 : #endif
    2323                 : 
    2324                 : ZEND_API int is_zend_mm(TSRMLS_D) /* {{{ */
    2325              27 : {
    2326              27 :         return AG(mm_heap)->use_zend_alloc;
    2327                 : }
    2328                 : /* }}} */
    2329                 : 
    2330                 : ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2331       322889692 : {
    2332                 :         TSRMLS_FETCH();
    2333                 : 
    2334       322889692 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2335       202542227 :                 return AG(mm_heap)->_malloc(size);
    2336                 :         }
    2337       120347465 :         return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2338                 : }
    2339                 : /* }}} */
    2340                 : 
    2341                 : ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2342       380254327 : {
    2343                 :         TSRMLS_FETCH();
    2344                 : 
    2345       380254327 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2346       239007305 :                 AG(mm_heap)->_free(ptr);
    2347       239007305 :                 return;
    2348                 :         }
    2349       141247022 :         _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2350                 : }
    2351                 : /* }}} */
    2352                 : 
    2353                 : ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2354        70789929 : {
    2355                 :         TSRMLS_FETCH();
    2356                 : 
    2357        70789929 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2358        39872742 :                 return AG(mm_heap)->_realloc(ptr, size);
    2359                 :         }
    2360        30917187 :         return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2361                 : }
    2362                 : /* }}} */
    2363                 : 
    2364                 : ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2365               0 : {
    2366               0 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2367               0 :                 return 0;
    2368                 :         }
    2369               0 :         return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2370                 : }
    2371                 : /* }}} */
    2372                 : 
    2373                 : #if defined(__GNUC__) && defined(i386)
    2374                 : 
    2375                 : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) /* {{{ */
    2376        15099058 : {
    2377        15099058 :         size_t res = nmemb;
    2378        15099058 :         unsigned long overflow = 0;
    2379                 : 
    2380        15099058 :         __asm__ ("mull %3\n\taddl %4,%0\n\tadcl %1,%1"
    2381                 :              : "=&a"(res), "=&d" (overflow)
    2382                 :              : "%0"(res),
    2383                 :                "rm"(size),
    2384                 :                "rm"(offset));
    2385                 :         
    2386        15099058 :         if (UNEXPECTED(overflow)) {
    2387               0 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2388                 :                 return 0;
    2389                 :         }
    2390        15099058 :         return res;
    2391                 : }
    2392                 : /* }}} */
    2393                 : 
    2394                 : #elif defined(__GNUC__) && defined(__x86_64__)
    2395                 : 
    2396                 : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2397                 : {
    2398                 :         size_t res = nmemb;
    2399                 :         unsigned long overflow = 0;
    2400                 : 
    2401                 :         __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq %1,%1"
    2402                 :              : "=&a"(res), "=&d" (overflow)
    2403                 :              : "%0"(res),
    2404                 :                "rm"(size),
    2405                 :                "rm"(offset));
    2406                 : 
    2407                 :         if (UNEXPECTED(overflow)) {
    2408                 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2409                 :                 return 0;
    2410                 :         }
    2411                 :         return res;
    2412                 : }
    2413                 : 
    2414                 : #elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
    2415                 : 
    2416                 : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2417                 : {
    2418                 :         zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
    2419                 : 
    2420                 :         if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
    2421                 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2422                 :                 return 0;
    2423                 :         }
    2424                 :         return (size_t) res;
    2425                 : }
    2426                 : 
    2427                 : #else
    2428                 : 
    2429                 : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) /* {{{ */
    2430                 : {
    2431                 :         size_t res = nmemb * size + offset;
    2432                 :         double _d  = (double)nmemb * (double)size + (double)offset;
    2433                 :         double _delta = (double)res - _d;
    2434                 : 
    2435                 :         if (UNEXPECTED((_d + _delta ) != _d)) {
    2436                 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2437                 :                 return 0;
    2438                 :         }
    2439                 :         return res;
    2440                 : }
    2441                 : /* }}} */
    2442                 : #endif
    2443                 : 
    2444                 : ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2445        14975666 : {
    2446        14975666 :         return emalloc_rel(safe_address(nmemb, size, offset));
    2447                 : }
    2448                 : /* }}} */
    2449                 : 
    2450                 : ZEND_API UChar *_safe_eumalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2451               0 : {
    2452               0 :         size = safe_address(size, sizeof(UChar), 0);
    2453               0 :         offset = safe_address(offset, sizeof(UChar), 0);
    2454               0 :         return (UChar*) _safe_emalloc(nmemb, size, offset ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2455                 : }
    2456                 : /* }}} */
    2457                 : 
    2458                 : ZEND_API zstr _safe_ezmalloc(int type, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2459               0 : {
    2460               0 :         if (type == IS_STRING) {
    2461               0 :                 return ZSTR(_safe_emalloc(nmemb, size, offset ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2462                 :         } else {
    2463               0 :                 return ZSTR(_safe_eumalloc(nmemb, size, offset ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2464                 :         }
    2465                 : }
    2466                 : /* }}} */
    2467                 : 
    2468                 : ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) /* {{{ */
    2469          121287 : {
    2470          121287 :         return pemalloc(safe_address(nmemb, size, offset), 1);
    2471                 : }
    2472                 : /* }}} */
    2473                 : 
    2474                 : ZEND_API UChar *_safe_umalloc(size_t nmemb, size_t size, size_t offset) /* {{{ */
    2475               0 : {
    2476               0 :         size = safe_address(size, sizeof(UChar), 0);
    2477               0 :         offset = safe_address(size, sizeof(UChar), 0);
    2478               0 :         return pemalloc(safe_address(nmemb, size, offset), 1);
    2479                 : }
    2480                 : /* }}} */
    2481                 : 
    2482                 : ZEND_API zstr _safe_zmalloc(int type, size_t nmemb, size_t size, size_t offset) /* {{{ */
    2483               0 : {
    2484               0 :         if (type == IS_STRING) {
    2485               0 :                 return ZSTR(_safe_malloc(nmemb, size, offset));
    2486                 :         } else {
    2487               0 :                 return ZSTR(_safe_umalloc(nmemb, size, offset));
    2488                 :         }
    2489                 : }
    2490                 : /* }}} */
    2491                 : 
    2492                 : ZEND_API void *_safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2493            2105 : {
    2494            2105 :         return erealloc_rel(ptr, safe_address(nmemb, size, offset));
    2495                 : }
    2496                 : /* }}} */
    2497                 : 
    2498                 : ZEND_API UChar *_safe_eurealloc(UChar *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2499               0 : {
    2500               0 :         size = safe_address(size, sizeof(UChar), 0);
    2501               0 :         offset = safe_address(offset, sizeof(UChar), 0);
    2502               0 :         return (UChar*) _safe_erealloc(ptr, nmemb, size, offset ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2503                 : }
    2504                 : /* }}} */
    2505                 : 
    2506                 : ZEND_API zstr _safe_ezrealloc(int type, zstr str, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2507               0 : {
    2508               0 :         if (type == IS_STRING) {
    2509               0 :                 return ZSTR(_safe_erealloc(str.v, nmemb, size, offset ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2510                 :         } else {
    2511               0 :                 return ZSTR(_safe_eurealloc(str.u, nmemb, size, offset ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2512                 :         }
    2513                 : }
    2514                 : /* }}} */
    2515                 : 
    2516                 : ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset) /* {{{ */
    2517               0 : {
    2518               0 :         return perealloc(ptr, safe_address(nmemb, size, offset), 1);
    2519                 : }
    2520                 : /* }}} */
    2521                 : 
    2522                 : ZEND_API UChar *_safe_urealloc(UChar *ptr, size_t nmemb, size_t size, size_t offset) /* {{{ */
    2523               0 : {
    2524               0 :         size = safe_address(size, sizeof(UChar), 0);
    2525               0 :         offset = safe_address(offset, sizeof(UChar), 0);
    2526               0 :         return (UChar*) perealloc(ptr, safe_address(nmemb, size, offset), 1);
    2527                 : }
    2528                 : /* }}} */
    2529                 : 
    2530                 : ZEND_API zstr _safe_zrealloc(int type, zstr str, size_t nmemb, size_t size, size_t offset) /* {{{ */
    2531               0 : {
    2532               0 :         if (type == IS_STRING) {
    2533               0 :                 return ZSTR(_safe_realloc(str.s, nmemb, size, offset));
    2534                 :         } else {
    2535               0 :                 return ZSTR(_safe_urealloc(str.u, nmemb, size, offset));
    2536                 :         }
    2537                 : }
    2538                 : /* }}} */
    2539                 : 
    2540                 : ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2541        10589044 : {
    2542                 :         void *p;
    2543                 : 
    2544        10589044 :         p = _safe_emalloc(nmemb, size, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2545        10589044 :         if (UNEXPECTED(p == NULL)) {
    2546               0 :                 return p;
    2547                 :         }
    2548        10589044 :         memset(p, 0, size * nmemb);
    2549        10589044 :         return p;
    2550                 : }
    2551                 : /* }}} */
    2552                 : 
    2553                 : ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2554         1627480 : {
    2555                 :         int length;
    2556                 :         char *p;
    2557                 : 
    2558         1627480 :         length = strlen(s)+1;
    2559         1627480 :         p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2560         1627480 :         if (UNEXPECTED(p == NULL)) {
    2561               0 :                 return p;
    2562                 :         }
    2563         1627480 :         memcpy(p, s, length);
    2564         1627480 :         return p;
    2565                 : }
    2566                 : /* }}} */
    2567                 : 
    2568                 : ZEND_API UChar *_eustrdup(const UChar *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2569             589 : {
    2570                 :         int length;
    2571                 :         UChar *p;
    2572                 : 
    2573             589 :         length = u_strlen(s)+1;
    2574             589 :         p = (UChar *) _emalloc(sizeof(UChar) * length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2575             589 :         if (!p) {
    2576               0 :                 return (UChar *)NULL;
    2577                 :         }
    2578             589 :         u_memcpy(p, s, length);
    2579             589 :         return p;
    2580                 : }
    2581                 : /* }}} */
    2582                 : 
    2583                 : ZEND_API zstr _ezstrdup(int type, const zstr str ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2584               0 : {
    2585               0 :         if (type == IS_STRING) {
    2586               0 :                 return ZSTR(_estrdup(str.s ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2587                 :         } else {
    2588               0 :                 return ZSTR(_eustrdup(str.u ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2589                 :         }
    2590                 : }
    2591                 : /* }}} */
    2592                 : 
    2593                 : ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2594        19490741 : {
    2595                 :         char *p;
    2596                 : 
    2597        19490741 :         p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2598        19490741 :         if (UNEXPECTED(p == NULL)) {
    2599               0 :                 return p;
    2600                 :         }
    2601        19490741 :         memcpy(p, s, length);
    2602        19490741 :         p[length] = 0;
    2603        19490741 :         return p;
    2604                 : }
    2605                 : /* }}} */
    2606                 : 
    2607                 : ZEND_API UChar *_eustrndup(const UChar *s, int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2608        13117025 : {
    2609                 :         UChar *p;
    2610                 : 
    2611        13117025 :         p = (UChar *) _emalloc(sizeof(UChar) * (length+1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2612        13117025 :         if (!p) {
    2613               0 :                 return (UChar *)NULL;
    2614                 :         }
    2615        13117025 :         memcpy(p, s, length * sizeof(UChar));
    2616        13117025 :         p[length] = 0;
    2617        13117025 :         return p;
    2618                 : }
    2619                 : /* }}} */
    2620                 : 
    2621                 : ZEND_API zstr _ezstrndup(int type, const zstr s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2622            9234 : {
    2623            9234 :         if (type == IS_STRING) {
    2624            2892 :                 return ZSTR(_estrndup(s.s, length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2625                 :         } else {
    2626            6342 :                 return ZSTR(_eustrndup(s.u, length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC));
    2627                 :         }
    2628                 : }
    2629                 : /* }}} */
    2630                 : 
    2631                 : ZEND_API char *zend_strndup(const char *s, uint length) /* {{{ */
    2632         2543630 : {
    2633                 :         char *p;
    2634                 : 
    2635         2543630 :         p = (char *) malloc(length+1);
    2636         2543630 :         if (UNEXPECTED(p == NULL)) {
    2637               0 :                 return p;
    2638                 :         }
    2639         2543630 :         if (length) {
    2640         2340581 :                 memcpy(p, s, length);
    2641                 :         }
    2642         2543630 :         p[length] = 0;
    2643         2543630 :         return p;
    2644                 : }
    2645                 : /* }}} */
    2646                 : 
    2647                 : ZEND_API UChar *zend_ustrdup(const UChar *s) /* {{{ */
    2648               0 : {
    2649                 :         UChar *p;
    2650                 :         uint length;
    2651                 : 
    2652               0 :         length = u_strlen(s)+1;
    2653               0 :         p = (UChar *) malloc(UBYTES(length+1));
    2654               0 :         if (!p) {
    2655               0 :                 return (UChar *)NULL;
    2656                 :         }
    2657               0 :         if (length) {
    2658               0 :                 memcpy(p, s, UBYTES(length));
    2659                 :         }
    2660               0 :         p[length] = 0;
    2661               0 :         return p;
    2662                 : }
    2663                 : /* }}} */
    2664                 : 
    2665                 : ZEND_API UChar *zend_ustrndup(const UChar *s, uint length) /* {{{ */
    2666        34058672 : {
    2667                 :         UChar *p;
    2668                 : 
    2669        34058672 :         p = (UChar *) malloc(UBYTES(length+1));
    2670        34058672 :         if (!p) {
    2671               0 :                 return (UChar *)NULL;
    2672                 :         }
    2673        34058672 :         if (length) {
    2674        34058671 :                 memcpy(p, s, UBYTES(length));
    2675                 :         }
    2676        34058672 :         p[length] = 0;
    2677        34058672 :         return p;
    2678                 : }
    2679                 : /* }}} */
    2680                 : 
    2681                 : ZEND_API zstr zend_zstrndup(int type, const zstr s, uint length) /* {{{ */
    2682               0 : {
    2683               0 :         if (type == IS_STRING) {
    2684               0 :                 return ZSTR(zend_strndup(s.s, length));
    2685                 :         } else {
    2686               0 :                 return ZSTR(zend_ustrndup(s.u, length));
    2687                 :         }
    2688                 : }
    2689                 : /* }}} */
    2690                 : 
    2691                 : ZEND_API zstr zend_zstrdup(int type, const zstr s) /* {{{ */
    2692               0 : {
    2693               0 :         if (type == IS_STRING) {
    2694               0 :                 return ZSTR(strdup(s.s));
    2695                 :         } else {
    2696               0 :                 return ZSTR(zend_ustrdup(s.u));
    2697                 :         }
    2698                 : }
    2699                 : /* }}} */
    2700                 : 
    2701                 : ZEND_API int zend_set_memory_limit(size_t memory_limit) /* {{{ */
    2702           17609 : {
    2703                 :         TSRMLS_FETCH();
    2704                 : 
    2705           17609 :         AG(mm_heap)->limit = (memory_limit >= AG(mm_heap)->block_size) ? memory_limit : AG(mm_heap)->block_size;
    2706                 : 
    2707           17609 :         return SUCCESS;
    2708                 : }
    2709                 : /* }}} */
    2710                 : 
    2711                 : ZEND_API size_t zend_memory_usage(int real_usage TSRMLS_DC) /* {{{ */
    2712          600325 : {
    2713          600325 :         if (real_usage) {
    2714            9438 :                 return AG(mm_heap)->real_size;
    2715                 :         } else {
    2716          590887 :                 size_t usage = AG(mm_heap)->size;
    2717                 : #if ZEND_MM_CACHE
    2718          590887 :                 usage -= AG(mm_heap)->cached;
    2719                 : #endif
    2720          590887 :                 return usage;
    2721                 :         }
    2722                 : }
    2723                 : /* }}} */
    2724                 : 
    2725                 : ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC) /* {{{ */
    2726               1 : {
    2727               1 :         if (real_usage) {
    2728               0 :                 return AG(mm_heap)->real_peak;
    2729                 :         } else {
    2730               1 :                 return AG(mm_heap)->peak;
    2731                 :         }
    2732                 : }
    2733                 : /* }}} */
    2734                 : 
    2735                 : ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC) /* {{{ */
    2736           51071 : {
    2737           51071 :         zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC);
    2738           51071 : }
    2739                 : /* }}} */
    2740                 : 
    2741                 : static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC) /* {{{ */
    2742           17007 : {
    2743                 :         char *tmp;
    2744           17007 :         alloc_globals->mm_heap = zend_mm_startup();
    2745                 : 
    2746           17007 :         tmp = getenv("USE_ZEND_ALLOC");
    2747           17007 :         if (tmp) {
    2748           17001 :                 alloc_globals->mm_heap->use_zend_alloc = zend_atoi(tmp, 0);
    2749           17001 :                 if (!alloc_globals->mm_heap->use_zend_alloc) {
    2750           17001 :                         alloc_globals->mm_heap->_malloc = malloc;
    2751           17001 :                         alloc_globals->mm_heap->_free = free;
    2752           17001 :                         alloc_globals->mm_heap->_realloc = realloc;
    2753                 :                 }
    2754                 :         }
    2755           17007 : }
    2756                 : /* }}} */
    2757                 : 
    2758                 : #ifdef ZTS
    2759                 : static void alloc_globals_dtor(zend_alloc_globals *alloc_globals TSRMLS_DC) /* {{{ */
    2760                 : {
    2761                 :         shutdown_memory_manager(1, 1 TSRMLS_CC);
    2762                 : }
    2763                 : /* }}} */
    2764                 : #endif
    2765                 : 
    2766                 : ZEND_API void start_memory_manager(TSRMLS_D) /* {{{ */
    2767           17007 : {
    2768                 : #ifdef ZTS
    2769                 :         ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
    2770                 : #else
    2771           17007 :         alloc_globals_ctor(&alloc_globals);
    2772                 : #endif
    2773           17007 : }
    2774                 : /* }}} */
    2775                 : 
    2776                 : ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap TSRMLS_DC) /* {{{ */
    2777               0 : {
    2778                 :         zend_mm_heap *old_heap;
    2779                 : 
    2780               0 :         old_heap = AG(mm_heap);
    2781               0 :         AG(mm_heap) = new_heap;
    2782               0 :         return old_heap;
    2783                 : }
    2784                 : /* }}} */
    2785                 : 
    2786                 : ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap) /* {{{ */
    2787               0 : {
    2788               0 :         return heap->storage;
    2789                 : }
    2790                 : /* }}} */
    2791                 : 
    2792                 : ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
    2793                 :                                           void* (*_malloc)(size_t),
    2794                 :                                           void  (*_free)(void*),
    2795                 :                                           void* (*_realloc)(void*, size_t))
    2796               0 : {
    2797               0 :         heap->use_zend_alloc = 0;
    2798               0 :         heap->_malloc = _malloc;
    2799               0 :         heap->_free = _free;
    2800               0 :         heap->_realloc = _realloc;
    2801               0 : }
    2802                 : 
    2803                 : #if ZEND_DEBUG
    2804                 : ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2805                 : {
    2806                 :         TSRMLS_FETCH();
    2807                 : 
    2808                 :         if (!AG(mm_heap)->use_zend_alloc) {
    2809                 :                 return 1;
    2810                 :         }
    2811                 :         return zend_mm_check_ptr(AG(mm_heap), ptr, silent ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2812                 : }
    2813                 : /* }}} */
    2814                 : 
    2815                 : ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */
    2816                 : {
    2817                 :         int errors;
    2818                 :         TSRMLS_FETCH();
    2819                 : 
    2820                 :         if (!AG(mm_heap)->use_zend_alloc) {
    2821                 :                 return;
    2822                 :         }
    2823                 : 
    2824                 :         zend_debug_alloc_output("------------------------------------------------\n");
    2825                 :         zend_debug_alloc_output("Full Memory Check at %s:%d\n" ZEND_FILE_LINE_RELAY_CC);
    2826                 : 
    2827                 :         errors = zend_mm_check_heap(AG(mm_heap), silent ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2828                 : 
    2829                 :         zend_debug_alloc_output("End of full memory check %s:%d (%d errors)\n" ZEND_FILE_LINE_RELAY_CC, errors);
    2830                 :         zend_debug_alloc_output("------------------------------------------------\n");
    2831                 : }
    2832                 : /* }}} */
    2833                 : #endif
    2834                 : 
    2835                 : /*
    2836                 :  * Local variables:
    2837                 :  * tab-width: 4
    2838                 :  * c-basic-offset: 4
    2839                 :  * indent-tabs-mode: t
    2840                 :  * End:
    2841                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:23 +0000 (34 hours ago)

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