5050 * with more specialized routines when the requested size is known.
5151 */
5252
53- #include "php.h"
5453#include "zend.h"
5554#include "zend_alloc.h"
5655#include "zend_globals.h"
@@ -2480,24 +2479,21 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
24802479 zend_mm_chunk * p ;
24812480 zend_mm_huge_list * list ;
24822481
2483- // Call observer shutdown callbacks before cleaning up
24842482#if ZEND_MM_CUSTOM
24852483 if (heap -> use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED ) {
24862484 zend_mm_observer * current = heap -> observers ;
24872485 while (current != NULL ) {
2486+ zend_mm_observer * next = current -> next ;
24882487 if (current -> shutdown != NULL ) {
24892488 current -> shutdown (full , silent );
24902489 }
2491- current = current -> next ;
2490+ pefree (current , 1 );
2491+ current = next ;
24922492 }
2493- }
2494- #endif
2495-
2496- if (full == false) {
2497- zend_mm_observers_shutdown (heap );
2493+ heap -> observers = NULL ;
2494+ heap -> use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED ;
24982495 }
24992496
2500- #if ZEND_MM_CUSTOM
25012497 if (heap -> use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED ) {
25022498 if (heap -> custom_heap ._malloc == tracked_malloc ) {
25032499 if (silent ) {
@@ -2651,7 +2647,7 @@ void* ZEND_FASTCALL _zend_mm_realloc2(zend_mm_heap *heap, void *ptr, size_t size
26512647ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size (zend_mm_heap * heap , void * ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC )
26522648{
26532649#if ZEND_MM_CUSTOM
2654- if (UNEXPECTED (heap -> use_custom_heap )) {
2650+ if (UNEXPECTED (heap -> use_custom_heap & ~ ZEND_MM_CUSTOM_HEAP_OBSERVED )) {
26552651 if (heap -> custom_heap ._malloc == tracked_malloc ) {
26562652 zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
26572653 zval * size_zv = zend_hash_index_find (heap -> tracked_allocs , h );
@@ -2730,29 +2726,100 @@ ZEND_API bool is_zend_ptr(const void *ptr)
27302726 return 0 ;
27312727}
27322728
2729+ #if ZEND_MM_CUSTOM
2730+ static ZEND_COLD void * ZEND_FASTCALL zend_mm_alloc_custom (zend_mm_heap * heap , int use_custom_heap , size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC )
2731+ {
2732+ void * ptr ;
2733+
2734+ ZEND_ASSERT (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED );
2735+ ptr = heap -> custom_heap ._malloc (size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2736+ HANDLE_OBSERVERS (malloc , size , ptr )
2737+
2738+ return ptr ;
2739+ }
2740+
2741+ static ZEND_COLD void ZEND_FASTCALL zend_mm_free_custom (zend_mm_heap * heap , int use_custom_heap , void * ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC )
2742+ {
2743+ ZEND_ASSERT (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED );
2744+ HANDLE_OBSERVERS (free , ptr )
2745+ heap -> custom_heap ._free (ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2746+ }
2747+ #endif
2748+
27332749#if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P )
27342750#undef _emalloc
27352751
27362752#if ZEND_MM_CUSTOM
2737- # define ZEND_MM_CUSTOM_ALLOCATOR (size ) do { \
2738- if (UNEXPECTED(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { \
2739- return AG(mm_heap)->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2753+ # define ZEND_MM_OBSERVED_BIN_ALLOCATOR (_size , _num , _min_size ) do { \
2754+ zend_mm_heap *heap = AG(mm_heap); \
2755+ int use_custom_heap = heap->use_custom_heap; \
2756+ if (UNEXPECTED(use_custom_heap)) { \
2757+ void *ptr; \
2758+ if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
2759+ return zend_mm_alloc_custom(heap, use_custom_heap, _size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2760+ } \
2761+ if (_size < _min_size) { \
2762+ ptr = zend_mm_alloc_small(heap, ZEND_MM_SMALL_SIZE_TO_BIN(_min_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2763+ } else { \
2764+ ptr = zend_mm_alloc_small(heap, _num ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2765+ } \
2766+ HANDLE_OBSERVERS(malloc, _size, ptr) \
2767+ return ptr; \
2768+ } \
2769+ } while (0)
2770+ # define ZEND_MM_OBSERVED_ALLOCATOR (size , allocation ) do { \
2771+ zend_mm_heap *heap = AG(mm_heap); \
2772+ int use_custom_heap = heap->use_custom_heap; \
2773+ if (UNEXPECTED(use_custom_heap)) { \
2774+ void *ptr; \
2775+ if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
2776+ return zend_mm_alloc_custom(heap, use_custom_heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2777+ } \
2778+ ptr = (allocation); \
2779+ HANDLE_OBSERVERS(malloc, size, ptr) \
2780+ return ptr; \
2781+ } \
2782+ } while (0)
2783+ # define ZEND_MM_OBSERVED_DEALLOCATOR (ptr , deallocation ) do { \
2784+ zend_mm_heap *heap = AG(mm_heap); \
2785+ int use_custom_heap = heap->use_custom_heap; \
2786+ if (UNEXPECTED(use_custom_heap)) { \
2787+ if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
2788+ zend_mm_free_custom(heap, use_custom_heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2789+ return; \
2790+ } \
2791+ HANDLE_OBSERVERS(free, ptr) \
2792+ deallocation; \
2793+ return; \
27402794 } \
27412795 } while (0)
2742- # define ZEND_MM_CUSTOM_DEALLOCATOR (ptr ) do { \
2743- if (UNEXPECTED(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { \
2744- AG(mm_heap)->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2796+ # define ZEND_MM_OBSERVED_BIN_DEALLOCATOR (ptr , _size , _min_size , deallocation ) do { \
2797+ zend_mm_heap *heap = AG(mm_heap); \
2798+ int use_custom_heap = heap->use_custom_heap; \
2799+ if (UNEXPECTED(use_custom_heap)) { \
2800+ if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \
2801+ zend_mm_free_custom(heap, use_custom_heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \
2802+ return; \
2803+ } \
2804+ if (_size < _min_size) { \
2805+ _efree_ ## _min_size(ptr); \
2806+ return; \
2807+ } \
2808+ HANDLE_OBSERVERS(free, ptr) \
2809+ deallocation; \
27452810 return; \
27462811 } \
27472812 } while (0)
27482813#else
2749- # define ZEND_MM_CUSTOM_ALLOCATOR (size )
2750- # define ZEND_MM_CUSTOM_DEALLOCATOR (ptr )
2814+ # define ZEND_MM_OBSERVED_BIN_ALLOCATOR (_size , _num , _min_size )
2815+ # define ZEND_MM_OBSERVED_ALLOCATOR (size , allocation )
2816+ # define ZEND_MM_OBSERVED_DEALLOCATOR (ptr , deallocation )
2817+ # define ZEND_MM_OBSERVED_BIN_DEALLOCATOR (ptr , _size , _min_size , deallocation )
27512818#endif
27522819
27532820# define _ZEND_BIN_ALLOCATOR (_num , _size , _elements , _pages , _min_size , y ) \
27542821 ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) { \
2755- ZEND_MM_CUSTOM_ALLOCATOR (_size); \
2822+ ZEND_MM_OBSERVED_BIN_ALLOCATOR (_size, _num, _min_size ); \
27562823 if (_size < _min_size) { \
27572824 return _emalloc_ ## _min_size(); \
27582825 } \
@@ -2763,20 +2830,28 @@ ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR, ZEND_MM_MIN_USEABLE_BIN_SIZE, y)
27632830
27642831ZEND_API void * ZEND_FASTCALL _emalloc_large (size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC )
27652832{
2766- ZEND_MM_CUSTOM_ALLOCATOR (size );
2833+ ZEND_MM_OBSERVED_ALLOCATOR (size , zend_mm_alloc_large_ex ( heap , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC ) );
27672834 return zend_mm_alloc_large_ex (AG (mm_heap ), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
27682835}
27692836
27702837ZEND_API void * ZEND_FASTCALL _emalloc_huge (size_t size )
27712838{
2772- ZEND_MM_CUSTOM_ALLOCATOR (size );
2839+ ZEND_MM_OBSERVED_ALLOCATOR (size , zend_mm_alloc_huge ( heap , size ) );
27732840 return zend_mm_alloc_huge (AG (mm_heap ), size );
27742841}
27752842
27762843#if ZEND_DEBUG
27772844# define _ZEND_BIN_FREE (_num , _size , _elements , _pages , _min_size , y ) \
27782845 ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \
2779- ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \
2846+ ZEND_MM_OBSERVED_BIN_DEALLOCATOR(ptr, _size, _min_size, { \
2847+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE); \
2848+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \
2849+ int page_num = page_offset / ZEND_MM_PAGE_SIZE; \
2850+ ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); \
2851+ ZEND_ASSERT(chunk->map[page_num] & ZEND_MM_IS_SRUN); \
2852+ ZEND_ASSERT(ZEND_MM_SRUN_BIN_NUM(chunk->map[page_num]) == _num); \
2853+ zend_mm_free_small(heap, ptr, _num); \
2854+ }); \
27802855 if (_size < _min_size) { \
27812856 _efree_ ## _min_size(ptr); \
27822857 return; \
@@ -2794,7 +2869,11 @@ ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size)
27942869#else
27952870# define _ZEND_BIN_FREE (_num , _size , _elements , _pages , _min_size , y ) \
27962871 ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \
2797- ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \
2872+ ZEND_MM_OBSERVED_BIN_DEALLOCATOR(ptr, _size, _min_size, { \
2873+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \
2874+ ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); \
2875+ zend_mm_free_small(heap, ptr, _num); \
2876+ }); \
27982877 if (_size < _min_size) { \
27992878 _efree_ ## _min_size(ptr); \
28002879 return; \
@@ -2811,7 +2890,17 @@ ZEND_MM_BINS_INFO(_ZEND_BIN_FREE, ZEND_MM_MIN_USEABLE_BIN_SIZE, y)
28112890
28122891ZEND_API void ZEND_FASTCALL _efree_large (void * ptr , size_t size )
28132892{
2814- ZEND_MM_CUSTOM_DEALLOCATOR (ptr );
2893+ ZEND_MM_OBSERVED_DEALLOCATOR (ptr , {
2894+ size_t page_offset = ZEND_MM_ALIGNED_OFFSET (ptr , ZEND_MM_CHUNK_SIZE );
2895+ zend_mm_chunk * chunk = (zend_mm_chunk * )ZEND_MM_ALIGNED_BASE (ptr , ZEND_MM_CHUNK_SIZE );
2896+ int page_num = page_offset / ZEND_MM_PAGE_SIZE ;
2897+ uint32_t pages_count = ZEND_MM_ALIGNED_SIZE_EX (size , ZEND_MM_PAGE_SIZE ) / ZEND_MM_PAGE_SIZE ;
2898+
2899+ ZEND_MM_CHECK (chunk -> heap == heap && ZEND_MM_ALIGNED_OFFSET (page_offset , ZEND_MM_PAGE_SIZE ) == 0 , "zend_mm_heap corrupted" );
2900+ ZEND_ASSERT (chunk -> map [page_num ] & ZEND_MM_IS_LRUN );
2901+ ZEND_ASSERT (ZEND_MM_LRUN_PAGES (chunk -> map [page_num ]) == pages_count );
2902+ zend_mm_free_large (heap , chunk , page_num , pages_count );
2903+ });
28152904 {
28162905 size_t page_offset = ZEND_MM_ALIGNED_OFFSET (ptr , ZEND_MM_CHUNK_SIZE );
28172906 zend_mm_chunk * chunk = (zend_mm_chunk * )ZEND_MM_ALIGNED_BASE (ptr , ZEND_MM_CHUNK_SIZE );
@@ -2828,7 +2917,7 @@ ZEND_API void ZEND_FASTCALL _efree_large(void *ptr, size_t size)
28282917ZEND_API void ZEND_FASTCALL _efree_huge (void * ptr , size_t size )
28292918{
28302919
2831- ZEND_MM_CUSTOM_DEALLOCATOR (ptr );
2920+ ZEND_MM_OBSERVED_DEALLOCATOR (ptr , zend_mm_free_huge ( heap , ptr ) );
28322921 zend_mm_free_huge (AG (mm_heap ), ptr );
28332922}
28342923#endif
@@ -2842,17 +2931,11 @@ ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
28422931 if (UNEXPECTED (use_custom_heap )) {
28432932 void * ptr ;
28442933
2845- // Check for actual custom handler (excluding observer bit)
28462934 if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED ) {
2847- ptr = heap -> custom_heap ._malloc (size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2848- } else {
2849- // No custom handler, use default heap
2850- ptr = zend_mm_alloc_heap (heap , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2935+ return zend_mm_alloc_custom (heap , use_custom_heap , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
28512936 }
2852-
2853- // Call observers if present
2937+ ptr = zend_mm_alloc_heap (heap , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
28542938 HANDLE_OBSERVERS (malloc , size , ptr )
2855-
28562939 return ptr ;
28572940 }
28582941#endif
@@ -2866,16 +2949,12 @@ ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_OR
28662949 int use_custom_heap = heap -> use_custom_heap ;
28672950
28682951 if (UNEXPECTED (use_custom_heap )) {
2869- // Call observers first (before free)
2870- HANDLE_OBSERVERS (free , ptr )
2871-
2872- // Check for actual custom handler (excluding observer bit)
28732952 if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED ) {
2874- heap -> custom_heap ._free (ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2875- } else {
2876- // No custom handler, use default heap
2877- zend_mm_free_heap (heap , ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2953+ zend_mm_free_custom (heap , use_custom_heap , ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
2954+ return ;
28782955 }
2956+ HANDLE_OBSERVERS (free , ptr )
2957+ zend_mm_free_heap (heap , ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
28792958 return ;
28802959 }
28812960#endif
@@ -2891,17 +2970,12 @@ ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC
28912970 if (UNEXPECTED (use_custom_heap )) {
28922971 void * new_ptr ;
28932972
2894- // Check for actual custom handler (excluding observer bit)
28952973 if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED ) {
28962974 new_ptr = heap -> custom_heap ._realloc (ptr , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
28972975 } else {
2898- // No custom handler, use default heap
28992976 new_ptr = zend_mm_realloc_heap (heap , ptr , size , 0 , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
29002977 }
2901-
2902- // Call observers if present
29032978 HANDLE_OBSERVERS (realloc , ptr , size , new_ptr )
2904-
29052979 return new_ptr ;
29062980 }
29072981#endif
@@ -2917,17 +2991,12 @@ ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size
29172991 if (UNEXPECTED (use_custom_heap )) {
29182992 void * new_ptr ;
29192993
2920- // Check for actual custom handler (excluding observer bit)
29212994 if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED ) {
29222995 new_ptr = heap -> custom_heap ._realloc (ptr , size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
29232996 } else {
2924- // No custom handler, use default heap
29252997 new_ptr = zend_mm_realloc_heap (heap , ptr , size , 1 , copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC );
29262998 }
2927-
2928- // Call observers if present
29292999 HANDLE_OBSERVERS (realloc , ptr , size , new_ptr )
2930-
29313000 return new_ptr ;
29323001 }
29333002#endif
@@ -3443,7 +3512,6 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
34433512#ifdef ZTS
34443513static void alloc_globals_dtor (zend_alloc_globals * alloc_globals )
34453514{
3446- zend_mm_observers_shutdown (alloc_globals -> mm_heap );
34473515 zend_mm_shutdown (alloc_globals -> mm_heap , 1 , 1 );
34483516}
34493517#endif
@@ -3645,7 +3713,6 @@ ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *
36453713 }
36463714 pefree (current , 1 );
36473715
3648- // Update flag if no more observers
36493716 if (heap -> observers == NULL ) {
36503717 heap -> use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED ;
36513718 }
@@ -3658,29 +3725,6 @@ ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *
36583725 return false;
36593726}
36603727
3661- void zend_mm_observers_shutdown (zend_mm_heap * heap )
3662- {
3663- #if ZEND_MM_CUSTOM
3664- if (heap == NULL ) {
3665- heap = AG (mm_heap );
3666- if (heap == NULL ) {
3667- return ;
3668- }
3669- }
3670-
3671- zend_mm_observer * current = heap -> observers ;
3672- zend_mm_observer * next = NULL ;
3673-
3674- while (current != NULL ) {
3675- next = current -> next ;
3676- pefree (current , 1 );
3677- current = next ;
3678- }
3679-
3680- heap -> observers = NULL ;
3681- heap -> use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED ;
3682- #endif
3683- }
36843728ZEND_API zend_mm_storage * zend_mm_get_storage (zend_mm_heap * heap )
36853729{
36863730#if ZEND_MM_STORAGE
@@ -3745,6 +3789,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
37453789#endif
37463790#if ZEND_MM_CUSTOM
37473791 heap -> use_custom_heap = 0 ;
3792+ heap -> observers = NULL ;
37483793#endif
37493794 heap -> storage = & tmp_storage ;
37503795 heap -> huge_list = NULL ;
0 commit comments