diff --git a/system/lib/emmalloc.c b/system/lib/emmalloc.c index f61c8dd993654..81a2499daab59 100644 --- a/system/lib/emmalloc.c +++ b/system/lib/emmalloc.c @@ -61,6 +61,8 @@ #include #include +void *_sbrk64(int64_t numBytes); + #ifdef __EMSCRIPTEN_TRACING__ #include #endif @@ -137,6 +139,7 @@ static volatile uint8_t multithreadingLock = 0; #define IS_POWER_OF_2(val) (((val) & ((val)-1)) == 0) #define ALIGN_UP(ptr, alignment) ((uint8_t*)((((uintptr_t)(ptr)) + ((alignment)-1)) & ~((alignment)-1))) +#define ALIGN_DOWN(ptr, alignment) ((uint8_t*)(((uintptr_t)(ptr)) & ~((alignment)-1))) #define HAS_ALIGNMENT(ptr, alignment) ((((uintptr_t)(ptr)) & ((alignment)-1)) == 0) static_assert(IS_POWER_OF_2(MALLOC_ALIGNMENT), "MALLOC_ALIGNMENT must be a power of two value!"); @@ -467,7 +470,8 @@ static bool claim_more_memory(size_t numBytes) { numBytes = (size_t)ALIGN_UP(numBytes, MALLOC_ALIGNMENT); // Claim memory via sbrk - uint8_t *startPtr = (uint8_t*)sbrk(numBytes); + assert((int64_t)numBytes >= 0); + uint8_t *startPtr = (uint8_t*)_sbrk64((int64_t)numBytes); if ((intptr_t)startPtr == -1) { #ifdef EMMALLOC_VERBOSE MAIN_THREAD_ASYNC_EM_ASM(err('claim_more_memory: sbrk failed!')); @@ -483,6 +487,9 @@ static bool claim_more_memory(size_t numBytes) { // Create a sentinel region at the end of the new heap block Region *endSentinelRegion = (Region*)(endPtr - sizeof(Region)); create_used_region(endSentinelRegion, sizeof(Region)); +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('claim_more_memory: created a sentinel memory region at address ' + ptrToString($0)), endSentinelRegion); +#endif // If we are the sole user of sbrk(), it will feed us continuous/consecutive memory addresses - take advantage // of that if so: instead of creating two disjoint memory regions blocks, expand the previous one to a larger size. @@ -1165,7 +1172,7 @@ struct mallinfo emmalloc_mallinfo() { struct mallinfo info; // Non-mmapped space allocated (bytes): For emmalloc, // let's define this as the difference between heap size and dynamic top end. - info.arena = emscripten_get_heap_size() - (size_t)sbrk(0); + info.arena = emscripten_get_heap_size() - (size_t)_sbrk64(0); // Number of "ordinary" blocks. Let's define this as the number of highest // size blocks. (subtract one from each, since there is a sentinel node in each list) info.ordblks = count_linked_list_size(&freeRegionBuckets[NUM_FREE_BUCKETS-1])-1; @@ -1227,73 +1234,118 @@ struct mallinfo emmalloc_mallinfo() { } EMMALLOC_ALIAS(mallinfo, emmalloc_mallinfo); -#if 0 // Note! This function is not fully multithreading safe: while this function is running, other threads should not be // allowed to call sbrk()! static int trim_dynamic_heap_reservation(size_t pad) { ASSERT_MALLOC_IS_ACQUIRED(); if (!listOfAllRegions) { +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): cannot trim memory, emmalloc is currently not initialized to manage any dynamic memory at all.')); +#endif return 0; // emmalloc is not controlling any dynamic memory at all - cannot release memory. } uint8_t *previousSbrkEndAddress = listOfAllRegions->endPtr; - assert(sbrk(0) == previousSbrkEndAddress); + void *sbrkAddr = _sbrk64(0); +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): _sbrk64(0) = ' + ptrToString($0) + ', previousSbrkEndAddress = ' + ptrToString($1)), sbrkAddr, previousSbrkEndAddress); +#endif + assert(sbrkAddr == previousSbrkEndAddress); size_t lastMemoryRegionSize = ((size_t*)previousSbrkEndAddress)[-1]; - assert(lastMemoryRegionSize == 16); // // The last memory region should be a sentinel node of exactly 16 bytes in size. - Region *endSentinelRegion = (Region*)(previousSbrkEndAddress - sizeof(Region)); + Region *endSentinelRegion = (Region*)(previousSbrkEndAddress - lastMemoryRegionSize); Region *lastActualRegion = prev_region(endSentinelRegion); - // Round padding up to multiple of 4 bytes to keep sbrk() and memory region alignment intact. - // Also have at least 8 bytes of payload so that we can form a full free region. - size_t newRegionSize = (size_t)ALIGN_UP(pad, 4); - if (pad > 0) { - newRegionSize += sizeof(Region) - (newRegionSize - pad); + if (!region_is_free(lastActualRegion)) { +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Last actual region ' + ptrToString($0) + ' is in use, there is nothing to trim from.'), lastActualRegion); +#endif + return 0; } - if (!region_is_free(lastActualRegion) || lastActualRegion->size <= newRegionSize) { - return 0; // Last actual region is in use, or caller desired to leave more free memory intact than there is. + // Sanitize odd alignments for padding values - this is the minimum alignment + // that emmalloc could handle. Align up to be conservative towards caller. + pad = (size_t)ALIGN_UP(pad, 4); + + // Calculate how many bytes we can shrink the sbrk() reservation by. + // Is the last free region smaller than what was requested to be left behind? + // If so, then there is nothing we can trim. + if (pad >= lastActualRegion->size) { +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Last actual region does not have enough space to leave ' + Number($0) + ' bytes of free memory in it.'), pad); +#endif + return 0; } - // This many bytes will be shrunk away. - size_t shrinkAmount = lastActualRegion->size - newRegionSize; - assert(HAS_ALIGNMENT(shrinkAmount, 4)); + // Subtract region size members off to calculate the excess bytes in payload. + size_t shrinkAmount = lastActualRegion->size - pad - 2*sizeof(size_t); + // sbrk() alignment is multiple of __alignof__(max_align_t), so round the + // trimming down to ensure that alignment is preserved. +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): shrinkAmount ' + Number($0) + '.'), shrinkAmount); +#endif + shrinkAmount = (size_t)ALIGN_DOWN(shrinkAmount, __alignof__(max_align_t)); +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): shrinkAmount2 ' + Number($0) + '.'), shrinkAmount); +#endif + // Nothing left to trim? + if (!shrinkAmount) { +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Aligning for sbrk() requirements removed opportunity to trim.')); +#endif + return 0; + } unlink_from_free_list(lastActualRegion); - // If pad == 0, we should delete the last free region altogether. If pad > 0, - // shrink the last free region to the desired size. - if (newRegionSize > 0) { + + size_t newRegionSize = lastActualRegion->size - shrinkAmount; + +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Shrinking ' + Number($0) + ' bytes off the free heap end region. New free heap end region size: ' + Number($1) + ' bytes.'), shrinkAmount, newRegionSize); +#endif + // If we can't fit a free Region in the shrunk space, we should delete the + // the last free region altogether. + if (newRegionSize >= sizeof(Region)) { create_free_region(lastActualRegion, newRegionSize); link_to_free_list(lastActualRegion); +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Created new free heap end region at ' + ptrToString($0) + '. Size: ' + Number($1) + ' bytes.'), lastActualRegion, newRegionSize); +#endif + } else { +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Not enough room to fit a free heap end region. Discarding it altogether.')); +#endif + newRegionSize = 0; } - // Recreate the sentinel region at the end of the last free region - endSentinelRegion = (Region*)((uint8_t*)lastActualRegion + newRegionSize); - create_used_region(endSentinelRegion, sizeof(Region)); + // Call sbrk() to shrink the memory area. + void *oldSbrk = _sbrk64(-(int64_t)shrinkAmount); + assert((intptr_t)oldSbrk != -1); // Shrinking with sbrk() should never fail. - // And update the size field of the whole region block. - listOfAllRegions->endPtr = (uint8_t*)endSentinelRegion + sizeof(Region); + // Ask where sbrk got us at. + void *sbrkNow = _sbrk64(0); - // Finally call sbrk() to shrink the memory area. - void *oldSbrk = sbrk(-(intptr_t)shrinkAmount); - assert((intptr_t)oldSbrk != -1); // Shrinking with sbrk() should never fail. - assert(oldSbrk == previousSbrkEndAddress); // Another thread should not have raced to increase sbrk() on us! + // Recreate the sentinel region at the end of the last free region. + Region *newEndSentinelRegion = (Region*)((uint8_t*)lastActualRegion + newRegionSize); + size_t newEndSentinelRegionSize = (uintptr_t)sbrkNow - (uintptr_t)newEndSentinelRegion; + +#ifdef EMMALLOC_VERBOSE + MAIN_THREAD_ASYNC_EM_ASM(out('emmalloc_trim(): Created new sentinel end region at ' + ptrToString($0) + '. Size: ' + Number($1) + ' bytes.'), newEndSentinelRegion, newEndSentinelRegionSize); +#endif + + create_used_region(newEndSentinelRegion, newEndSentinelRegionSize); + + // And update the size field of the whole region block. + listOfAllRegions->endPtr = (uint8_t*)newEndSentinelRegion + newEndSentinelRegionSize; // All successful, and we actually trimmed memory! return 1; } -#endif int emmalloc_trim(size_t pad) { - // Reducing the size of the sbrk region is currently broken. - // See https://github.com/emscripten-core/emscripten/issues/23343 - // And https://github.com/emscripten-core/emscripten/pull/13442 - return 0; - /* MALLOC_ACQUIRE(); int success = trim_dynamic_heap_reservation(pad); MALLOC_RELEASE(); return success; - */ } EMMALLOC_ALIAS(malloc_trim, emmalloc_trim) @@ -1376,5 +1428,5 @@ void emmalloc_dump_free_dynamic_memory_fragmentation_map() { } size_t emmalloc_unclaimed_heap_memory(void) { - return emscripten_get_heap_max() - (size_t)sbrk(0); + return emscripten_get_heap_max() - (size_t)_sbrk64(0); } diff --git a/system/lib/libc/sbrk.c b/system/lib/libc/sbrk.c index 2e2747ee31028..c370f9ec2f3d6 100644 --- a/system/lib/libc/sbrk.c +++ b/system/lib/libc/sbrk.c @@ -56,20 +56,25 @@ uintptr_t* emscripten_get_sbrk_ptr() { #define READ_SBRK_PTR(sbrk_ptr) (*(sbrk_ptr)) #endif -void *sbrk(intptr_t increment_) { - uintptr_t increment = (uintptr_t)increment_; - increment = (increment + (SBRK_ALIGNMENT-1)) & ~(SBRK_ALIGNMENT-1); +void *_sbrk64(int64_t increment) { + if (increment >= 0) { + increment = (increment + (SBRK_ALIGNMENT-1)) & ~((int64_t)SBRK_ALIGNMENT-1); + } else { + increment = -(-increment & ~((int64_t)SBRK_ALIGNMENT-1)); + } + uintptr_t *sbrk_ptr = (uintptr_t*)emscripten_get_sbrk_ptr(); // To make sbrk thread-safe, implement a CAS loop to update the // value of sbrk_ptr. while (1) { uintptr_t old_brk = READ_SBRK_PTR(sbrk_ptr); - uintptr_t new_brk = old_brk + increment; - // Check for a) an overflow, which would indicate that we are trying to - // allocate over maximum addressable memory. and b) if necessary, + int64_t new_brk64 = (int64_t)old_brk + increment; + uintptr_t new_brk = (uintptr_t)new_brk64; + // Check for a) an over/underflow, which would indicate that we are + // allocating over maximum addressable memory. and b) if necessary, // increase the WebAssembly Memory size, and abort if that fails. - if ((increment > 0 && new_brk <= old_brk) + if (new_brk < 0 || new_brk64 != (int64_t)new_brk || (new_brk > emscripten_get_heap_size() && !emscripten_resize_heap(new_brk))) { errno = ENOMEM; return (void*)-1; @@ -93,6 +98,26 @@ void *sbrk(intptr_t increment_) { } } +void *sbrk(intptr_t increment_) { +#if defined(__wasm64__) // TODO || !defined(wasm2gb) + // In the correct https://linux.die.net/man/2/sbrk spec, sbrk() parameter is + // intended to be treated as signed, meaning that it is not possible in a + // 32-bit program to sbrk alloc (or dealloc) more than 2GB of memory at once. + + // Treat sbrk() parameter as signed. + return _sbrk64((int64_t)increment_); +#else + // BUG: Currently the Emscripten test suite codifies expectations that sbrk() + // values passed to this function are to be treated as unsigned, which means + // that in 2GB and 4GB build modes, it is not possible to shrink memory. + // To satisfy that mode, treat sbrk() parameters in 32-bit builds as unsigned. + // https://github.com/emscripten-core/emscripten/issues/25138 + + // Treat sbrk() parameter as unsigned. + return _sbrk64((int64_t)(uintptr_t)increment_); +#endif +} + int brk(void* ptr) { #ifdef __EMSCRIPTEN_SHARED_MEMORY__ // FIXME diff --git a/test/code_size/test_codesize_cxx_ctors1.json b/test/code_size/test_codesize_cxx_ctors1.json index 13bd612c56292..47588332ee0f0 100644 --- a/test/code_size/test_codesize_cxx_ctors1.json +++ b/test/code_size/test_codesize_cxx_ctors1.json @@ -1,10 +1,10 @@ { "a.out.js": 19754, "a.out.js.gz": 8162, - "a.out.nodebug.wasm": 129504, - "a.out.nodebug.wasm.gz": 49232, - "total": 149258, - "total_gz": 57394, + "a.out.nodebug.wasm": 129517, + "a.out.nodebug.wasm.gz": 49253, + "total": 149271, + "total_gz": 57415, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_cxx_ctors2.json b/test/code_size/test_codesize_cxx_ctors2.json index de0312f8463a4..3faa5d4548a4c 100644 --- a/test/code_size/test_codesize_cxx_ctors2.json +++ b/test/code_size/test_codesize_cxx_ctors2.json @@ -1,10 +1,10 @@ { "a.out.js": 19732, "a.out.js.gz": 8148, - "a.out.nodebug.wasm": 128931, - "a.out.nodebug.wasm.gz": 48876, - "total": 148663, - "total_gz": 57024, + "a.out.nodebug.wasm": 128944, + "a.out.nodebug.wasm.gz": 48891, + "total": 148676, + "total_gz": 57039, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_cxx_except.json b/test/code_size/test_codesize_cxx_except.json index dc86577e8831b..9122f813d117a 100644 --- a/test/code_size/test_codesize_cxx_except.json +++ b/test/code_size/test_codesize_cxx_except.json @@ -1,10 +1,10 @@ { "a.out.js": 23415, "a.out.js.gz": 9145, - "a.out.nodebug.wasm": 171266, - "a.out.nodebug.wasm.gz": 57323, - "total": 194681, - "total_gz": 66468, + "a.out.nodebug.wasm": 171279, + "a.out.nodebug.wasm.gz": 57348, + "total": 194694, + "total_gz": 66493, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/code_size/test_codesize_cxx_except_wasm.json b/test/code_size/test_codesize_cxx_except_wasm.json index 42e1c746dc717..95e46cfd54adf 100644 --- a/test/code_size/test_codesize_cxx_except_wasm.json +++ b/test/code_size/test_codesize_cxx_except_wasm.json @@ -1,10 +1,10 @@ { "a.out.js": 19643, "a.out.js.gz": 8112, - "a.out.nodebug.wasm": 144625, - "a.out.nodebug.wasm.gz": 54883, - "total": 164268, - "total_gz": 62995, + "a.out.nodebug.wasm": 144638, + "a.out.nodebug.wasm.gz": 54898, + "total": 164281, + "total_gz": 63010, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/code_size/test_codesize_cxx_except_wasm_legacy.json b/test/code_size/test_codesize_cxx_except_wasm_legacy.json index ef68840268bcf..958f00dc9ff7d 100644 --- a/test/code_size/test_codesize_cxx_except_wasm_legacy.json +++ b/test/code_size/test_codesize_cxx_except_wasm_legacy.json @@ -1,10 +1,10 @@ { "a.out.js": 19643, "a.out.js.gz": 8112, - "a.out.nodebug.wasm": 142214, - "a.out.nodebug.wasm.gz": 54349, - "total": 161857, - "total_gz": 62461, + "a.out.nodebug.wasm": 142227, + "a.out.nodebug.wasm.gz": 54362, + "total": 161870, + "total_gz": 62474, "sent": [ "_abort_js", "_tzset_js", diff --git a/test/code_size/test_codesize_cxx_mangle.json b/test/code_size/test_codesize_cxx_mangle.json index dbcbe0a7c1003..2997a46f6af3c 100644 --- a/test/code_size/test_codesize_cxx_mangle.json +++ b/test/code_size/test_codesize_cxx_mangle.json @@ -1,10 +1,10 @@ { "a.out.js": 23465, "a.out.js.gz": 9164, - "a.out.nodebug.wasm": 235307, - "a.out.nodebug.wasm.gz": 78924, - "total": 258772, - "total_gz": 88088, + "a.out.nodebug.wasm": 235320, + "a.out.nodebug.wasm.gz": 78938, + "total": 258785, + "total_gz": 88102, "sent": [ "__cxa_begin_catch", "__cxa_end_catch", diff --git a/test/code_size/test_codesize_cxx_noexcept.json b/test/code_size/test_codesize_cxx_noexcept.json index a53f624b47b00..76c3448e92f30 100644 --- a/test/code_size/test_codesize_cxx_noexcept.json +++ b/test/code_size/test_codesize_cxx_noexcept.json @@ -1,10 +1,10 @@ { "a.out.js": 19754, "a.out.js.gz": 8162, - "a.out.nodebug.wasm": 131921, - "a.out.nodebug.wasm.gz": 50229, - "total": 151675, - "total_gz": 58391, + "a.out.nodebug.wasm": 131934, + "a.out.nodebug.wasm.gz": 50245, + "total": 151688, + "total_gz": 58407, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_cxx_wasmfs.json b/test/code_size/test_codesize_cxx_wasmfs.json index 6b26f43ce03a9..3cd8ffdd333fe 100644 --- a/test/code_size/test_codesize_cxx_wasmfs.json +++ b/test/code_size/test_codesize_cxx_wasmfs.json @@ -1,10 +1,10 @@ { "a.out.js": 7143, "a.out.js.gz": 3338, - "a.out.nodebug.wasm": 169792, - "a.out.nodebug.wasm.gz": 63078, - "total": 176935, - "total_gz": 66416, + "a.out.nodebug.wasm": 169805, + "a.out.nodebug.wasm.gz": 63096, + "total": 176948, + "total_gz": 66434, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_files_wasmfs.json b/test/code_size/test_codesize_files_wasmfs.json index 64b119042fabb..3f24cb72ad314 100644 --- a/test/code_size/test_codesize_files_wasmfs.json +++ b/test/code_size/test_codesize_files_wasmfs.json @@ -1,10 +1,10 @@ { "a.out.js": 5549, "a.out.js.gz": 2591, - "a.out.nodebug.wasm": 50226, - "a.out.nodebug.wasm.gz": 18077, - "total": 55775, - "total_gz": 20668, + "a.out.nodebug.wasm": 50237, + "a.out.nodebug.wasm.gz": 18094, + "total": 55786, + "total_gz": 20685, "sent": [ "a (emscripten_date_now)", "b (emscripten_err)", diff --git a/test/code_size/test_codesize_hello_dylink.json b/test/code_size/test_codesize_hello_dylink.json index 93f20bcfcaebe..043bff9354593 100644 --- a/test/code_size/test_codesize_hello_dylink.json +++ b/test/code_size/test_codesize_hello_dylink.json @@ -1,10 +1,10 @@ { "a.out.js": 26976, "a.out.js.gz": 11458, - "a.out.nodebug.wasm": 18558, - "a.out.nodebug.wasm.gz": 9178, - "total": 45534, - "total_gz": 20636, + "a.out.nodebug.wasm": 18570, + "a.out.nodebug.wasm.gz": 9188, + "total": 45546, + "total_gz": 20646, "sent": [ "__heap_base", "__indirect_function_table", diff --git a/test/code_size/test_codesize_hello_dylink_all.json b/test/code_size/test_codesize_hello_dylink_all.json index d33b796620ca5..7b217c4cef72a 100644 --- a/test/code_size/test_codesize_hello_dylink_all.json +++ b/test/code_size/test_codesize_hello_dylink_all.json @@ -1,7 +1,7 @@ { "a.out.js": 246331, - "a.out.nodebug.wasm": 597590, - "total": 843921, + "a.out.nodebug.wasm": 597755, + "total": 844086, "sent": [ "IMG_Init", "IMG_Load", @@ -1986,6 +1986,7 @@ "_ns_flagdata", "_pthread_cleanup_pop", "_pthread_cleanup_push", + "_sbrk64", "_webgl1_match_ext_proc_address_without_suffix", "a64l", "abort", @@ -3843,6 +3844,7 @@ "$_flushlbf", "$_pthread_cleanup_pop", "$_pthread_cleanup_push", + "$_sbrk64", "$_webgl1_match_ext_proc_address_without_suffix", "$a64l", "$abort", diff --git a/test/code_size/test_codesize_mem_O3.json b/test/code_size/test_codesize_mem_O3.json index 239c688c36ffd..280add1b7afd0 100644 --- a/test/code_size/test_codesize_mem_O3.json +++ b/test/code_size/test_codesize_mem_O3.json @@ -1,10 +1,10 @@ { "a.out.js": 4399, "a.out.js.gz": 2112, - "a.out.nodebug.wasm": 5255, - "a.out.nodebug.wasm.gz": 2398, - "total": 9654, - "total_gz": 4510, + "a.out.nodebug.wasm": 5267, + "a.out.nodebug.wasm.gz": 2422, + "total": 9666, + "total_gz": 4534, "sent": [ "a (emscripten_resize_heap)" ], diff --git a/test/code_size/test_codesize_mem_O3_grow.json b/test/code_size/test_codesize_mem_O3_grow.json index 7f5b2c76a38c8..a153b653db71b 100644 --- a/test/code_size/test_codesize_mem_O3_grow.json +++ b/test/code_size/test_codesize_mem_O3_grow.json @@ -1,10 +1,10 @@ { "a.out.js": 4684, "a.out.js.gz": 2264, - "a.out.nodebug.wasm": 5256, - "a.out.nodebug.wasm.gz": 2398, - "total": 9940, - "total_gz": 4662, + "a.out.nodebug.wasm": 5268, + "a.out.nodebug.wasm.gz": 2421, + "total": 9952, + "total_gz": 4685, "sent": [ "a (emscripten_resize_heap)" ], diff --git a/test/code_size/test_codesize_mem_O3_grow_standalone.json b/test/code_size/test_codesize_mem_O3_grow_standalone.json index e8804ee0fcdfd..5ab7c9db61b1a 100644 --- a/test/code_size/test_codesize_mem_O3_grow_standalone.json +++ b/test/code_size/test_codesize_mem_O3_grow_standalone.json @@ -1,10 +1,10 @@ { "a.out.js": 4125, "a.out.js.gz": 1977, - "a.out.nodebug.wasm": 5542, - "a.out.nodebug.wasm.gz": 2580, - "total": 9667, - "total_gz": 4557, + "a.out.nodebug.wasm": 5554, + "a.out.nodebug.wasm.gz": 2599, + "total": 9679, + "total_gz": 4576, "sent": [ "args_get", "args_sizes_get", diff --git a/test/code_size/test_codesize_mem_O3_standalone.json b/test/code_size/test_codesize_mem_O3_standalone.json index f5289a0c19a05..771c7c2a476cd 100644 --- a/test/code_size/test_codesize_mem_O3_standalone.json +++ b/test/code_size/test_codesize_mem_O3_standalone.json @@ -1,10 +1,10 @@ { "a.out.js": 4058, "a.out.js.gz": 1941, - "a.out.nodebug.wasm": 5467, - "a.out.nodebug.wasm.gz": 2520, - "total": 9525, - "total_gz": 4461, + "a.out.nodebug.wasm": 5479, + "a.out.nodebug.wasm.gz": 2542, + "total": 9537, + "total_gz": 4483, "sent": [ "args_get", "args_sizes_get", diff --git a/test/code_size/test_codesize_mem_O3_standalone_lib.json b/test/code_size/test_codesize_mem_O3_standalone_lib.json index 2af368f5ef095..aa52e981c46e4 100644 --- a/test/code_size/test_codesize_mem_O3_standalone_lib.json +++ b/test/code_size/test_codesize_mem_O3_standalone_lib.json @@ -1,10 +1,10 @@ { "a.out.js": 3602, "a.out.js.gz": 1699, - "a.out.nodebug.wasm": 5234, - "a.out.nodebug.wasm.gz": 2343, - "total": 8836, - "total_gz": 4042, + "a.out.nodebug.wasm": 5246, + "a.out.nodebug.wasm.gz": 2347, + "total": 8848, + "total_gz": 4046, "sent": [], "imports": [], "exports": [ diff --git a/test/code_size/test_codesize_mem_O3_standalone_narg.json b/test/code_size/test_codesize_mem_O3_standalone_narg.json index 725124343804b..c47dcf1a48a9d 100644 --- a/test/code_size/test_codesize_mem_O3_standalone_narg.json +++ b/test/code_size/test_codesize_mem_O3_standalone_narg.json @@ -1,10 +1,10 @@ { "a.out.js": 3605, "a.out.js.gz": 1708, - "a.out.nodebug.wasm": 5260, - "a.out.nodebug.wasm.gz": 2379, - "total": 8865, - "total_gz": 4087, + "a.out.nodebug.wasm": 5272, + "a.out.nodebug.wasm.gz": 2381, + "total": 8877, + "total_gz": 4089, "sent": [ "proc_exit" ], diff --git a/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm.json b/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm.json index 9421384941395..16da3c7b71605 100644 --- a/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm.json +++ b/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm.json @@ -3,8 +3,8 @@ "a.html.gz": 321, "a.js": 4437, "a.js.gz": 2281, - "a.wasm": 8317, - "a.wasm.gz": 5660, - "total": 13208, - "total_gz": 8262 + "a.wasm": 8299, + "a.wasm.gz": 5645, + "total": 13190, + "total_gz": 8247 } diff --git a/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm2js.json b/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm2js.json index 70767589e79ba..679f7e3cb8377 100644 --- a/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm2js.json +++ b/test/code_size/test_minimal_runtime_code_size_hello_webgl2_wasm2js.json @@ -1,8 +1,8 @@ { "a.html": 346, "a.html.gz": 255, - "a.js": 18207, - "a.js.gz": 9835, - "total": 18553, - "total_gz": 10090 + "a.js": 18190, + "a.js.gz": 9818, + "total": 18536, + "total_gz": 10073 } diff --git a/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm.json b/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm.json index ad58b6d1a5ae9..8f945a8bc4984 100644 --- a/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm.json +++ b/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm.json @@ -3,8 +3,8 @@ "a.html.gz": 321, "a.js": 3975, "a.js.gz": 2123, - "a.wasm": 8317, - "a.wasm.gz": 5660, - "total": 12746, - "total_gz": 8104 + "a.wasm": 8299, + "a.wasm.gz": 5645, + "total": 12728, + "total_gz": 8089 } diff --git a/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm2js.json b/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm2js.json index 11fad0917b472..a94de51bf326e 100644 --- a/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm2js.json +++ b/test/code_size/test_minimal_runtime_code_size_hello_webgl_wasm2js.json @@ -1,8 +1,8 @@ { "a.html": 346, "a.html.gz": 255, - "a.js": 17733, - "a.js.gz": 9669, - "total": 18079, - "total_gz": 9924 + "a.js": 17717, + "a.js.gz": 9653, + "total": 18063, + "total_gz": 9908 } diff --git a/test/code_size/test_minimal_runtime_code_size_random_printf_wasm.json b/test/code_size/test_minimal_runtime_code_size_random_printf_wasm.json index 3be9e2b5bfba5..14b69b0ad7fcc 100644 --- a/test/code_size/test_minimal_runtime_code_size_random_printf_wasm.json +++ b/test/code_size/test_minimal_runtime_code_size_random_printf_wasm.json @@ -1,4 +1,4 @@ { "a.html": 12507, - "a.html.gz": 6824 + "a.html.gz": 6822 } diff --git a/test/code_size/test_unoptimized_code_size.json b/test/code_size/test_unoptimized_code_size.json index 1eed6617a859a..66ab52b4f5b01 100644 --- a/test/code_size/test_unoptimized_code_size.json +++ b/test/code_size/test_unoptimized_code_size.json @@ -6,11 +6,11 @@ "no_asserts.js": 26352, "no_asserts.js.gz": 8789, "no_asserts.wasm": 12227, - "no_asserts.wasm.gz": 6010, + "no_asserts.wasm.gz": 6008, "strict.js": 51919, "strict.js.gz": 16352, "strict.wasm": 15127, "strict.wasm.gz": 7447, "total": 174633, - "total_gz": 63064 + "total_gz": 63062 } diff --git a/test/core/test_emmalloc_trim.c b/test/core/test_emmalloc_trim.c index 571538ddf7599..1669e7c3693ce 100644 --- a/test/core/test_emmalloc_trim.c +++ b/test/core/test_emmalloc_trim.c @@ -9,10 +9,13 @@ size_t round_to_4k(size_t val){ } void print_stats(const char* title) { + /* + // Uncomment for debugging: printf("%s: dynamic heap: %zu\n", title, round_to_4k(emmalloc_dynamic_heap_size())); printf("%s: free dynamic memory: %zu\n", title, round_to_4k(emmalloc_free_dynamic_memory())); printf("%s: unclaimed heap memory: %zu\n", title, round_to_4k(emmalloc_unclaimed_heap_memory())); printf("%s: sbrk: %#zx\n", title, round_to_4k((size_t)sbrk(0))); + */ } int main() { @@ -26,29 +29,39 @@ int main() { assert(ptr2); print_stats("after alloc"); + // After having allocated memory, trim the heap. This may or may not actually + // trim (it is unspecified whether the heap is trimmed after initial mallocs) did_free = emmalloc_trim(0); - assert(did_free); + // But print for posterity whether we did actually trim. printf("1st trim: did_free=%d\n", did_free); print_stats("1"); + // Trimming again back-to-back after a trim should not trim more. did_free = emmalloc_trim(0); - assert(!did_free); printf("2nd trim: did_free=%d\n", did_free); print_stats("2"); - free(ptr2); + assert(!did_free); - did_free = emmalloc_trim(100000); - assert(did_free); + // Free one block. That should allow memory to be trimmed. + free(ptr2); + did_free = emmalloc_trim(0); printf("3rd trim: did_free=%d\n", did_free); print_stats("3"); + assert(did_free); + // Free second block. That should also allow more memory to be trimmed. + // Try trimming by leaving a padding. + free(ptr); did_free = emmalloc_trim(100000); - assert(!did_free); printf("4th trim: did_free=%d\n", did_free); print_stats("4"); + assert(did_free); + assert(emmalloc_free_dynamic_memory() >= 100000); + // Now try re-trimming by also discarding the padding. This should trim + // more. did_free = emmalloc_trim(0); - assert(did_free); printf("5th trim: did_free=%d\n", did_free); print_stats("5"); + assert(did_free); } diff --git a/test/core/test_emmalloc_trim.out b/test/core/test_emmalloc_trim.out index fe8877981081c..a4bce70eb8a7f 100644 --- a/test/core/test_emmalloc_trim.out +++ b/test/core/test_emmalloc_trim.out @@ -1,34 +1,6 @@ heap size: 134217728 -init: dynamic heap: 4096 -init: free dynamic memory: 4096 -init: unclaimed heap memory: 2147348480 -init: sbrk: 0x12000 -after alloc: dynamic heap: 37752832 -after alloc: free dynamic memory: 4096 -after alloc: unclaimed heap memory: 2109599744 -after alloc: sbrk: 0x2412000 1st trim: did_free=1 -1: dynamic heap: 37752832 -1: free dynamic memory: 0 -1: unclaimed heap memory: 2109599744 -1: sbrk: 0x2412000 2nd trim: did_free=0 -2: dynamic heap: 37752832 -2: free dynamic memory: 0 -2: unclaimed heap memory: 2109599744 -2: sbrk: 0x2412000 3rd trim: did_free=1 -3: dynamic heap: 33656832 -3: free dynamic memory: 102400 -3: unclaimed heap memory: 2109599744 -3: sbrk: 0x2412000 -4th trim: did_free=0 -4: dynamic heap: 33656832 -4: free dynamic memory: 102400 -4: unclaimed heap memory: 2109599744 -4: sbrk: 0x2412000 +4th trim: did_free=1 5th trim: did_free=1 -5: dynamic heap: 33558528 -5: free dynamic memory: 0 -5: unclaimed heap memory: 2109599744 -5: sbrk: 0x2412000 diff --git a/test/test_core.py b/test/test_core.py index 133c7d6aa241f..7e19ce50d9057 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -938,7 +938,6 @@ def test_emmalloc_memory_statistics(self): @no_4gb('output is sensitive to absolute data layout') @no_asan('ASan does not support custom memory allocators') @no_lsan('LSan does not support custom memory allocators') - @disabled('https://github.com/emscripten-core/emscripten/issues/23343') def test_emmalloc_trim(self): self.set_setting('MALLOC', 'emmalloc') self.cflags += ['-sINITIAL_MEMORY=128MB', '-sALLOW_MEMORY_GROWTH', '-sMAXIMUM_MEMORY=2147418112']