4747#include <memory.h>
4848#include <assert.h>
4949#include <malloc.h>
50- #include <emscripten/heap .h>
51- #include <emscripten/threading .h>
50+ #include <limits .h>
51+ #include <stdlib .h>
5252
5353#ifdef __EMSCRIPTEN_TRACING__
5454#include <emscripten/trace.h>
5555#endif
5656
57+ // Defind by the linker to have the address of the start of the heap.
58+ extern unsigned char __heap_base ;
59+
5760// Behavior of right shifting a signed integer is compiler implementation defined.
5861static_assert ((((int32_t )0x80000000U ) >> 31 ) == -1 , "This malloc implementation requires that right-shifting a signed integer produces a sign-extending (arithmetic) shift!" );
5962
6063// Configuration: specifies the minimum alignment that malloc()ed memory outputs. Allocation requests with smaller alignment
6164// than this will yield an allocation with this much alignment.
6265#define MALLOC_ALIGNMENT alignof(max_align_t)
63- static_assert (alignof(max_align_t ) == 8 , "max_align_t must be correct" );
66+ static_assert (alignof(max_align_t ) == 16 , "max_align_t must be correct" );
6467
65- #define EMMALLOC_EXPORT __attribute__((weak, __visibility__("default") ))
68+ #define EMMALLOC_EXPORT __attribute__((weak))
6669
6770#define MIN (x , y ) ((x) < (y) ? (x) : (y))
6871#define MAX (x , y ) ((x) > (y) ? (x) : (y))
@@ -138,7 +141,72 @@ static RootRegion *listOfAllRegions = NULL;
138141// when adding and removing elements from the linked list, i.e. we are guaranteed that
139142// the sentinel node is always fixed and there, and the actual free region list elements
140143// start at freeRegionBuckets[i].next each.
141- static Region freeRegionBuckets [NUM_FREE_BUCKETS ];
144+ static Region freeRegionBuckets [NUM_FREE_BUCKETS ] = {
145+ { .prev = & freeRegionBuckets [0 ], .next = & freeRegionBuckets [0 ] },
146+ { .prev = & freeRegionBuckets [1 ], .next = & freeRegionBuckets [1 ] },
147+ { .prev = & freeRegionBuckets [2 ], .next = & freeRegionBuckets [2 ] },
148+ { .prev = & freeRegionBuckets [3 ], .next = & freeRegionBuckets [3 ] },
149+ { .prev = & freeRegionBuckets [4 ], .next = & freeRegionBuckets [4 ] },
150+ { .prev = & freeRegionBuckets [5 ], .next = & freeRegionBuckets [5 ] },
151+ { .prev = & freeRegionBuckets [6 ], .next = & freeRegionBuckets [6 ] },
152+ { .prev = & freeRegionBuckets [7 ], .next = & freeRegionBuckets [7 ] },
153+ { .prev = & freeRegionBuckets [8 ], .next = & freeRegionBuckets [8 ] },
154+ { .prev = & freeRegionBuckets [9 ], .next = & freeRegionBuckets [9 ] },
155+ { .prev = & freeRegionBuckets [10 ], .next = & freeRegionBuckets [10 ] },
156+ { .prev = & freeRegionBuckets [11 ], .next = & freeRegionBuckets [11 ] },
157+ { .prev = & freeRegionBuckets [12 ], .next = & freeRegionBuckets [12 ] },
158+ { .prev = & freeRegionBuckets [13 ], .next = & freeRegionBuckets [13 ] },
159+ { .prev = & freeRegionBuckets [14 ], .next = & freeRegionBuckets [14 ] },
160+ { .prev = & freeRegionBuckets [15 ], .next = & freeRegionBuckets [15 ] },
161+ { .prev = & freeRegionBuckets [16 ], .next = & freeRegionBuckets [16 ] },
162+ { .prev = & freeRegionBuckets [17 ], .next = & freeRegionBuckets [17 ] },
163+ { .prev = & freeRegionBuckets [18 ], .next = & freeRegionBuckets [18 ] },
164+ { .prev = & freeRegionBuckets [19 ], .next = & freeRegionBuckets [19 ] },
165+ { .prev = & freeRegionBuckets [20 ], .next = & freeRegionBuckets [20 ] },
166+ { .prev = & freeRegionBuckets [21 ], .next = & freeRegionBuckets [21 ] },
167+ { .prev = & freeRegionBuckets [22 ], .next = & freeRegionBuckets [22 ] },
168+ { .prev = & freeRegionBuckets [23 ], .next = & freeRegionBuckets [23 ] },
169+ { .prev = & freeRegionBuckets [24 ], .next = & freeRegionBuckets [24 ] },
170+ { .prev = & freeRegionBuckets [25 ], .next = & freeRegionBuckets [25 ] },
171+ { .prev = & freeRegionBuckets [26 ], .next = & freeRegionBuckets [26 ] },
172+ { .prev = & freeRegionBuckets [27 ], .next = & freeRegionBuckets [27 ] },
173+ { .prev = & freeRegionBuckets [28 ], .next = & freeRegionBuckets [28 ] },
174+ { .prev = & freeRegionBuckets [29 ], .next = & freeRegionBuckets [29 ] },
175+ { .prev = & freeRegionBuckets [30 ], .next = & freeRegionBuckets [30 ] },
176+ { .prev = & freeRegionBuckets [31 ], .next = & freeRegionBuckets [31 ] },
177+ { .prev = & freeRegionBuckets [32 ], .next = & freeRegionBuckets [32 ] },
178+ { .prev = & freeRegionBuckets [33 ], .next = & freeRegionBuckets [33 ] },
179+ { .prev = & freeRegionBuckets [34 ], .next = & freeRegionBuckets [34 ] },
180+ { .prev = & freeRegionBuckets [35 ], .next = & freeRegionBuckets [35 ] },
181+ { .prev = & freeRegionBuckets [36 ], .next = & freeRegionBuckets [36 ] },
182+ { .prev = & freeRegionBuckets [37 ], .next = & freeRegionBuckets [37 ] },
183+ { .prev = & freeRegionBuckets [38 ], .next = & freeRegionBuckets [38 ] },
184+ { .prev = & freeRegionBuckets [39 ], .next = & freeRegionBuckets [39 ] },
185+ { .prev = & freeRegionBuckets [40 ], .next = & freeRegionBuckets [40 ] },
186+ { .prev = & freeRegionBuckets [41 ], .next = & freeRegionBuckets [41 ] },
187+ { .prev = & freeRegionBuckets [42 ], .next = & freeRegionBuckets [42 ] },
188+ { .prev = & freeRegionBuckets [43 ], .next = & freeRegionBuckets [43 ] },
189+ { .prev = & freeRegionBuckets [44 ], .next = & freeRegionBuckets [44 ] },
190+ { .prev = & freeRegionBuckets [45 ], .next = & freeRegionBuckets [45 ] },
191+ { .prev = & freeRegionBuckets [46 ], .next = & freeRegionBuckets [46 ] },
192+ { .prev = & freeRegionBuckets [47 ], .next = & freeRegionBuckets [47 ] },
193+ { .prev = & freeRegionBuckets [48 ], .next = & freeRegionBuckets [48 ] },
194+ { .prev = & freeRegionBuckets [49 ], .next = & freeRegionBuckets [49 ] },
195+ { .prev = & freeRegionBuckets [50 ], .next = & freeRegionBuckets [50 ] },
196+ { .prev = & freeRegionBuckets [51 ], .next = & freeRegionBuckets [51 ] },
197+ { .prev = & freeRegionBuckets [52 ], .next = & freeRegionBuckets [52 ] },
198+ { .prev = & freeRegionBuckets [53 ], .next = & freeRegionBuckets [53 ] },
199+ { .prev = & freeRegionBuckets [54 ], .next = & freeRegionBuckets [54 ] },
200+ { .prev = & freeRegionBuckets [55 ], .next = & freeRegionBuckets [55 ] },
201+ { .prev = & freeRegionBuckets [56 ], .next = & freeRegionBuckets [56 ] },
202+ { .prev = & freeRegionBuckets [57 ], .next = & freeRegionBuckets [57 ] },
203+ { .prev = & freeRegionBuckets [58 ], .next = & freeRegionBuckets [58 ] },
204+ { .prev = & freeRegionBuckets [59 ], .next = & freeRegionBuckets [59 ] },
205+ { .prev = & freeRegionBuckets [60 ], .next = & freeRegionBuckets [60 ] },
206+ { .prev = & freeRegionBuckets [61 ], .next = & freeRegionBuckets [61 ] },
207+ { .prev = & freeRegionBuckets [62 ], .next = & freeRegionBuckets [62 ] },
208+ { .prev = & freeRegionBuckets [63 ], .next = & freeRegionBuckets [63 ] },
209+ };
142210
143211// A bitmask that tracks the population status for each of the 64 distinct memory regions:
144212// a zero at bit position i means that the free list bucket i is empty. This bitmask is
@@ -347,6 +415,7 @@ static void link_to_free_list(Region *freeRegion)
347415 freeRegionBucketsUsed |= ((BUCKET_BITMASK_T )1 ) << bucketIndex ;
348416}
349417
418+ #if 0
350419static void dump_memory_regions ()
351420{
352421 ASSERT_MALLOC_IS_ACQUIRED ();
@@ -458,6 +527,7 @@ int emmalloc_validate_memory_regions()
458527 MALLOC_RELEASE ();
459528 return memoryError ;
460529}
530+ #endif
461531
462532static bool claim_more_memory (size_t numBytes )
463533{
@@ -469,20 +539,38 @@ static bool claim_more_memory(size_t numBytes)
469539 validate_memory_regions ();
470540#endif
471541
472- // Claim memory via sbrk
473- uint8_t * startPtr = (uint8_t * )sbrk (numBytes );
474- if ((intptr_t )startPtr == -1 )
475- {
542+ uint8_t * startPtr ;
543+ uint8_t * endPtr ;
544+ do {
545+ // If this is the first time we're called, see if we can use
546+ // the initial heap memory set up by wasm-ld.
547+ if (!listOfAllRegions ) {
548+ unsigned char * heap_end = sbrk (0 );
549+ if (numBytes <= (size_t )(heap_end - & __heap_base )) {
550+ startPtr = & __heap_base ;
551+ endPtr = heap_end ;
552+ break ;
553+ }
554+ }
555+
556+ // Round numBytes up to the nearest page size.
557+ numBytes = (numBytes + (PAGE_SIZE - 1 )) & - PAGE_SIZE ;
558+
559+ // Claim memory via sbrk
560+ startPtr = (uint8_t * )sbrk (numBytes );
561+ if ((intptr_t )startPtr == -1 )
562+ {
476563#ifdef EMMALLOC_VERBOSE
477- MAIN_THREAD_ASYNC_EM_ASM (console .error ('claim_more_memory: sbrk failed!' ));
564+ MAIN_THREAD_ASYNC_EM_ASM (console .error ('claim_more_memory: sbrk failed!' ));
478565#endif
479- return false;
480- }
566+ return false;
567+ }
481568#ifdef EMMALLOC_VERBOSE
482- MAIN_THREAD_ASYNC_EM_ASM (console .log ('claim_more_memory: claimed 0x' + ($0 >>> 0 ).toString (16 ) + ' - 0x' + ($1 >>> 0 ).toString (16 ) + ' (' + ($2 >>> 0 ) + ' bytes) via sbrk()' ), startPtr , startPtr + numBytes , numBytes );
569+ MAIN_THREAD_ASYNC_EM_ASM (console .log ('claim_more_memory: claimed 0x' + ($0 >>> 0 ).toString (16 ) + ' - 0x' + ($1 >>> 0 ).toString (16 ) + ' (' + ($2 >>> 0 ) + ' bytes) via sbrk()' ), startPtr , startPtr + numBytes , numBytes );
483570#endif
484- assert (HAS_ALIGNMENT (startPtr , alignof(size_t )));
485- uint8_t * endPtr = startPtr + numBytes ;
571+ assert (HAS_ALIGNMENT (startPtr , alignof(size_t )));
572+ endPtr = startPtr + numBytes ;
573+ } while (0 );
486574
487575 // Create a sentinel region at the end of the new heap block
488576 Region * endSentinelRegion = (Region * )(endPtr - sizeof (Region ));
@@ -535,6 +623,7 @@ static bool claim_more_memory(size_t numBytes)
535623 return true;
536624}
537625
626+ #if 0
538627// Initialize emmalloc during static initialization.
539628// See system/lib/README.md for static constructor ordering.
540629__attribute__((constructor (47 )))
@@ -562,6 +651,7 @@ void emmalloc_blank_slate_from_orbit()
562651 initialize_emmalloc_heap ();
563652 MALLOC_RELEASE ();
564653}
654+ #endif
565655
566656static void * attempt_allocate (Region * freeRegion , size_t alignment , size_t size )
567657{
@@ -796,19 +886,21 @@ static void *allocate_memory(size_t alignment, size_t size)
796886 return 0 ;
797887}
798888
889+ static
799890void * emmalloc_memalign (size_t alignment , size_t size )
800891{
801892 MALLOC_ACQUIRE ();
802893 void * ptr = allocate_memory (alignment , size );
803894 MALLOC_RELEASE ();
804895 return ptr ;
805896}
806- extern __typeof (emmalloc_memalign ) emscripten_builtin_memalign __attribute__((alias ("emmalloc_memalign" )));
807897
898+ #if 0
808899void * EMMALLOC_EXPORT memalign (size_t alignment , size_t size )
809900{
810901 return emmalloc_memalign (alignment , size );
811902}
903+ #endif
812904
813905void * EMMALLOC_EXPORT aligned_alloc (size_t alignment , size_t size )
814906{
@@ -817,18 +909,18 @@ void * EMMALLOC_EXPORT aligned_alloc(size_t alignment, size_t size)
817909 return emmalloc_memalign (alignment , size );
818910}
819911
912+ static
820913void * emmalloc_malloc (size_t size )
821914{
822915 return emmalloc_memalign (MALLOC_ALIGNMENT , size );
823916}
824- extern __typeof (emmalloc_malloc ) emscripten_builtin_malloc __attribute__((alias ("emmalloc_malloc" )));
825- extern __typeof (emmalloc_malloc ) __libc_malloc __attribute__((alias ("emmalloc_malloc" )));
826917
827918void * EMMALLOC_EXPORT malloc (size_t size )
828919{
829920 return emmalloc_malloc (size );
830921}
831922
923+ static
832924size_t emmalloc_usable_size (void * ptr )
833925{
834926 if (!ptr )
@@ -854,6 +946,7 @@ size_t EMMALLOC_EXPORT malloc_usable_size(void *ptr)
854946 return emmalloc_usable_size (ptr );
855947}
856948
949+ static
857950void emmalloc_free (void * ptr )
858951{
859952#ifdef EMMALLOC_MEMVALIDATE
@@ -923,12 +1016,10 @@ void emmalloc_free(void *ptr)
9231016 emmalloc_validate_memory_regions ();
9241017#endif
9251018}
926- extern __typeof (emmalloc_free ) emscripten_builtin_free __attribute__((alias ("emmalloc_free" )));
927- extern __typeof (emmalloc_free ) __libc_free __attribute__((alias ("emmalloc_free" )));
9281019
9291020void EMMALLOC_EXPORT free (void * ptr )
9301021{
931- return emmalloc_free (ptr );
1022+ emmalloc_free (ptr );
9321023}
9331024
9341025// Can be called to attempt to increase or decrease the size of the given region
@@ -1005,6 +1096,7 @@ static int acquire_and_attempt_region_resize(Region *region, size_t size)
10051096 return success ;
10061097}
10071098
1099+ static
10081100void * emmalloc_aligned_realloc (void * ptr , size_t alignment , size_t size )
10091101{
10101102#ifdef EMMALLOC_VERBOSE
@@ -1058,11 +1150,14 @@ void *emmalloc_aligned_realloc(void *ptr, size_t alignment, size_t size)
10581150 return newptr ;
10591151}
10601152
1153+ #if 0
10611154void * EMMALLOC_EXPORT aligned_realloc (void * ptr , size_t alignment , size_t size )
10621155{
10631156 return emmalloc_aligned_realloc (ptr , alignment , size );
10641157}
1158+ #endif
10651159
1160+ #if 0
10661161// realloc_try() is like realloc(), but only attempts to try to resize the existing memory
10671162// area. If resizing the existing memory area fails, then realloc_try() will return 0
10681163// (the original memory block is not freed or modified). If resizing succeeds, previous
@@ -1140,25 +1235,29 @@ void *emmalloc_aligned_realloc_uninitialized(void *ptr, size_t alignment, size_t
11401235 free (ptr );
11411236 return emmalloc_memalign (alignment , size );
11421237}
1238+ #endif
11431239
1240+ static
11441241void * emmalloc_realloc (void * ptr , size_t size )
11451242{
11461243 return emmalloc_aligned_realloc (ptr , MALLOC_ALIGNMENT , size );
11471244}
1148- extern __typeof (emmalloc_realloc ) __libc_realloc __attribute__((alias ("emmalloc_realloc" )));
11491245
11501246void * EMMALLOC_EXPORT realloc (void * ptr , size_t size )
11511247{
11521248 return emmalloc_realloc (ptr , size );
11531249}
11541250
1251+ #if 0
11551252// realloc_uninitialized() is like realloc(), but old memory contents
11561253// will be undefined after reallocation. (old memory is not preserved in any case)
11571254void * emmalloc_realloc_uninitialized (void * ptr , size_t size )
11581255{
11591256 return emmalloc_aligned_realloc_uninitialized (ptr , MALLOC_ALIGNMENT , size );
11601257}
1258+ #endif
11611259
1260+ static
11621261int emmalloc_posix_memalign (void * * memptr , size_t alignment , size_t size )
11631262{
11641263 assert (memptr );
@@ -1173,6 +1272,7 @@ int EMMALLOC_EXPORT posix_memalign(void **memptr, size_t alignment, size_t size)
11731272 return emmalloc_posix_memalign (memptr , alignment , size );
11741273}
11751274
1275+ static
11761276void * emmalloc_calloc (size_t num , size_t size )
11771277{
11781278 size_t bytes = num * size ;
@@ -1181,13 +1281,13 @@ void *emmalloc_calloc(size_t num, size_t size)
11811281 memset (ptr , 0 , bytes );
11821282 return ptr ;
11831283}
1184- extern __typeof (emmalloc_calloc ) __libc_calloc __attribute__((alias ("emmalloc_calloc" )));
11851284
11861285void * EMMALLOC_EXPORT calloc (size_t num , size_t size )
11871286{
11881287 return emmalloc_calloc (num , size );
11891288}
11901289
1290+ #if 0
11911291static int count_linked_list_size (Region * list )
11921292{
11931293 int size = 1 ;
@@ -1427,3 +1527,9 @@ size_t emmalloc_compute_free_dynamic_memory_fragmentation_map(size_t freeMemoryS
14271527size_t emmalloc_unclaimed_heap_memory (void ) {
14281528 return emscripten_get_heap_max () - (size_t )sbrk (0 );
14291529}
1530+ #endif
1531+
1532+ // Define these to satisfy musl references.
1533+ void * __libc_malloc (size_t ) __attribute__((alias ("malloc" )));
1534+ void __libc_free (void * ) __attribute__((alias ("free" )));
1535+ void * __libc_calloc (size_t nmemb , size_t size ) __attribute__((alias ("calloc" )));
0 commit comments