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

LCOV - code coverage report
Current view: top level - Zend - zend_alloc.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 497 753 66.0 %
Date: 2014-12-20 Functions: 37 56 66.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 21 Dec 2014 04:58:46 +0000 (30 hours ago)

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