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-07-21 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       14532 : static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size)
     286             : {
     287       14532 :         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       14532 : static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr)
     296             : {
     297       14532 :         free(ptr);
     298       14532 : }
     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 ZEND_ATTRIBUTE_ALLOC_SIZE(2);
     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) ZEND_ATTRIBUTE_ALLOC_SIZE(3);
     664             : 
     665    16330926 : 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) : "cc");
     671             :         return n;
     672             : #elif defined(__GNUC__) && defined(__x86_64__)
     673             :         unsigned long n;
     674             : 
     675    16330926 :         __asm__("bsr %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
     676    16330926 :         return (unsigned int)n;
     677             : #elif defined(_MSC_VER) && defined(_M_IX86)
     678             :         __asm {
     679             :                 bsr eax, _size
     680             :         }
     681             : #elif defined(__GNUC__) && (defined(__arm__) ||  defined(__aarch64__))
     682             :         return (8 * SIZEOF_SIZE_T - 1) - __builtin_clzl(_size);
     683             : #else
     684             :         unsigned int n = 0;
     685             :         while (_size != 0) {
     686             :                 _size = _size >> 1;
     687             :                 n++;
     688             :         }
     689             :         return n-1;
     690             : #endif
     691             : }
     692             : 
     693    35247970 : static inline unsigned int zend_mm_low_bit(size_t _size)
     694             : {
     695             : #if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
     696             :         unsigned int n;
     697             : 
     698             :         __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
     699             :         return n;
     700             : #elif defined(__GNUC__) && defined(__x86_64__)
     701             :         unsigned long n;
     702             : 
     703    35247970 :         __asm__("bsf %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
     704    35247970 :         return (unsigned int)n;
     705             : #elif defined(_MSC_VER) && defined(_M_IX86)
     706             :         __asm {
     707             :                 bsf eax, _size
     708             :    }
     709             : #elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
     710             :         return __builtin_ctzl(_size);
     711             : #else
     712             :         static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
     713             :         unsigned int n;
     714             :         unsigned int index = 0;
     715             : 
     716             :         n = offset[_size & 15];
     717             :         while (n == 4) {
     718             :                 _size >>= 4;
     719             :                 index += n;
     720             :                 n = offset[_size & 15];
     721             :         }
     722             : 
     723             :         return index + n;
     724             : #endif
     725             : }
     726             : 
     727    49699408 : static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
     728             : {
     729             :         size_t size;
     730             :         size_t index;
     731             : 
     732             :         ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
     733             : 
     734    49699408 :         size = ZEND_MM_FREE_BLOCK_SIZE(mm_block);
     735    49699408 :         if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) {
     736             :                 zend_mm_free_block **p;
     737             : 
     738     6689628 :                 index = ZEND_MM_LARGE_BUCKET_INDEX(size);
     739     6689628 :                 p = &heap->large_free_buckets[index];
     740     6689628 :                 mm_block->child[0] = mm_block->child[1] = NULL;
     741     6689628 :                 if (!*p) {
     742     4848377 :                         *p = mm_block;
     743     4848377 :                         mm_block->parent = p;
     744     4848377 :                         mm_block->prev_free_block = mm_block->next_free_block = mm_block;
     745     4848377 :                         heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
     746             :                 } else {
     747             :                         size_t m;
     748             : 
     749     2982498 :                         for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
     750     2982498 :                                 zend_mm_free_block *prev = *p;
     751             : 
     752     2982498 :                                 if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) {
     753     2878835 :                                         p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1];
     754     2878835 :                                         if (!*p) {
     755     1737588 :                                                 *p = mm_block;
     756     1737588 :                                                 mm_block->parent = p;
     757     1737588 :                                                 mm_block->prev_free_block = mm_block->next_free_block = mm_block;
     758     1737588 :                                                 break;
     759             :                                         }
     760             :                                 } else {
     761      103663 :                                         zend_mm_free_block *next = prev->next_free_block;
     762             : 
     763      103663 :                                         prev->next_free_block = next->prev_free_block = mm_block;
     764      103663 :                                         mm_block->next_free_block = next;
     765      103663 :                                         mm_block->prev_free_block = prev;
     766      103663 :                                         mm_block->parent = NULL;
     767      103663 :                                         break;
     768             :                                 }
     769     1141247 :                         }
     770             :                 }
     771             :         } else {
     772             :                 zend_mm_free_block *prev, *next;
     773             : 
     774    43009780 :                 index = ZEND_MM_BUCKET_INDEX(size);
     775             : 
     776    43009780 :                 prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index);
     777    43009780 :                 if (prev->prev_free_block == prev) {
     778    17336217 :                         heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index);
     779             :                 }
     780    43009780 :                 next = prev->next_free_block;
     781             : 
     782    43009780 :                 mm_block->prev_free_block = prev;
     783    43009780 :                 mm_block->next_free_block = next;
     784    43009780 :                 prev->next_free_block = next->prev_free_block = mm_block;
     785             :         }
     786    49699408 : }
     787             : 
     788    49736375 : static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
     789             : {
     790    49736375 :         zend_mm_free_block *prev = mm_block->prev_free_block;
     791    49736375 :         zend_mm_free_block *next = mm_block->next_free_block;
     792             : 
     793             :         ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED);
     794             : 
     795    49736375 :         if (EXPECTED(prev == mm_block)) {
     796             :                 zend_mm_free_block **rp, **cp;
     797             : 
     798             : #if ZEND_MM_SAFE_UNLINKING
     799     6585434 :                 if (UNEXPECTED(next != mm_block)) {
     800           0 :                         zend_mm_panic("zend_mm_heap corrupted");
     801             :                 }
     802             : #endif
     803             : 
     804     6585434 :                 rp = &mm_block->child[mm_block->child[1] != NULL];
     805     6585434 :                 prev = *rp;
     806     6585434 :                 if (EXPECTED(prev == NULL)) {
     807     5827092 :                         size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
     808             : 
     809     5827092 :                         ZEND_MM_CHECK_TREE(mm_block);
     810     5827092 :                         *mm_block->parent = NULL;
     811     5827092 :                         if (mm_block->parent == &heap->large_free_buckets[index]) {
     812     4848327 :                                 heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
     813             :                     }
     814             :                 } else {
     815     1894361 :                         while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) {
     816      377677 :                                 prev = *cp;
     817      377677 :                                 rp = cp;
     818             :                         }
     819      758342 :                         *rp = NULL;
     820             : 
     821             : subst_block:
     822      767253 :                         ZEND_MM_CHECK_TREE(mm_block);
     823      767253 :                         *mm_block->parent = prev;
     824      767253 :                         prev->parent = mm_block->parent;
     825      767253 :                         if ((prev->child[0] = mm_block->child[0])) {
     826      348345 :                                 ZEND_MM_CHECK_TREE(prev->child[0]);
     827      348345 :                                 prev->child[0]->parent = &prev->child[0];
     828             :                         }
     829      767253 :                         if ((prev->child[1] = mm_block->child[1])) {
     830       35134 :                                 ZEND_MM_CHECK_TREE(prev->child[1]);
     831       35134 :                                 prev->child[1]->parent = &prev->child[1];
     832             :                         }
     833             :                 }
     834             :         } else {
     835             : 
     836             : #if ZEND_MM_SAFE_UNLINKING
     837    43150941 :                 if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) {
     838           0 :                         zend_mm_panic("zend_mm_heap corrupted");
     839             :                 }
     840             : #endif
     841             : 
     842    43150941 :                 prev->next_free_block = next;
     843    43150941 :                 next->prev_free_block = prev;
     844             : 
     845    43150941 :                 if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) {
     846    43007295 :                         if (EXPECTED(prev == next)) {
     847    17336149 :                                 size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block));
     848             : 
     849    17336149 :                                 if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) {
     850    17336149 :                                         heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index);
     851             :                                 }
     852             :                         }
     853      143646 :                 } else if (UNEXPECTED(mm_block->parent == ZEND_MM_REST_BLOCK)) {
     854       40730 :                         heap->rest_count--;
     855      102916 :                 } else if (UNEXPECTED(mm_block->parent != NULL)) {
     856        8911 :                         goto subst_block;
     857             :                 }
     858             :         }
     859    49736375 : }
     860             : 
     861       40730 : static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block)
     862             : {
     863             :         zend_mm_free_block *prev, *next;
     864             : 
     865       81460 :         while (heap->rest_count >= ZEND_MM_MAX_REST_BLOCKS) {
     866           0 :                 zend_mm_free_block *p = heap->rest_buckets[1];
     867             : 
     868           0 :                 if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(p))) {
     869           0 :                         heap->rest_count--;
     870             :                 }
     871           0 :                 prev = p->prev_free_block;
     872           0 :                 next = p->next_free_block;
     873           0 :                 prev->next_free_block = next;
     874           0 :                 next->prev_free_block = prev;
     875           0 :                 zend_mm_add_to_free_list(heap, p);
     876             :         }
     877             : 
     878       40730 :         if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) {
     879       40730 :                 mm_block->parent = ZEND_MM_REST_BLOCK;
     880       40730 :                 heap->rest_count++;
     881             :         }
     882             : 
     883             :         ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED);
     884             : 
     885       40730 :         prev = heap->rest_buckets[0];
     886       40730 :         next = prev->next_free_block;
     887       40730 :         mm_block->prev_free_block = prev;
     888       40730 :         mm_block->next_free_block = next;
     889       40730 :         prev->next_free_block = next->prev_free_block = mm_block;
     890       40730 : }
     891             : 
     892          24 : static inline void zend_mm_init(zend_mm_heap *heap)
     893             : {
     894             :         zend_mm_free_block* p;
     895             :         int i;
     896             : 
     897          24 :         heap->free_bitmap = 0;
     898          24 :         heap->large_free_bitmap = 0;
     899             : #if ZEND_MM_CACHE
     900          24 :         heap->cached = 0;
     901          24 :         memset(heap->cache, 0, sizeof(heap->cache));
     902             : #endif
     903             : #if ZEND_MM_CACHE_STAT
     904             :         for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
     905             :                 heap->cache_stat[i].count = 0;
     906             :         }
     907             : #endif
     908          24 :         p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
     909        1560 :         for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
     910        1536 :                 p->next_free_block = p;
     911        1536 :                 p->prev_free_block = p;
     912        1536 :                 p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
     913        1536 :                 heap->large_free_buckets[i] = NULL;
     914             :         }
     915          24 :         heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap);
     916          24 :         heap->rest_count = 0;
     917          24 : }
     918             : 
     919       14499 : static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment)
     920             : {
     921       14499 :         zend_mm_segment **p = &heap->segments_list;
     922             : 
     923       29248 :         while (*p != segment) {
     924         250 :                 p = &(*p)->next_segment;
     925             :         }
     926       14499 :         *p = segment->next_segment;
     927       14499 :         heap->real_size -= segment->size;
     928       14499 :         ZEND_MM_STORAGE_FREE(segment);
     929       14499 : }
     930             : 
     931             : #if ZEND_MM_CACHE
     932           0 : static void zend_mm_free_cache(zend_mm_heap *heap)
     933             : {
     934             :         int i;
     935             : 
     936           0 :         for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
     937           0 :                 if (heap->cache[i]) {
     938           0 :                         zend_mm_free_block *mm_block = heap->cache[i];
     939             : 
     940           0 :                         while (mm_block) {
     941           0 :                                 size_t size = ZEND_MM_BLOCK_SIZE(mm_block);
     942           0 :                                 zend_mm_free_block *q = mm_block->prev_free_block;
     943           0 :                                 zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block);
     944             : 
     945           0 :                                 heap->cached -= size;
     946             : 
     947           0 :                                 if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
     948           0 :                                         mm_block = (zend_mm_free_block*)ZEND_MM_PREV_BLOCK(mm_block);
     949           0 :                                         size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
     950           0 :                                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) mm_block);
     951             :                                 }
     952           0 :                                 if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
     953           0 :                                         size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
     954           0 :                                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
     955             :                                 }
     956           0 :                                 ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
     957             : 
     958           0 :                                 if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
     959           0 :                                     ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) {
     960           0 :                                         zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
     961             :                                 } else {
     962           0 :                                         zend_mm_add_to_free_list(heap, (zend_mm_free_block *) mm_block);
     963             :                                 }
     964             : 
     965           0 :                                 mm_block = q;
     966             :                         }
     967           0 :                         heap->cache[i] = NULL;
     968             : #if ZEND_MM_CACHE_STAT
     969             :                         heap->cache_stat[i].count = 0;
     970             : #endif
     971             :                 }
     972             :         }
     973           0 : }
     974             : #endif
     975             : 
     976             : #if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES
     977             : static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */
     978             : {
     979             :         size_t i = 0;
     980             :         unsigned char t;
     981             : 
     982             : #ifdef ZEND_WIN32
     983             :         HCRYPTPROV   hCryptProv;
     984             :         int has_context = 0;
     985             : 
     986             :         if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
     987             :                 /* Could mean that the key container does not exist, let try 
     988             :                    again by asking for a new one */
     989             :                 if (GetLastError() == NTE_BAD_KEYSET) {
     990             :                         if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
     991             :                                 has_context = 1;
     992             :                         }
     993             :                 }
     994             :         } else {
     995             :                 has_context = 1;
     996             :         }
     997             :         if (has_context) {
     998             :                 do {
     999             :                         BOOL ret = CryptGenRandom(hCryptProv, size, buf);
    1000             :                         CryptReleaseContext(hCryptProv, 0);
    1001             :                         if (ret) {
    1002             :                                 while (i < size && buf[i] != 0) {
    1003             :                                         i++;
    1004             :                                 }
    1005             :                                 if (i == size) {
    1006             :                                         return;
    1007             :                                 }
    1008             :                    }
    1009             :                 } while (0);
    1010             :         }
    1011             : #elif defined(HAVE_DEV_URANDOM)
    1012             :         int fd = open("/dev/urandom", 0);
    1013             : 
    1014             :         if (fd >= 0) {
    1015             :                 if (read(fd, buf, size) == size) {
    1016             :                         while (i < size && buf[i] != 0) {
    1017             :                                 i++;
    1018             :                         }
    1019             :                         if (i == size) {
    1020             :                                 close(fd);
    1021             :                             return;
    1022             :                         }
    1023             :                 }
    1024             :                 close(fd);
    1025             :         }
    1026             : #endif
    1027             :         t = (unsigned char)getpid();
    1028             :         while (i < size) {
    1029             :                 do {
    1030             :                         buf[i] = ((unsigned char)rand()) ^ t;
    1031             :                 } while (buf[i] == 0);
    1032             :                 t = buf[i++] << 1;
    1033             :     }
    1034             : }
    1035             : /* }}} */
    1036             : #endif
    1037             : 
    1038             : /* Notes:
    1039             :  * - This function may alter the block_sizes values to match platform alignment
    1040             :  * - This function does *not* perform sanity checks on the arguments
    1041             :  */
    1042           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)
    1043             : {
    1044             :         zend_mm_storage *storage;
    1045             :         zend_mm_heap    *heap;
    1046             : 
    1047             : #if 0
    1048             :         int i;
    1049             : 
    1050             :         printf("ZEND_MM_ALIGNMENT=%d\n", ZEND_MM_ALIGNMENT);
    1051             :         printf("ZEND_MM_ALIGNMENT_LOG2=%d\n", ZEND_MM_ALIGNMENT_LOG2);
    1052             :         printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE);
    1053             :         printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE);
    1054             :         printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE);
    1055             :         printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
    1056             :         printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE);
    1057             :         printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE);
    1058             :         printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1059             :         for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) {
    1060             :                 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)));
    1061             :         }
    1062             :         exit(0);
    1063             : #endif
    1064             : 
    1065             : #if ZEND_MM_HEAP_PROTECTION
    1066             :         if (_mem_block_start_magic == 0) {
    1067             :                 zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic));
    1068             :         }
    1069             :         if (_mem_block_end_magic == 0) {
    1070             :                 zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic));
    1071             :         }
    1072             : #endif
    1073             : #if ZEND_MM_COOKIES
    1074             :         if (_zend_mm_cookie == 0) {
    1075             :                 zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie));
    1076             :         }
    1077             : #endif
    1078             : 
    1079           8 :         if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) {
    1080           0 :                 fprintf(stderr, "'block_size' must be a power of two\n");
    1081             : /* See http://support.microsoft.com/kb/190351 */
    1082             : #ifdef PHP_WIN32
    1083             :                 fflush(stderr);
    1084             : #endif
    1085           0 :                 exit(255);
    1086             :         }
    1087           8 :         storage = handlers->init(params);
    1088           8 :         if (!storage) {
    1089           0 :                 fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name);
    1090             : /* See http://support.microsoft.com/kb/190351 */
    1091             : #ifdef PHP_WIN32
    1092             :                 fflush(stderr);
    1093             : #endif
    1094           0 :                 exit(255);
    1095             :         }
    1096           8 :         storage->handlers = handlers;
    1097             : 
    1098           8 :         heap = malloc(sizeof(struct _zend_mm_heap));
    1099           8 :         if (heap == NULL) {
    1100           0 :                 fprintf(stderr, "Cannot allocate heap for zend_mm storage [%s]\n", handlers->name);
    1101             : #ifdef PHP_WIN32
    1102             :                 fflush(stderr);
    1103             : #endif
    1104           0 :                 exit(255);
    1105             :         }
    1106           8 :         heap->storage = storage;
    1107           8 :         heap->block_size = block_size;
    1108           8 :         heap->compact_size = 0;
    1109           8 :         heap->segments_list = NULL;
    1110           8 :         zend_mm_init(heap);
    1111             : # if ZEND_MM_CACHE_STAT
    1112             :         memset(heap->cache_stat, 0, sizeof(heap->cache_stat));
    1113             : # endif
    1114             : 
    1115           8 :         heap->use_zend_alloc = 1;
    1116           8 :         heap->real_size = 0;
    1117           8 :         heap->overflow = 0;
    1118           8 :         heap->real_peak = 0;
    1119           8 :         heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2);
    1120           8 :         heap->size = 0;
    1121           8 :         heap->peak = 0;
    1122           8 :         heap->internal = internal;
    1123           8 :         heap->reserve = NULL;
    1124           8 :         heap->reserve_size = reserve_size;
    1125           8 :         if (reserve_size > 0) {
    1126           8 :                 heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1127             :         }
    1128           8 :         if (internal) {
    1129             :                 int i;
    1130             :                 zend_mm_free_block *p, *q, *orig;
    1131           0 :                 zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap)  ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1132             : 
    1133           0 :                 *mm_heap = *heap;
    1134             : 
    1135           0 :                 p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0);
    1136           0 :                 orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0);
    1137           0 :                 for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) {
    1138           0 :                         q = p;
    1139           0 :                         while (q->prev_free_block != orig) {
    1140           0 :                                 q = q->prev_free_block;
    1141             :                         }
    1142           0 :                         q->prev_free_block = p;
    1143           0 :                         q = p;
    1144           0 :                         while (q->next_free_block != orig) {
    1145           0 :                                 q = q->next_free_block;
    1146             :                         }
    1147           0 :                         q->next_free_block = p;
    1148           0 :                         p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2);
    1149           0 :                         orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2);
    1150           0 :                         if (mm_heap->large_free_buckets[i]) {
    1151           0 :                                 mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i];
    1152             :                         }
    1153             :                 }
    1154           0 :                 mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap);
    1155           0 :                 mm_heap->rest_count = 0;
    1156             : 
    1157           0 :                 free(heap);
    1158           0 :                 heap = mm_heap;
    1159             :         }
    1160           8 :         return heap;
    1161             : }
    1162             : 
    1163           8 : ZEND_API zend_mm_heap *zend_mm_startup(void)
    1164             : {
    1165             :         int i;
    1166             :         size_t seg_size;
    1167           8 :         char *mem_type = getenv("ZEND_MM_MEM_TYPE");
    1168             :         char *tmp;
    1169             :         const zend_mm_mem_handlers *handlers;
    1170             :         zend_mm_heap *heap;
    1171             : 
    1172           8 :         if (mem_type == NULL) {
    1173           8 :                 i = 0;
    1174             :         } else {
    1175           0 :                 for (i = 0; mem_handlers[i].name; i++) {
    1176           0 :                         if (strcmp(mem_handlers[i].name, mem_type) == 0) {
    1177           0 :                                 break;
    1178             :                         }
    1179             :                 }
    1180           0 :                 if (!mem_handlers[i].name) {
    1181           0 :                         fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);
    1182           0 :                         fprintf(stderr, "  supported types:\n");
    1183             : /* See http://support.microsoft.com/kb/190351 */
    1184             : #ifdef PHP_WIN32
    1185             :                         fflush(stderr);
    1186             : #endif
    1187           0 :                         for (i = 0; mem_handlers[i].name; i++) {
    1188           0 :                                 fprintf(stderr, "    '%s'\n", mem_handlers[i].name);
    1189             :                         }
    1190             : /* See http://support.microsoft.com/kb/190351 */
    1191             : #ifdef PHP_WIN32
    1192             :                         fflush(stderr);
    1193             : #endif
    1194           0 :                         exit(255);
    1195             :                 }
    1196             :         }
    1197           8 :         handlers = &mem_handlers[i];
    1198             : 
    1199           8 :         tmp = getenv("ZEND_MM_SEG_SIZE");
    1200           8 :         if (tmp) {
    1201           0 :                 seg_size = zend_atoi(tmp, 0);
    1202           0 :                 if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {
    1203           0 :                         fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");
    1204             : /* See http://support.microsoft.com/kb/190351 */
    1205             : #ifdef PHP_WIN32
    1206             :                         fflush(stderr);
    1207             : #endif
    1208           0 :                         exit(255);
    1209           0 :                 } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {
    1210           0 :                         fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");
    1211             : /* See http://support.microsoft.com/kb/190351 */
    1212             : #ifdef PHP_WIN32
    1213             :                         fflush(stderr);
    1214             : #endif
    1215           0 :                         exit(255);
    1216             :                 }
    1217             :         } else {
    1218           8 :                 seg_size = ZEND_MM_SEG_SIZE;
    1219             :         }
    1220             : 
    1221           8 :         heap = zend_mm_startup_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL);
    1222           8 :         if (heap) {
    1223           8 :                 tmp = getenv("ZEND_MM_COMPACT");
    1224           8 :                 if (tmp) {
    1225           0 :                         heap->compact_size = zend_atoi(tmp, 0);
    1226             :                 } else {
    1227           8 :                         heap->compact_size = 2 * 1024 * 1024;
    1228             :                 }
    1229             :         }
    1230           8 :         return heap;
    1231             : }
    1232             : 
    1233             : #if ZEND_DEBUG
    1234             : static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b)
    1235             : {
    1236             :         long leaks = 0;
    1237             :         zend_mm_block *p, *q;
    1238             : 
    1239             :         p = ZEND_MM_NEXT_BLOCK(b);
    1240             :         while (1) {
    1241             :                 if (ZEND_MM_IS_GUARD_BLOCK(p)) {
    1242             :                         ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD);
    1243             :                         segment = segment->next_segment;
    1244             :                         if (!segment) {
    1245             :                                 break;
    1246             :                         }
    1247             :                         p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1248             :                         continue;
    1249             :                 }
    1250             :                 q = ZEND_MM_NEXT_BLOCK(p);
    1251             :                 if (q <= p ||
    1252             :                     (char*)q > (char*)segment + segment->size ||
    1253             :                     p->info._size != q->info._prev) {
    1254             :                     zend_mm_panic("zend_mm_heap corrupted");
    1255             :                 }
    1256             :                 if (!ZEND_MM_IS_FREE_BLOCK(p)) {
    1257             :                         if (p->magic == MEM_BLOCK_VALID) {
    1258             :                                 if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) {
    1259             :                                         ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
    1260             :                                         leaks++;
    1261             :                                 }
    1262             : #if ZEND_MM_CACHE
    1263             :                         } else if (p->magic == MEM_BLOCK_CACHED) {
    1264             :                                 /* skip it */
    1265             : #endif
    1266             :                         } else if (p->magic != MEM_BLOCK_LEAK) {
    1267             :                             zend_mm_panic("zend_mm_heap corrupted");
    1268             :                         }
    1269             :                 }
    1270             :                 p = q;
    1271             :         }
    1272             :         return leaks;
    1273             : }
    1274             : 
    1275             : static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC)
    1276             : {
    1277             :         zend_mm_segment *segment = heap->segments_list;
    1278             :         zend_mm_block *p, *q;
    1279             :         zend_uint total = 0;
    1280             : 
    1281             :         if (!segment) {
    1282             :                 return;
    1283             :         }
    1284             :         p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1285             :         while (1) {
    1286             :                 q = ZEND_MM_NEXT_BLOCK(p);
    1287             :                 if (q <= p ||
    1288             :                     (char*)q > (char*)segment + segment->size ||
    1289             :                     p->info._size != q->info._prev) {
    1290             :                         zend_mm_panic("zend_mm_heap corrupted");
    1291             :                 }
    1292             :                 if (!ZEND_MM_IS_FREE_BLOCK(p)) {
    1293             :                         if (p->magic == MEM_BLOCK_VALID) {
    1294             :                                 long repeated;
    1295             :                                 zend_leak_info leak;
    1296             : 
    1297             :                                 ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK);
    1298             : 
    1299             :                                 leak.addr = ZEND_MM_DATA_OF(p);
    1300             :                                 leak.size = p->debug.size;
    1301             :                                 leak.filename = p->debug.filename;
    1302             :                                 leak.lineno = p->debug.lineno;
    1303             :                                 leak.orig_filename = p->debug.orig_filename;
    1304             :                                 leak.orig_lineno = p->debug.orig_lineno;
    1305             : 
    1306             :                                 zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
    1307             :                                 zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC);
    1308             :                                 repeated = zend_mm_find_leaks(segment, p);
    1309             :                                 total += 1 + repeated;
    1310             :                                 if (repeated) {
    1311             :                                         zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC);
    1312             :                                 }
    1313             : #if ZEND_MM_CACHE
    1314             :                         } else if (p->magic == MEM_BLOCK_CACHED) {
    1315             :                                 /* skip it */
    1316             : #endif
    1317             :                         } else if (p->magic != MEM_BLOCK_LEAK) {
    1318             :                                 zend_mm_panic("zend_mm_heap corrupted");
    1319             :                         }
    1320             :                 }
    1321             :                 if (ZEND_MM_IS_GUARD_BLOCK(q)) {
    1322             :                         segment = segment->next_segment;
    1323             :                         if (!segment) {
    1324             :                                 break;
    1325             :                         }
    1326             :                         q = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1327             :                 }
    1328             :                 p = q;
    1329             :         }
    1330             :         if (total) {
    1331             :                 zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC);
    1332             :         }
    1333             : }
    1334             : 
    1335             : static int zend_mm_check_ptr(zend_mm_heap *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    1336             : {
    1337             :         zend_mm_block *p;
    1338             :         int no_cache_notice = 0;
    1339             :         int had_problems = 0;
    1340             :         int valid_beginning = 1;
    1341             : 
    1342             :         if (silent==2) {
    1343             :                 silent = 1;
    1344             :                 no_cache_notice = 1;
    1345             :         } else if (silent==3) {
    1346             :                 silent = 0;
    1347             :                 no_cache_notice = 1;
    1348             :         }
    1349             :         if (!silent) {
    1350             :                 TSRMLS_FETCH();
    1351             :                 
    1352             :                 zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC);
    1353             :                 zend_debug_alloc_output("---------------------------------------\n");
    1354             :                 zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr);
    1355             :                 if (__zend_orig_filename) {
    1356             :                         zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC);
    1357             :                 }
    1358             :                 if (!ptr) {
    1359             :                         zend_debug_alloc_output("NULL\n");
    1360             :                         zend_debug_alloc_output("---------------------------------------\n");
    1361             :                         return 0;
    1362             :                 }
    1363             :         }
    1364             : 
    1365             :         if (!ptr) {
    1366             :                 if (silent) {
    1367             :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1368             :                 }
    1369             :         }
    1370             : 
    1371             :         p = ZEND_MM_HEADER_OF(ptr);
    1372             : 
    1373             : #ifdef ZTS
    1374             :         if (ZEND_MM_BAD_THREAD_ID(p)) {
    1375             :                 if (!silent) {
    1376             :                         zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id());
    1377             :                         had_problems = 1;
    1378             :                 } else {
    1379             :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1380             :                 }
    1381             :         }
    1382             : #endif
    1383             : 
    1384             :         if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) {
    1385             :                 if (!silent) {
    1386             :                         zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev);
    1387             :                         had_problems = 1;
    1388             :                 } else {
    1389             :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1390             :                 }
    1391             :         }
    1392             :         if (p->info._prev != ZEND_MM_GUARD_BLOCK &&
    1393             :             ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) {
    1394             :                 if (!silent) {
    1395             :                         zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size);
    1396             :                         had_problems = 1;
    1397             :                 } else {
    1398             :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1399             :                 }
    1400             :         }
    1401             : 
    1402             :         if (had_problems) {
    1403             :                 zend_debug_alloc_output("---------------------------------------\n");
    1404             :                 return 0;
    1405             :         }
    1406             : 
    1407             :         if (!silent) {
    1408             :                 zend_debug_alloc_output("%10s\t","Beginning:  ");
    1409             :         }
    1410             : 
    1411             :         if (!ZEND_MM_IS_USED_BLOCK(p)) {
    1412             :                 if (!silent) {
    1413             :                         if (p->magic != MEM_BLOCK_FREED) {
    1414             :                                 zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
    1415             :                         } else {
    1416             :                                 zend_debug_alloc_output("Freed\n");
    1417             :                         }
    1418             :                         had_problems = 1;
    1419             :                 } else {
    1420             :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1421             :                 }
    1422             :         } else if (ZEND_MM_IS_GUARD_BLOCK(p)) {
    1423             :                 if (!silent) {
    1424             :                         if (p->magic != MEM_BLOCK_FREED) {
    1425             :                                 zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED);
    1426             :                         } else {
    1427             :                                 zend_debug_alloc_output("Guard\n");
    1428             :                         }
    1429             :                         had_problems = 1;
    1430             :                 } else {
    1431             :                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1432             :                 }
    1433             :         } else {
    1434             :                 switch (p->magic) {
    1435             :                         case MEM_BLOCK_VALID:
    1436             :                         case MEM_BLOCK_LEAK:
    1437             :                                 if (!silent) {
    1438             :                                         zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size);
    1439             :                                 }
    1440             :                                 break; /* ok */
    1441             :                         case MEM_BLOCK_CACHED:
    1442             :                                 if (!no_cache_notice) {
    1443             :                                         if (!silent) {
    1444             :                                                 zend_debug_alloc_output("Cached\n");
    1445             :                                                 had_problems = 1;
    1446             :                                         } else {
    1447             :                                                 return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1448             :                                         }
    1449             :                                 }
    1450             :                         case MEM_BLOCK_FREED:
    1451             :                                 if (!silent) {
    1452             :                                         zend_debug_alloc_output("Freed (invalid)\n");
    1453             :                                         had_problems = 1;
    1454             :                                 } else {
    1455             :                                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1456             :                                 }
    1457             :                                 break;
    1458             :                         case MEM_BLOCK_GUARD:
    1459             :                                 if (!silent) {
    1460             :                                         zend_debug_alloc_output("Guard (invalid)\n");
    1461             :                                         had_problems = 1;
    1462             :                                 } else {
    1463             :                                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1464             :                                 }
    1465             :                                 break;
    1466             :                         default:
    1467             :                                 if (!silent) {
    1468             :                                         zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID);
    1469             :                                         had_problems = 1;
    1470             :                                         valid_beginning = 0;
    1471             :                                 } else {
    1472             :                                         return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1473             :                                 }
    1474             :                                 break;
    1475             :                 }
    1476             :         }
    1477             : 
    1478             : #if ZEND_MM_HEAP_PROTECTION
    1479             :         if (!valid_beginning) {
    1480             :                 if (!silent) {
    1481             :                         zend_debug_alloc_output("%10s\t", "Start:");
    1482             :                         zend_debug_alloc_output("Unknown\n");
    1483             :                         zend_debug_alloc_output("%10s\t", "End:");
    1484             :                         zend_debug_alloc_output("Unknown\n");
    1485             :                 }
    1486             :         } else {
    1487             :                 char *end_magic = ZEND_MM_END_MAGIC_PTR(p);
    1488             : 
    1489             :                 if (p->debug.start_magic == _mem_block_start_magic) {
    1490             :                         if (!silent) {
    1491             :                                 zend_debug_alloc_output("%10s\t", "Start:");
    1492             :                                 zend_debug_alloc_output("OK\n");
    1493             :                         }
    1494             :                 } else {
    1495             :                         char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic;
    1496             :                         int overflows=0;
    1497             :                         int i;
    1498             : 
    1499             :                         if (silent) {
    1500             :                                 return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1501             :                         }
    1502             :                         had_problems = 1;
    1503             :                         overflow_ptr = (char *) &p->debug.start_magic;
    1504             :                         i = END_MAGIC_SIZE;
    1505             :                         while (--i >= 0) {
    1506             :                                 if (overflow_ptr[i]!=magic_ptr[i]) {
    1507             :                                         overflows++;
    1508             :                                 }
    1509             :                         }
    1510             :                         zend_debug_alloc_output("%10s\t", "Start:");
    1511             :                         zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic);
    1512             :                         zend_debug_alloc_output("%10s\t","");
    1513             :                         if (overflows >= END_MAGIC_SIZE) {
    1514             :                                 zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
    1515             :                         } else {
    1516             :                                 zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
    1517             :                         }
    1518             :                 }
    1519             :                 if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) {
    1520             :                         if (!silent) {
    1521             :                                 zend_debug_alloc_output("%10s\t", "End:");
    1522             :                                 zend_debug_alloc_output("OK\n");
    1523             :                         }
    1524             :                 } else {
    1525             :                         char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic;
    1526             :                         int overflows=0;
    1527             :                         int i;
    1528             : 
    1529             :                         if (silent) {
    1530             :                                 return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    1531             :                         }
    1532             :                         had_problems = 1;
    1533             :                         overflow_ptr = (char *) end_magic;
    1534             : 
    1535             :                         for (i=0; i < END_MAGIC_SIZE; i++) {
    1536             :                                 if (overflow_ptr[i]!=magic_ptr[i]) {
    1537             :                                         overflows++;
    1538             :                                 }
    1539             :                         }
    1540             : 
    1541             :                         zend_debug_alloc_output("%10s\t", "End:");
    1542             :                         zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic);
    1543             :                         zend_debug_alloc_output("%10s\t","");
    1544             :                         if (overflows >= END_MAGIC_SIZE) {
    1545             :                                 zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE);
    1546             :                         } else {
    1547             :                                 zend_debug_alloc_output("%d byte(s) overflown\n", overflows);
    1548             :                         }
    1549             :                 }
    1550             :         }
    1551             : #endif
    1552             : 
    1553             :         if (!silent) {
    1554             :                 zend_debug_alloc_output("---------------------------------------\n");
    1555             :         }
    1556             :         return ((!had_problems) ? 1 : 0);
    1557             : }
    1558             : 
    1559             : static int zend_mm_check_heap(zend_mm_heap *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    1560             : {
    1561             :         zend_mm_segment *segment = heap->segments_list;
    1562             :         zend_mm_block *p, *q;
    1563             :         int errors = 0;
    1564             : 
    1565             :         if (!segment) {
    1566             :                 return 0;
    1567             :         }
    1568             :         p = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1569             :         while (1) {
    1570             :                 q = ZEND_MM_NEXT_BLOCK(p);
    1571             :                 if (q <= p ||
    1572             :                     (char*)q > (char*)segment + segment->size ||
    1573             :                     p->info._size != q->info._prev) {
    1574             :                         zend_mm_panic("zend_mm_heap corrupted");
    1575             :                 }
    1576             :                 if (!ZEND_MM_IS_FREE_BLOCK(p)) {
    1577             :                         if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) {
    1578             :                                 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)) {
    1579             :                                         errors++;
    1580             :                                 }
    1581             : #if ZEND_MM_CACHE
    1582             :                         } else if (p->magic == MEM_BLOCK_CACHED) {
    1583             :                                 /* skip it */
    1584             : #endif
    1585             :                         } else if (p->magic != MEM_BLOCK_LEAK) {
    1586             :                                 zend_mm_panic("zend_mm_heap corrupted");
    1587             :                         }
    1588             :                 }
    1589             :                 if (ZEND_MM_IS_GUARD_BLOCK(q)) {
    1590             :                         segment = segment->next_segment;
    1591             :                         if (!segment) {
    1592             :                                 return errors;
    1593             :                         }
    1594             :                         q = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1595             :                 }
    1596             :                 p = q;
    1597             :         }
    1598             : }
    1599             : #endif
    1600             : 
    1601       63796 : ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC)
    1602             : {
    1603             :         zend_mm_storage *storage;
    1604             :         zend_mm_segment *segment;
    1605             :         zend_mm_segment *prev;
    1606             :         int internal;
    1607             : 
    1608       63796 :         if (!heap->use_zend_alloc) {
    1609       63772 :                 if (full_shutdown) {
    1610       21282 :                         free(heap);
    1611             :                 }
    1612       63772 :                 return;
    1613             :         }
    1614             : 
    1615          24 :         if (heap->reserve) {
    1616             : #if ZEND_DEBUG
    1617             :                 if (!silent) {
    1618             :                         _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1619             :                 }
    1620             : #endif
    1621          24 :                 heap->reserve = NULL;
    1622             :         }
    1623             : 
    1624             : #if ZEND_MM_CACHE_STAT
    1625             :         if (full_shutdown) {
    1626             :                 FILE *f;
    1627             : 
    1628             :                 f = fopen("zend_mm.log", "w");
    1629             :                 if (f) {
    1630             :                         int i,j;
    1631             :                         size_t size, true_size, min_size, max_size;
    1632             :                         int hit = 0, miss = 0;
    1633             : 
    1634             :                         fprintf(f, "\nidx min_size max_size true_size  max_len     hits   misses\n");
    1635             :                         size = 0;
    1636             :                         while (1) {
    1637             :                                 true_size = ZEND_MM_TRUE_SIZE(size);
    1638             :                                 if (ZEND_MM_SMALL_SIZE(true_size)) {
    1639             :                                         min_size = size;
    1640             :                                         i = ZEND_MM_BUCKET_INDEX(true_size);
    1641             :                                         size++;
    1642             :                                         while (1) {
    1643             :                                                 true_size = ZEND_MM_TRUE_SIZE(size);
    1644             :                                                 if (ZEND_MM_SMALL_SIZE(true_size)) {
    1645             :                                                         j = ZEND_MM_BUCKET_INDEX(true_size);
    1646             :                                                         if (j > i) {
    1647             :                                                                 max_size = size-1;
    1648             :                                                                 break;
    1649             :                                                         }
    1650             :                                                 } else {
    1651             :                                                         max_size = size-1;
    1652             :                                                         break;
    1653             :                                                 }
    1654             :                                                 size++;
    1655             :                                         }
    1656             :                                         hit += heap->cache_stat[i].hit;
    1657             :                                         miss += heap->cache_stat[i].miss;
    1658             :                                         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);
    1659             :                                 } else {
    1660             :                                         break;
    1661             :                                 }
    1662             :                         }
    1663             :                         fprintf(f, "                                        %8d %8d\n", hit, miss);
    1664             :                         fprintf(f, "                                        %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss);
    1665             :                         fclose(f);
    1666             :                 }
    1667             :         }
    1668             : #endif
    1669             : 
    1670             : #if ZEND_DEBUG
    1671             :         if (!silent) {
    1672             :                 zend_mm_check_leaks(heap TSRMLS_CC);
    1673             :         }
    1674             : #endif
    1675             : 
    1676          24 :         internal = heap->internal;
    1677          24 :         storage = heap->storage;
    1678          24 :         segment = heap->segments_list;
    1679          24 :         if (full_shutdown) {
    1680          24 :                 while (segment) {
    1681           8 :                         prev = segment;
    1682           8 :                         segment = segment->next_segment;
    1683           8 :                         ZEND_MM_STORAGE_FREE(prev);
    1684             :                 }
    1685           8 :                 heap->segments_list = NULL;
    1686           8 :                 storage->handlers->dtor(storage);
    1687           8 :                 if (!internal) {
    1688           8 :                         free(heap);
    1689             :                 }
    1690             :         } else {
    1691          16 :                 if (segment) {
    1692             : #ifndef ZEND_WIN32
    1693          16 :                         if (heap->reserve_size) {
    1694          57 :                                 while (segment->next_segment) {
    1695          25 :                                         prev = segment;
    1696          25 :                                         segment = segment->next_segment;
    1697          25 :                                         ZEND_MM_STORAGE_FREE(prev);
    1698             :                                 }
    1699          16 :                                 heap->segments_list = segment;
    1700             :                         } else {
    1701             : #endif
    1702             :                                 do {
    1703           0 :                                         prev = segment;
    1704           0 :                                         segment = segment->next_segment;
    1705           0 :                                         ZEND_MM_STORAGE_FREE(prev);
    1706           0 :                                 } while (segment);
    1707           0 :                                 heap->segments_list = NULL;
    1708             : #ifndef ZEND_WIN32
    1709             :                         }
    1710             : #endif
    1711             :                 }
    1712          32 :                 if (heap->compact_size &&
    1713          16 :                     heap->real_peak > heap->compact_size) {
    1714           1 :                         storage->handlers->compact(storage);
    1715             :                 }
    1716          16 :                 zend_mm_init(heap);
    1717          16 :                 if (heap->segments_list) {
    1718          16 :                         heap->real_size = heap->segments_list->size;
    1719          16 :                         heap->real_peak = heap->segments_list->size;
    1720             :                 } else {
    1721           0 :                         heap->real_size = 0;
    1722           0 :                         heap->real_peak = 0;
    1723             :                 }
    1724          16 :                 heap->size = 0;
    1725          16 :                 heap->peak = 0;
    1726          16 :                 if (heap->segments_list) {
    1727             :                         /* mark segment as a free block */
    1728          16 :                         zend_mm_free_block *b = (zend_mm_free_block*)((char*)heap->segments_list + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    1729          16 :                         size_t block_size = heap->segments_list->size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
    1730             : 
    1731          16 :                         ZEND_MM_MARK_FIRST_BLOCK(b);
    1732          16 :                         ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(b, block_size));
    1733          16 :                         ZEND_MM_BLOCK(b, ZEND_MM_FREE_BLOCK, block_size);
    1734          16 :                         zend_mm_add_to_free_list(heap, b);
    1735             :                 }
    1736          16 :                 if (heap->reserve_size) {
    1737          16 :                         heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size  ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1738             :                 }
    1739          16 :                 heap->overflow = 0;
    1740             :         }
    1741             : }
    1742             : 
    1743           0 : static void zend_mm_safe_error(zend_mm_heap *heap,
    1744             :         const char *format,
    1745             :         size_t limit,
    1746             : #if ZEND_DEBUG
    1747             :         const char *filename,
    1748             :         uint lineno,
    1749             : #endif
    1750             :         size_t size)
    1751             : {
    1752           0 :         if (heap->reserve) {
    1753           0 :                 _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
    1754           0 :                 heap->reserve = NULL;
    1755             :         }
    1756           0 :         if (heap->overflow == 0) {
    1757             :                 const char *error_filename;
    1758             :                 uint error_lineno;
    1759             :                 TSRMLS_FETCH();
    1760           0 :                 if (zend_is_compiling(TSRMLS_C)) {
    1761           0 :                         error_filename = zend_get_compiled_filename(TSRMLS_C);
    1762           0 :                         error_lineno = zend_get_compiled_lineno(TSRMLS_C);
    1763           0 :                 } else if (EG(in_execution)) {
    1764           0 :                         error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL;
    1765           0 :                         error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0;
    1766             :                 } else {
    1767           0 :                         error_filename = NULL;
    1768           0 :                         error_lineno = 0;
    1769             :                 }
    1770           0 :                 if (!error_filename) {
    1771           0 :                         error_filename = "Unknown";
    1772             :                 }
    1773           0 :                 heap->overflow = 1;
    1774           0 :                 zend_try {
    1775           0 :                         zend_error_noreturn(E_ERROR,
    1776             :                                 format,
    1777             :                                 limit,
    1778             : #if ZEND_DEBUG
    1779             :                                 filename,
    1780             :                                 lineno,
    1781             : #endif
    1782             :                                 size);
    1783           0 :                 } zend_catch {
    1784           0 :                         if (heap->overflow == 2) {
    1785           0 :                                 fprintf(stderr, "\nFatal error: ");
    1786           0 :                                 fprintf(stderr,
    1787             :                                         format,
    1788             :                                         limit,
    1789             : #if ZEND_DEBUG
    1790             :                                         filename,
    1791             :                                         lineno,
    1792             : #endif
    1793             :                                         size);
    1794           0 :                                 fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno);
    1795             :                         }
    1796             : /* See http://support.microsoft.com/kb/190351 */
    1797             : #ifdef PHP_WIN32
    1798             :                         fflush(stderr);
    1799             : #endif
    1800           0 :                 } zend_end_try();
    1801             :         } else {
    1802           0 :                 heap->overflow = 2;
    1803             :         }
    1804           0 :         zend_bailout();
    1805           0 : }
    1806             : 
    1807     3814198 : static zend_mm_free_block *zend_mm_search_large_block(zend_mm_heap *heap, size_t true_size)
    1808             : {
    1809             :         zend_mm_free_block *best_fit;
    1810     3814198 :         size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size);
    1811     3814198 :         size_t bitmap = heap->large_free_bitmap >> index;
    1812             :         zend_mm_free_block *p;
    1813             : 
    1814     3814198 :         if (bitmap == 0) {
    1815       14148 :                 return NULL;
    1816             :         }
    1817             : 
    1818     3800050 :         if (UNEXPECTED((bitmap & 1) != 0)) {
    1819             :                 /* Search for best "large" free block */
    1820      750892 :                 zend_mm_free_block *rst = NULL;
    1821             :                 size_t m;
    1822      750892 :                 size_t best_size = -1;
    1823             : 
    1824      750892 :                 best_fit = NULL;
    1825      750892 :                 p = heap->large_free_buckets[index];
    1826      923560 :                 for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) {
    1827      923560 :                         if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
    1828      464043 :                                 return p->next_free_block;
    1829      729601 :                         } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size &&
    1830      270084 :                                    ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
    1831      253026 :                                 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
    1832      253026 :                                 best_fit = p;
    1833             :                         }
    1834      459517 :                         if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) {
    1835      320608 :                                 if (p->child[1]) {
    1836       63105 :                                         rst = p->child[1];
    1837             :                                 }
    1838      320608 :                                 if (p->child[0]) {
    1839      123301 :                                         p = p->child[0];
    1840             :                                 } else {
    1841      197307 :                                         break;
    1842             :                                 }
    1843      138909 :                         } else if (p->child[1]) {
    1844       49367 :                                 p = p->child[1];
    1845             :                         } else {
    1846       89542 :                                 break;
    1847             :                         }
    1848      172668 :                 }
    1849             : 
    1850      337496 :                 for (p = rst; p; p = p->child[p->child[0] != NULL]) {
    1851       50647 :                         if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
    1852           0 :                                 return p->next_free_block;
    1853      101294 :                         } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
    1854       50647 :                                    ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
    1855       14934 :                                 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
    1856       14934 :                                 best_fit = p;
    1857             :                         }
    1858             :                 }
    1859             : 
    1860      286849 :                 if (best_fit) {
    1861      188705 :                         return best_fit->next_free_block;
    1862             :                 }
    1863       98144 :                 bitmap = bitmap >> 1;
    1864       98144 :                 if (!bitmap) {
    1865         384 :                         return NULL;
    1866             :                 }
    1867       97760 :                 index++;
    1868             :         }
    1869             : 
    1870             :         /* Search for smallest "large" free block */
    1871     3146918 :         best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)];
    1872     6393844 :         while ((p = p->child[p->child[0] != NULL])) {
    1873      100008 :                 if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) {
    1874       27598 :                         best_fit = p;
    1875             :                 }
    1876             :         }
    1877     3146918 :         return best_fit->next_free_block;
    1878             : }
    1879             : 
    1880    59886197 : static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    1881             : {
    1882             :         zend_mm_free_block *best_fit;
    1883    59886197 :         size_t true_size = ZEND_MM_TRUE_SIZE(size);
    1884             :         size_t block_size;
    1885             :         size_t remaining_size;
    1886             :         size_t segment_size;
    1887             :         zend_mm_segment *segment;
    1888    59886197 :         int keep_rest = 0;
    1889             : #ifdef ZEND_SIGNALS
    1890             :         TSRMLS_FETCH();
    1891             : #endif
    1892             : 
    1893    59886197 :         HANDLE_BLOCK_INTERRUPTIONS();
    1894             : 
    1895    59886197 :         if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
    1896    58654505 :                 size_t index = ZEND_MM_BUCKET_INDEX(true_size);
    1897             :                 size_t bitmap;
    1898             : 
    1899    58654505 :                 if (UNEXPECTED(true_size < size)) {
    1900           0 :                         goto out_of_memory;
    1901             :                 }
    1902             : #if ZEND_MM_CACHE
    1903    58654505 :                 if (EXPECTED(heap->cache[index] != NULL)) {
    1904             :                         /* Get block from cache */
    1905             : #if ZEND_MM_CACHE_STAT
    1906             :                         heap->cache_stat[index].count--;
    1907             :                         heap->cache_stat[index].hit++;
    1908             : #endif
    1909    23970955 :                         best_fit = heap->cache[index];
    1910    23970955 :                         heap->cache[index] = best_fit->prev_free_block;
    1911    23970955 :                         heap->cached -= true_size;
    1912             :                         ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
    1913             :                         ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
    1914    23970955 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1915    23970955 :                         return ZEND_MM_DATA_OF(best_fit);
    1916             :                 }
    1917             : #if ZEND_MM_CACHE_STAT
    1918             :                 heap->cache_stat[index].miss++;
    1919             : #endif
    1920             : #endif
    1921             : 
    1922    34683550 :                 bitmap = heap->free_bitmap >> index;
    1923    34683550 :                 if (bitmap) {
    1924             :                         /* Found some "small" free block that can be used */
    1925    32101044 :                         index += zend_mm_low_bit(bitmap);
    1926    32101044 :                         best_fit = heap->free_buckets[index*2];
    1927             : #if ZEND_MM_CACHE_STAT
    1928             :                         heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++;
    1929             : #endif
    1930    32101044 :                         goto zend_mm_finished_searching_for_block;
    1931             :                 }
    1932             :         }
    1933             : 
    1934             : #if ZEND_MM_CACHE_STAT
    1935             :         heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++;
    1936             : #endif
    1937             : 
    1938     3814198 :         best_fit = zend_mm_search_large_block(heap, true_size);
    1939             : 
    1940     3814198 :         if (!best_fit && heap->real_size >= heap->limit - heap->block_size) {
    1941           0 :                 zend_mm_free_block *p = heap->rest_buckets[0];
    1942           0 :                 size_t best_size = -1;
    1943             : 
    1944           0 :                 while (p != ZEND_MM_REST_BUCKET(heap)) {
    1945           0 :                         if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) {
    1946           0 :                                 best_fit = p;
    1947           0 :                                 goto zend_mm_finished_searching_for_block;
    1948           0 :                         } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size &&
    1949           0 :                                    ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) {
    1950           0 :                                 best_size = ZEND_MM_FREE_BLOCK_SIZE(p);
    1951           0 :                                 best_fit = p;
    1952             :                         }
    1953           0 :                         p = p->prev_free_block;
    1954             :                 }
    1955             :         }
    1956             : 
    1957     3814198 :         if (!best_fit) {
    1958       14532 :                 if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
    1959             :                         /* Make sure we add a memory block which is big enough,
    1960             :                            segment must have header "size" and trailer "guard" block */
    1961           4 :                         segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
    1962           4 :                         segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
    1963           4 :                         keep_rest = 1;
    1964             :                 } else {
    1965       14528 :                         segment_size = heap->block_size;
    1966             :                 }
    1967             : 
    1968       29064 :                 if (segment_size < true_size ||
    1969       14532 :                     heap->real_size + segment_size > heap->limit) {
    1970             :                         /* Memory limit overflow */
    1971             : #if ZEND_MM_CACHE
    1972           0 :                         zend_mm_free_cache(heap);
    1973             : #endif
    1974           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1975             : #if ZEND_DEBUG
    1976             :                         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);
    1977             : #else
    1978           0 :                         zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size);
    1979             : #endif
    1980             :                 }
    1981             : 
    1982       14532 :                 segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size);
    1983             : 
    1984       14532 :                 if (!segment) {
    1985             :                         /* Storage manager cannot allocate memory */
    1986             : #if ZEND_MM_CACHE
    1987           0 :                         zend_mm_free_cache(heap);
    1988             : #endif
    1989             : out_of_memory:
    1990           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1991             : #if ZEND_DEBUG
    1992             :                         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);
    1993             : #else
    1994           0 :                         zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size);
    1995             : #endif
    1996           0 :                         return NULL;
    1997             :                 }
    1998             : 
    1999       14532 :                 heap->real_size += segment_size;
    2000       14532 :                 if (heap->real_size > heap->real_peak) {
    2001          39 :                         heap->real_peak = heap->real_size;
    2002             :                 }
    2003             : 
    2004       14532 :                 segment->size = segment_size;
    2005       14532 :                 segment->next_segment = heap->segments_list;
    2006       14532 :                 heap->segments_list = segment;
    2007             : 
    2008       14532 :                 best_fit = (zend_mm_free_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    2009       14532 :                 ZEND_MM_MARK_FIRST_BLOCK(best_fit);
    2010             : 
    2011       14532 :                 block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
    2012             : 
    2013       14532 :                 ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size));
    2014             : 
    2015             :         } else {
    2016             : zend_mm_finished_searching_for_block:
    2017             :                 /* remove from free list */
    2018             :                 ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED);
    2019             :                 ZEND_MM_CHECK_COOKIE(best_fit);
    2020    35900710 :                 ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit);
    2021    35900710 :                 zend_mm_remove_from_free_list(heap, best_fit);
    2022             : 
    2023    35900710 :                 block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit);
    2024             :         }
    2025             : 
    2026    35915242 :         remaining_size = block_size - true_size;
    2027             : 
    2028    35915242 :         if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2029    23396914 :                 true_size = block_size;
    2030    23396914 :                 ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
    2031             :         } else {
    2032             :                 zend_mm_free_block *new_free_block;
    2033             : 
    2034             :                 /* prepare new free block */
    2035    12518328 :                 ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size);
    2036    12518328 :                 new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(best_fit, true_size);
    2037    12518328 :                 ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2038             : 
    2039             :                 /* add the new free block to the free list */
    2040    12518328 :                 if (EXPECTED(!keep_rest)) {
    2041    12518324 :                         zend_mm_add_to_free_list(heap, new_free_block);
    2042             :                 } else {
    2043           4 :                         zend_mm_add_to_rest_list(heap, new_free_block);
    2044             :                 }
    2045             :         }
    2046             : 
    2047             :         ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);
    2048             : 
    2049    35915242 :         heap->size += true_size;
    2050    35915242 :         if (heap->peak < heap->size) {
    2051       59595 :                 heap->peak = heap->size;
    2052             :         }
    2053             : 
    2054    35915242 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2055             : 
    2056    35915242 :         return ZEND_MM_DATA_OF(best_fit);
    2057             : }
    2058             : 
    2059             : 
    2060    59886157 : static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2061             : {
    2062             :         zend_mm_block *mm_block;
    2063             :         zend_mm_block *next_block;
    2064             :         size_t size;
    2065             : #ifdef ZEND_SIGNALS
    2066             :         TSRMLS_FETCH();
    2067             : #endif
    2068    59886157 :         if (!ZEND_MM_VALID_PTR(p)) {
    2069           0 :                 return;
    2070             :         }
    2071             : 
    2072    59886157 :         HANDLE_BLOCK_INTERRUPTIONS();
    2073             : 
    2074    59886157 :         mm_block = ZEND_MM_HEADER_OF(p);
    2075    59886157 :         size = ZEND_MM_BLOCK_SIZE(mm_block);
    2076             :         ZEND_MM_CHECK_PROTECTION(mm_block);
    2077             : 
    2078             : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2079             :         memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size);
    2080             : #endif
    2081             : 
    2082             : #if ZEND_MM_CACHE
    2083    59886157 :         if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) {
    2084    23977005 :                 size_t index = ZEND_MM_BUCKET_INDEX(size);
    2085    23977005 :                 zend_mm_free_block **cache = &heap->cache[index];
    2086             : 
    2087    23977005 :                 ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
    2088    23977005 :                 *cache = (zend_mm_free_block*)mm_block;
    2089    23977005 :                 heap->cached += size;
    2090             :                 ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
    2091             : #if ZEND_MM_CACHE_STAT
    2092             :                 if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
    2093             :                         heap->cache_stat[index].max_count = heap->cache_stat[index].count;
    2094             :                 }
    2095             : #endif
    2096    23977005 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2097    23977005 :                 return;
    2098             :         }
    2099             : #endif
    2100             : 
    2101    35909152 :         heap->size -= size;
    2102             : 
    2103    35909152 :         next_block = ZEND_MM_BLOCK_AT(mm_block, size);
    2104    35909152 :         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2105     8208089 :                 zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2106     8208089 :                 size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
    2107             :         }
    2108    35909152 :         if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) {
    2109     4281956 :                 mm_block = ZEND_MM_PREV_BLOCK(mm_block);
    2110     4281956 :                 zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) mm_block);
    2111     4281956 :                 size += ZEND_MM_FREE_BLOCK_SIZE(mm_block);
    2112             :         }
    2113    35964423 :         if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
    2114       40772 :             ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) {
    2115       14499 :                 zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE));
    2116             :         } else {
    2117    35894653 :                 ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size);
    2118    35894653 :                 zend_mm_add_to_free_list(heap, (zend_mm_free_block *) mm_block);
    2119             :         }
    2120    35909152 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2121             : }
    2122             : 
    2123    10548738 : static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2124             : {
    2125    10548738 :         zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p);
    2126             :         zend_mm_block *next_block;
    2127             :         size_t true_size;
    2128             :         size_t orig_size;
    2129             :         void *ptr;
    2130             : #ifdef ZEND_SIGNALS
    2131             :         TSRMLS_FETCH();
    2132             : #endif
    2133    10548738 :         if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) {
    2134     4653225 :                 return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2135             :         }
    2136             : 
    2137     5895513 :         HANDLE_BLOCK_INTERRUPTIONS();
    2138             : 
    2139     5895513 :         mm_block = ZEND_MM_HEADER_OF(p);
    2140     5895513 :         true_size = ZEND_MM_TRUE_SIZE(size);
    2141     5895513 :         orig_size = ZEND_MM_BLOCK_SIZE(mm_block);
    2142             :         ZEND_MM_CHECK_PROTECTION(mm_block);
    2143             : 
    2144     5895513 :         if (UNEXPECTED(true_size < size)) {
    2145           0 :                 goto out_of_memory;
    2146             :         }
    2147             : 
    2148     5895513 :         if (true_size <= orig_size) {
    2149     2438261 :                 size_t remaining_size = orig_size - true_size;
    2150             : 
    2151     2438261 :                 if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2152             :                         zend_mm_free_block *new_free_block;
    2153             : 
    2154       41435 :                         next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
    2155       41435 :                         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2156        9662 :                                 remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block);
    2157        9662 :                                 zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2158             :                         }
    2159             : 
    2160             :                         /* prepare new free block */
    2161       41435 :                         ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2162       41435 :                         new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
    2163             : 
    2164       41435 :                         ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2165             : 
    2166             :                         /* add the new free block to the free list */
    2167       41435 :                         zend_mm_add_to_free_list(heap, new_free_block);
    2168       41435 :                         heap->size += (true_size - orig_size);
    2169             :                 }
    2170             :                 ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
    2171     2438261 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2172     2438261 :                 return p;
    2173             :         }
    2174             : 
    2175             : #if ZEND_MM_CACHE
    2176     3457252 :         if (ZEND_MM_SMALL_SIZE(true_size)) {
    2177     2266659 :                 size_t index = ZEND_MM_BUCKET_INDEX(true_size);
    2178             :                 
    2179     2266659 :                 if (heap->cache[index] != NULL) {
    2180             :                         zend_mm_free_block *best_fit;
    2181             :                         zend_mm_free_block **cache;
    2182             : 
    2183             : #if ZEND_MM_CACHE_STAT
    2184             :                         heap->cache_stat[index].count--;
    2185             :                         heap->cache_stat[index].hit++;
    2186             : #endif
    2187     1164140 :                         best_fit = heap->cache[index];
    2188     1164140 :                         heap->cache[index] = best_fit->prev_free_block;
    2189             :                         ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED);
    2190             :                         ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0);
    2191             :         
    2192     1164140 :                         ptr = ZEND_MM_DATA_OF(best_fit);
    2193             : 
    2194             : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2195             :                         memcpy(ptr, p, mm_block->debug.size);
    2196             : #else
    2197     1164140 :                         memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
    2198             : #endif
    2199             : 
    2200     1164140 :                         heap->cached -= true_size - orig_size;
    2201             : 
    2202     1164140 :                         index = ZEND_MM_BUCKET_INDEX(orig_size);
    2203     1164140 :                         cache = &heap->cache[index];
    2204             : 
    2205     1164140 :                         ((zend_mm_free_block*)mm_block)->prev_free_block = *cache;
    2206     1164140 :                         *cache = (zend_mm_free_block*)mm_block;
    2207             :                         ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED);
    2208             : #if ZEND_MM_CACHE_STAT
    2209             :                         if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) {
    2210             :                                 heap->cache_stat[index].max_count = heap->cache_stat[index].count;
    2211             :                         }
    2212             : #endif
    2213             : 
    2214     1164140 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2215     1164140 :                         return ptr;
    2216             :                 }
    2217             :         }
    2218             : #endif
    2219             : 
    2220     2293112 :         next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size);
    2221             : 
    2222     2293112 :         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2223             :                 ZEND_MM_CHECK_COOKIE(next_block);
    2224     1368970 :                 ZEND_MM_CHECK_BLOCK_LINKAGE(next_block);
    2225     1368970 :                 if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) {
    2226     1335958 :                         size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block);
    2227     1335958 :                         size_t remaining_size = block_size - true_size;
    2228             : 
    2229     1335958 :                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2230             : 
    2231     1335958 :                         if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2232       50252 :                                 true_size = block_size;
    2233       50252 :                                 ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2234             :                         } else {
    2235             :                                 zend_mm_free_block *new_free_block;
    2236             : 
    2237             :                                 /* prepare new free block */
    2238     1285706 :                                 ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2239     1285706 :                                 new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
    2240     1285706 :                                 ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2241             : 
    2242             :                                 /* add the new free block to the free list */
    2243     1372054 :                                 if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
    2244       45622 :                                     ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) {
    2245       40726 :                                         zend_mm_add_to_rest_list(heap, new_free_block);
    2246             :                                 } else {
    2247     1244980 :                                         zend_mm_add_to_free_list(heap, new_free_block);
    2248             :                                 }
    2249             :                         }
    2250             :                         ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0);
    2251     1335958 :                         heap->size = heap->size + true_size - orig_size;
    2252     1335958 :                         if (heap->peak < heap->size) {
    2253        6293 :                                 heap->peak = heap->size;
    2254             :                         }
    2255     1335958 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2256     1335958 :                         return p;
    2257       33032 :                 } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) &&
    2258          20 :                                    ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) {
    2259           0 :                         zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block);
    2260           0 :                         goto realloc_segment;
    2261             :                 }
    2262      924142 :         } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) {
    2263             :                 zend_mm_segment *segment;
    2264             :                 zend_mm_segment *segment_copy;
    2265             :                 size_t segment_size;
    2266             :                 size_t block_size;
    2267             :                 size_t remaining_size;
    2268             : 
    2269             : realloc_segment:
    2270             :                 /* segment size, size of block and size of guard block */
    2271           0 :                 if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) {
    2272           0 :                         segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE;
    2273           0 :                         segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
    2274             :                 } else {
    2275           0 :                         segment_size = heap->block_size;
    2276             :                 }
    2277             : 
    2278           0 :                 segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE);
    2279           0 :                 if (segment_size < true_size ||
    2280           0 :                     heap->real_size + segment_size - segment_copy->size > heap->limit) {
    2281           0 :                         if (ZEND_MM_IS_FREE_BLOCK(next_block)) {
    2282           0 :                                 zend_mm_add_to_free_list(heap, (zend_mm_free_block *) next_block);
    2283             :                         }
    2284             : #if ZEND_MM_CACHE
    2285           0 :                         zend_mm_free_cache(heap);
    2286             : #endif
    2287           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2288             : #if ZEND_DEBUG
    2289             :                         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);
    2290             : #else
    2291           0 :                         zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size);
    2292             : #endif
    2293           0 :                         return NULL;
    2294             :                 }
    2295             : 
    2296           0 :                 segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size);
    2297           0 :                 if (!segment) {
    2298             : #if ZEND_MM_CACHE
    2299           0 :                         zend_mm_free_cache(heap);
    2300             : #endif
    2301             : out_of_memory:
    2302           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
    2303             : #if ZEND_DEBUG
    2304             :                         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);
    2305             : #else
    2306           0 :                         zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size);
    2307             : #endif
    2308           0 :                         return NULL;
    2309             :                 }
    2310           0 :                 heap->real_size += segment_size - segment->size;
    2311           0 :                 if (heap->real_size > heap->real_peak) {
    2312           0 :                         heap->real_peak = heap->real_size;
    2313             :                 }
    2314             : 
    2315           0 :                 segment->size = segment_size;
    2316             : 
    2317           0 :                 if (segment != segment_copy) {
    2318           0 :                         zend_mm_segment **seg = &heap->segments_list;
    2319           0 :                         while (*seg != segment_copy) {
    2320           0 :                                 seg = &(*seg)->next_segment;
    2321             :                         }
    2322           0 :                         *seg = segment;
    2323           0 :                         mm_block = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
    2324           0 :                         ZEND_MM_MARK_FIRST_BLOCK(mm_block);
    2325             :                 }
    2326             : 
    2327           0 :                 block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE;
    2328           0 :                 remaining_size = block_size - true_size;
    2329             : 
    2330             :                 /* setup guard block */
    2331           0 :                 ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size));
    2332             : 
    2333           0 :                 if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) {
    2334           0 :                         true_size = block_size;
    2335           0 :                         ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2336             :                 } else {
    2337             :                         zend_mm_free_block *new_free_block;
    2338             : 
    2339             :                         /* prepare new free block */
    2340           0 :                         ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size);
    2341           0 :                         new_free_block = (zend_mm_free_block *) ZEND_MM_BLOCK_AT(mm_block, true_size);
    2342           0 :                         ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
    2343             : 
    2344             :                         /* add the new free block to the free list */
    2345           0 :                         zend_mm_add_to_rest_list(heap, new_free_block);
    2346             :                 }
    2347             : 
    2348             :                 ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1);
    2349             : 
    2350           0 :                 heap->size = heap->size + true_size - orig_size;
    2351           0 :                 if (heap->peak < heap->size) {
    2352           0 :                         heap->peak = heap->size;
    2353             :                 }
    2354             : 
    2355           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2356           0 :                 return ZEND_MM_DATA_OF(mm_block);
    2357             :         }
    2358             : 
    2359      957154 :         ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2360             : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2361             :         memcpy(ptr, p, mm_block->debug.size);
    2362             : #else
    2363      957154 :         memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE);
    2364             : #endif
    2365      957154 :         _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2366      957154 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2367      957154 :         return ptr;
    2368             : }
    2369             : 
    2370           0 : ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2371             : {
    2372           0 :         return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2373             : }
    2374             : 
    2375           0 : ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2376             : {
    2377           0 :         _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2378           0 : }
    2379             : 
    2380           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)
    2381             : {
    2382           0 :         return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2383             : }
    2384             : 
    2385           0 : ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2386             : {
    2387             :         zend_mm_block *mm_block;
    2388             : 
    2389           0 :         if (!ZEND_MM_VALID_PTR(p)) {
    2390           0 :                 return 0;
    2391             :         }
    2392           0 :         mm_block = ZEND_MM_HEADER_OF(p);
    2393             :         ZEND_MM_CHECK_PROTECTION(mm_block);
    2394             : #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION
    2395             :         return mm_block->debug.size;
    2396             : #else
    2397           0 :         return ZEND_MM_BLOCK_SIZE(mm_block);
    2398             : #endif
    2399             : }
    2400             : 
    2401             : /**********************/
    2402             : /* Allocation Manager */
    2403             : /**********************/
    2404             : 
    2405             : typedef struct _zend_alloc_globals {
    2406             :         zend_mm_heap *mm_heap;
    2407             : } zend_alloc_globals;
    2408             : 
    2409             : #ifdef ZTS
    2410             : static int alloc_globals_id;
    2411             : # define AG(v) TSRMG(alloc_globals_id, zend_alloc_globals *, v)
    2412             : #else
    2413             : # define AG(v) (alloc_globals.v)
    2414             : static zend_alloc_globals alloc_globals;
    2415             : #endif
    2416             : 
    2417         138 : ZEND_API int is_zend_mm(TSRMLS_D)
    2418             : {
    2419         138 :         return AG(mm_heap)->use_zend_alloc;
    2420             : }
    2421             : 
    2422   198982611 : ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2423             : {
    2424             :         TSRMLS_FETCH();
    2425             : 
    2426   198982611 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2427   144706817 :                 return AG(mm_heap)->_malloc(size);
    2428             :         }
    2429    54275794 :         return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2430             : }
    2431             : 
    2432   207187244 : ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2433             : {
    2434             :         TSRMLS_FETCH();
    2435             : 
    2436   207187244 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2437   148258241 :                 AG(mm_heap)->_free(ptr);
    2438   148258241 :                 return;
    2439             :         }
    2440    58929003 :         _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2441             : }
    2442             : 
    2443    16062228 : ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2444             : {
    2445             :         TSRMLS_FETCH();
    2446             : 
    2447    16062228 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2448     5513490 :                 return AG(mm_heap)->_realloc(ptr, size);
    2449             :         }
    2450    10548738 :         return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2451             : }
    2452             : 
    2453           0 : ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2454             : {
    2455           0 :         if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) {
    2456           0 :                 return 0;
    2457             :         }
    2458           0 :         return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2459             : }
    2460             : 
    2461             : #if defined(__GNUC__) && (defined(__native_client__) || defined(i386))
    2462             : 
    2463             : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2464             : {
    2465             :         size_t res = nmemb;
    2466             :         unsigned long overflow = 0;
    2467             : 
    2468             :         __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1"
    2469             :              : "=&a"(res), "=&d" (overflow)
    2470             :              : "%0"(res),
    2471             :                "rm"(size),
    2472             :                "rm"(offset));
    2473             :         
    2474             :         if (UNEXPECTED(overflow)) {
    2475             :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2476             :                 return 0;
    2477             :         }
    2478             :         return res;
    2479             : }
    2480             : 
    2481             : #elif defined(__GNUC__) && defined(__x86_64__)
    2482             : 
    2483    17733966 : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2484             : {
    2485    17733966 :         size_t res = nmemb;
    2486    17733966 :         unsigned long overflow = 0;
    2487             : 
    2488             : #ifdef __ILP32__ /* x32 */
    2489             : # define LP_SUFF "l"
    2490             : #else /* amd64 */
    2491             : # define LP_SUFF "q"
    2492             : #endif
    2493             : 
    2494    17733966 :         __asm__ ("mul" LP_SUFF  " %3\n\t"
    2495             :                  "add %4,%0\n\t"
    2496             :                  "adc $0,%1"
    2497             :              : "=&a"(res), "=&d" (overflow)
    2498             :              : "%0"(res),
    2499             :                "rm"(size),
    2500             :                "rm"(offset));
    2501             : 
    2502             : #undef LP_SUFF
    2503    17733966 :         if (UNEXPECTED(overflow)) {
    2504           1 :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2505             :                 return 0;
    2506             :         }
    2507    17733965 :         return res;
    2508             : }
    2509             : 
    2510             : #elif defined(__GNUC__) && defined(__arm__)
    2511             : 
    2512             : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2513             : {
    2514             :         size_t res;
    2515             :         unsigned long overflow;
    2516             : 
    2517             :         __asm__ ("umlal %0,%1,%2,%3"
    2518             :              : "=r"(res), "=r"(overflow)
    2519             :              : "r"(nmemb),
    2520             :                "r"(size),
    2521             :                "0"(offset),
    2522             :                "1"(0));
    2523             : 
    2524             :         if (UNEXPECTED(overflow)) {
    2525             :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2526             :                 return 0;
    2527             :         }
    2528             :         return res;
    2529             : }
    2530             : 
    2531             : #elif defined(__GNUC__) && defined(__aarch64__)
    2532             : 
    2533             : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2534             : {
    2535             :         size_t res;
    2536             :         unsigned long overflow;
    2537             : 
    2538             :         __asm__ ("mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc %1,%1,xzr"
    2539             :              : "=&r"(res), "=&r"(overflow)
    2540             :              : "r"(nmemb),
    2541             :                "r"(size),
    2542             :                "r"(offset));
    2543             : 
    2544             :         if (UNEXPECTED(overflow)) {
    2545             :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2546             :                 return 0;
    2547             :         }
    2548             :         return res;
    2549             : }
    2550             : 
    2551             : #elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
    2552             : 
    2553             : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2554             : {
    2555             :         zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset;
    2556             : 
    2557             :         if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) {
    2558             :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2559             :                 return 0;
    2560             :         }
    2561             :         return (size_t) res;
    2562             : }
    2563             : 
    2564             : #else
    2565             : 
    2566             : static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
    2567             : {
    2568             :         size_t res = nmemb * size + offset;
    2569             :         double _d  = (double)nmemb * (double)size + (double)offset;
    2570             :         double _delta = (double)res - _d;
    2571             : 
    2572             :         if (UNEXPECTED((_d + _delta ) != _d)) {
    2573             :                 zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
    2574             :                 return 0;
    2575             :         }
    2576             :         return res;
    2577             : }
    2578             : #endif
    2579             : 
    2580             : 
    2581    10734698 : ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2582             : {
    2583    10734698 :         return emalloc_rel(safe_address(nmemb, size, offset));
    2584             : }
    2585             : 
    2586     6997755 : ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset)
    2587             : {
    2588     6997755 :         return pemalloc(safe_address(nmemb, size, offset), 1);
    2589             : }
    2590             : 
    2591        1513 : 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)
    2592             : {
    2593        1513 :         return erealloc_rel(ptr, safe_address(nmemb, size, offset));
    2594             : }
    2595             : 
    2596           0 : ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset)
    2597             : {
    2598           0 :         return perealloc(ptr, safe_address(nmemb, size, offset), 1);
    2599             : }
    2600             : 
    2601             : 
    2602     7343264 : ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2603             : {
    2604             :         void *p;
    2605             : #ifdef ZEND_SIGNALS
    2606             :         TSRMLS_FETCH();
    2607             : #endif
    2608     7343264 :         HANDLE_BLOCK_INTERRUPTIONS();
    2609             : 
    2610     7343264 :         p = _safe_emalloc(nmemb, size, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2611     7343264 :         if (UNEXPECTED(p == NULL)) {
    2612           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2613           0 :                 return p;
    2614             :         }
    2615     7343264 :         memset(p, 0, size * nmemb);
    2616     7343264 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2617     7343264 :         return p;
    2618             : }
    2619             : 
    2620      605992 : ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2621             : {
    2622             :         int length;
    2623             :         char *p;
    2624             : #ifdef ZEND_SIGNALS
    2625             :         TSRMLS_FETCH();
    2626             : #endif
    2627             : 
    2628      605992 :         HANDLE_BLOCK_INTERRUPTIONS();
    2629             : 
    2630      605992 :         length = strlen(s)+1;
    2631      605992 :         p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2632      605992 :         if (UNEXPECTED(p == NULL)) {
    2633           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2634           0 :                 return p;
    2635             :         }
    2636      605992 :         memcpy(p, s, length);
    2637      605992 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2638      605992 :         return p;
    2639             : }
    2640             : 
    2641    16511129 : ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2642             : {
    2643             :         char *p;
    2644             : #ifdef ZEND_SIGNALS
    2645             :         TSRMLS_FETCH();
    2646             : #endif
    2647             : 
    2648    16511129 :         HANDLE_BLOCK_INTERRUPTIONS();
    2649             : 
    2650    16511129 :         p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2651    16511129 :         if (UNEXPECTED(p == NULL)) {
    2652           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2653           0 :                 return p;
    2654             :         }
    2655    16511129 :         memcpy(p, s, length);
    2656    16511129 :         p[length] = 0;
    2657    16511129 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2658    16511129 :         return p;
    2659             : }
    2660             : 
    2661             : 
    2662    58624410 : ZEND_API char *zend_strndup(const char *s, uint length)
    2663             : {
    2664             :         char *p;
    2665             : #ifdef ZEND_SIGNALS
    2666             :         TSRMLS_FETCH();
    2667             : #endif
    2668             : 
    2669    58624410 :         HANDLE_BLOCK_INTERRUPTIONS();
    2670             : 
    2671    58624410 :         p = (char *) malloc(length+1);
    2672    58624410 :         if (UNEXPECTED(p == NULL)) {
    2673           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    2674           0 :                 return p;
    2675             :         }
    2676    58624410 :         if (length) {
    2677    58009267 :                 memcpy(p, s, length);
    2678             :         }
    2679    58624410 :         p[length] = 0;
    2680    58624410 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    2681    58624410 :         return p;
    2682             : }
    2683             : 
    2684             : 
    2685       22055 : ZEND_API int zend_set_memory_limit(size_t memory_limit TSRMLS_DC)
    2686             : {
    2687       22055 :         AG(mm_heap)->limit = (memory_limit >= AG(mm_heap)->block_size) ? memory_limit : AG(mm_heap)->block_size;
    2688             : 
    2689       22055 :         return SUCCESS;
    2690             : }
    2691             : 
    2692        1581 : ZEND_API size_t zend_memory_usage(int real_usage TSRMLS_DC)
    2693             : {
    2694        1581 :         if (real_usage) {
    2695         451 :                 return AG(mm_heap)->real_size;
    2696             :         } else {
    2697        1130 :                 size_t usage = AG(mm_heap)->size;
    2698             : #if ZEND_MM_CACHE
    2699        1130 :                 usage -= AG(mm_heap)->cached;
    2700             : #endif
    2701        1130 :                 return usage;
    2702             :         }
    2703             : }
    2704             : 
    2705           1 : ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC)
    2706             : {
    2707           1 :         if (real_usage) {
    2708           0 :                 return AG(mm_heap)->real_peak;
    2709             :         } else {
    2710           1 :                 return AG(mm_heap)->peak;
    2711             :         }
    2712             : }
    2713             : 
    2714       63796 : ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC)
    2715             : {
    2716       63796 :         zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC);
    2717       63796 : }
    2718             : 
    2719       21257 : static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC)
    2720             : {
    2721       21257 :         char *tmp = getenv("USE_ZEND_ALLOC");
    2722             : 
    2723       42506 :         if (tmp && !zend_atoi(tmp, 0)) {
    2724       21249 :                 alloc_globals->mm_heap = malloc(sizeof(struct _zend_mm_heap));
    2725       21249 :                 memset(alloc_globals->mm_heap, 0, sizeof(struct _zend_mm_heap));
    2726       21249 :                 alloc_globals->mm_heap->use_zend_alloc = 0;
    2727       21249 :                 alloc_globals->mm_heap->_malloc = malloc;
    2728       21249 :                 alloc_globals->mm_heap->_free = free;
    2729       21249 :                 alloc_globals->mm_heap->_realloc = realloc;
    2730             :         } else {
    2731           8 :                 alloc_globals->mm_heap = zend_mm_startup();
    2732             :         }
    2733       21257 : }
    2734             : 
    2735             : #ifdef ZTS
    2736             : static void alloc_globals_dtor(zend_alloc_globals *alloc_globals TSRMLS_DC)
    2737             : {
    2738             :         shutdown_memory_manager(1, 1 TSRMLS_CC);
    2739             : }
    2740             : #endif
    2741             : 
    2742       21257 : ZEND_API void start_memory_manager(TSRMLS_D)
    2743             : {
    2744             : #ifdef ZTS
    2745             :         ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
    2746             : #else
    2747       21257 :         alloc_globals_ctor(&alloc_globals);
    2748             : #endif
    2749       21257 : }
    2750             : 
    2751           0 : ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap TSRMLS_DC)
    2752             : {
    2753             :         zend_mm_heap *old_heap;
    2754             : 
    2755           0 :         old_heap = AG(mm_heap);
    2756           0 :         AG(mm_heap) = new_heap;
    2757           0 :         return old_heap;
    2758             : }
    2759             : 
    2760           0 : ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap)
    2761             : {
    2762           0 :         return heap->storage;
    2763             : }
    2764             : 
    2765           0 : ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
    2766             :                                           void* (*_malloc)(size_t),
    2767             :                                           void  (*_free)(void*),
    2768             :                                           void* (*_realloc)(void*, size_t))
    2769             : {
    2770           0 :         heap->use_zend_alloc = 0;
    2771           0 :         heap->_malloc = _malloc;
    2772           0 :         heap->_free = _free;
    2773           0 :         heap->_realloc = _realloc;
    2774           0 : }
    2775             : 
    2776             : #if ZEND_DEBUG
    2777             : ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2778             : {
    2779             :         TSRMLS_FETCH();
    2780             : 
    2781             :         if (!AG(mm_heap)->use_zend_alloc) {
    2782             :                 return 1;
    2783             :         }
    2784             :         return zend_mm_check_ptr(AG(mm_heap), ptr, silent ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2785             : }
    2786             : 
    2787             : 
    2788             : ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
    2789             : {
    2790             :         int errors;
    2791             :         TSRMLS_FETCH();
    2792             : 
    2793             :         if (!AG(mm_heap)->use_zend_alloc) {
    2794             :                 return;
    2795             :         }
    2796             : 
    2797             :         zend_debug_alloc_output("------------------------------------------------\n");
    2798             :         zend_debug_alloc_output("Full Memory Check at %s:%d\n" ZEND_FILE_LINE_RELAY_CC);
    2799             : 
    2800             :         errors = zend_mm_check_heap(AG(mm_heap), silent ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
    2801             : 
    2802             :         zend_debug_alloc_output("End of full memory check %s:%d (%d errors)\n" ZEND_FILE_LINE_RELAY_CC, errors);
    2803             :         zend_debug_alloc_output("------------------------------------------------\n");
    2804             : }
    2805             : #endif
    2806             : 
    2807             : /*
    2808             :  * Local variables:
    2809             :  * tab-width: 4
    2810             :  * c-basic-offset: 4
    2811             :  * indent-tabs-mode: t
    2812             :  * End:
    2813             :  */

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:06 +0000 (6 days ago)

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