diff --git a/ChangeLog.md b/ChangeLog.md index 1a7d222f5b48..8e7185a0c4b5 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -22,6 +22,17 @@ See docs/process.md for more on how version tagging works. ----------------------- - Add support for `-sEXPORT_ES6`/`*.mjs` on Node.js. (#17915) - Idle workers in a PThread pool no longer prevent Node.js app from exiting. (#18227) +- The default `STACK_SIZE` was reduced from 5MB to 64KB. Projects that use more + than 64Kb of stack will now need specify `-sSTACK_SIZE` at link time. For + example, `-sSTACK_SIZE=5MB` can be used to restore the previous behaviour. + To aid in debugging, as of #18154, we now also place the stack first in memory + in debug builds so that overflows will be immediately detected, and result in + runtime errors. This change brings emscripten into line with `wasm-ld` and + wasi-sdk defaults, and also reduces memory usage by default. In general, + WebAssembly stack usage should be lower than on other platforms since a lot of + state normally stored on the stack is hidden within the runtime and does not + occupy linear memory at all. The default for `DEFAULT_PTHREAD_STACK_SIZE` was + also reduced from 2MB to 64KB to match. 3.1.26 - 11/17/22 ----------------- @@ -48,6 +59,7 @@ See docs/process.md for more on how version tagging works. overflow will trap rather corrupting global data first). This should not be a user-visible change (unless your program does something very odd such depending on the specific location of stack data in memory). (#18154) +- Add support for `-sEXPORT_ES6`/`*.mjs` on Node.js. (#17915) 3.1.25 - 11/08/22 ----------------- diff --git a/src/library.js b/src/library.js index 387d3980b45b..3329bc0e25d1 100644 --- a/src/library.js +++ b/src/library.js @@ -3139,12 +3139,14 @@ mergeInto(LibraryManager.library, { #if STACK_OVERFLOW_CHECK // Used by wasm-emscripten-finalize to implement STACK_OVERFLOW_CHECK __handle_stack_overflow__sig: 'vp', - __handle_stack_overflow__deps: ['emscripten_stack_get_base'], + __handle_stack_overflow__deps: ['emscripten_stack_get_base', 'emscripten_stack_get_end', '$ptrToString'], __handle_stack_overflow: function(requested) { requested = requested >>> 0; + var base = _emscripten_stack_get_base(); + var end = _emscripten_stack_get_end(); abort('stack overflow (Attempt to set SP to ' + ptrToString(requested) + - ', with stack limits [' + ptrToString(_emscripten_stack_get_end()) + - ' - ' + ptrToString(_emscripten_stack_get_base()) + '])'); + ', with stack limits [' + ptrToString(end) + ' - ' + ptrToString(base) + + ']). If you require more stack space build with -sSTACK_SIZE='); }, #endif diff --git a/src/settings.js b/src/settings.js index b63c29c8ee65..9ec1915fc230 100644 --- a/src/settings.js +++ b/src/settings.js @@ -110,7 +110,7 @@ var MEM_INIT_METHOD = false; // assertions are on, we will assert on not exceeding this, otherwise, // it will fail silently. // [link] -var STACK_SIZE = 5*1024*1024; +var STACK_SIZE = 64*1024; // What malloc()/free() to use, out of // * dlmalloc - a powerful general-purpose malloc @@ -1595,7 +1595,7 @@ var PTHREAD_POOL_DELAY_LOAD = false; // those that have their addresses taken, or ones that are too large to fit as // local vars in wasm code. // [link] -var DEFAULT_PTHREAD_STACK_SIZE = 2*1024*1024; +var DEFAULT_PTHREAD_STACK_SIZE = 64*1024; // True when building with --threadprofiler // [link] diff --git a/test/browser/test_sdl_create_rgb_surface_from.c b/test/browser/test_sdl_create_rgb_surface_from.c index 1349127c542a..9a4cee8865e1 100644 --- a/test/browser/test_sdl_create_rgb_surface_from.c +++ b/test/browser/test_sdl_create_rgb_surface_from.c @@ -12,25 +12,24 @@ #define width 600 #define height 450 +uint8_t pixels[width * height * 4]; int main() { - - uint8_t pixels[width * height * 4]; uint8_t *end = pixels + width * height * 4; uint8_t *pixel = pixels; SDL_Rect rect = {0, 0, width, height}; while (pixel != end) { - *pixel = (pixel - pixels) * 256 / (width * height * 4); - pixel++; + *pixel = (pixel - pixels) * 256 / (width * height * 4); + pixel++; } SDL_Init(SDL_INIT_VIDEO); SDL_Surface *screen = SDL_SetVideoMode(width, height, 32, SDL_HWSURFACE); - SDL_Surface *image = SDL_CreateRGBSurfaceFrom(pixels, width, height, 32, width * 4, - 0x000000ff, - 0x0000ff00, - 0x00ff0000, + SDL_Surface *image = SDL_CreateRGBSurfaceFrom(pixels, width, height, 32, width * 4, + 0x000000ff, + 0x0000ff00, + 0x00ff0000, 0xff000000); SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, 255, 0, 0)); @@ -40,6 +39,5 @@ int main() { printf("There should be a red to white gradient\n"); SDL_Quit(); - return 0; } diff --git a/test/core/test_emmalloc_memory_statistics.cpp b/test/core/test_emmalloc_memory_statistics.cpp index 3e76af71705e..42750a3109a8 100644 --- a/test/core/test_emmalloc_memory_statistics.cpp +++ b/test/core/test_emmalloc_memory_statistics.cpp @@ -2,30 +2,29 @@ #include template -T round_to_4k(T val) { - return (T)(((size_t)val + 4095) & ~4095); +T round_to_4k(T val){ + return (T)(((size_t)val + 4095) & ~4095); } -int main() { - void *ptr = malloc(32*1024*1024); - void *ptr2 = malloc(4*1024*1024); - void *ptr3 = malloc(64*1024*1024); - void *ptr4 = malloc(16*1024); - void *ptr5 = malloc(2*1024*1024); - printf("%ld\n", (long)(ptr && ptr2 && ptr3 && ptr4 && ptr5)); - free(ptr2); - free(ptr4); - printf("validate_memory_regions: %d\n", emmalloc_validate_memory_regions()); - printf("dynamic_heap_size: %zu\n", emmalloc_dynamic_heap_size()); - printf("free_dynamic_memory: %zu\n", emmalloc_free_dynamic_memory()); - size_t numFreeMemoryRegions = 0; - size_t freeMemorySizeMap[32]; - numFreeMemoryRegions = emmalloc_compute_free_dynamic_memory_fragmentation_map(freeMemorySizeMap); - printf("numFreeMemoryRegions: %zu\n", numFreeMemoryRegions); - for (int i = 0; i < 32; ++i) { - printf("%zu ", freeMemorySizeMap[i]); - } - printf("\n"); - printf("unclaimed_heap_memory: %zu\n", round_to_4k(emmalloc_unclaimed_heap_memory())); - return 0; +int main() +{ + void *ptr = malloc(32*1024*1024); + void *ptr2 = malloc(4*1024*1024); + void *ptr3 = malloc(64*1024*1024); + void *ptr4 = malloc(16*1024); + void *ptr5 = malloc(2*1024*1024); + printf("valid allocs: %d\n", (int)(ptr && ptr2 && ptr3 && ptr4 && ptr5)); + free(ptr2); + free(ptr4); + printf("emmalloc_validate_memory_regions: %d\n", emmalloc_validate_memory_regions()); + printf("emmalloc_dynamic_heap_size : %zu\n", emmalloc_dynamic_heap_size()); + printf("emmalloc_free_dynamic_memory : %zu\n", emmalloc_free_dynamic_memory()); + size_t numFreeMemoryRegions = 0; + size_t freeMemorySizeMap[32]; + numFreeMemoryRegions = emmalloc_compute_free_dynamic_memory_fragmentation_map(freeMemorySizeMap); + printf("numFreeMemoryRegions: %zu\n", numFreeMemoryRegions); + for(int i = 0; i < 32; ++i) + printf("%zu ", freeMemorySizeMap[i]); + printf("\n"); + printf("emmalloc_unclaimed_heap_memory : %zu\n", round_to_4k(emmalloc_unclaimed_heap_memory())); } diff --git a/test/core/test_emmalloc_memory_statistics.out b/test/core/test_emmalloc_memory_statistics.out index 85b343f92d67..670cb4e1f2f4 100644 --- a/test/core/test_emmalloc_memory_statistics.out +++ b/test/core/test_emmalloc_memory_statistics.out @@ -1,7 +1,7 @@ -1 -validate_memory_regions: 0 -dynamic_heap_size: 106971424 -free_dynamic_memory: 4210892 +valid allocs: 1 +emmalloc_validate_memory_regions: 0 +emmalloc_dynamic_heap_size : 106971424 +emmalloc_free_dynamic_memory : 4210892 numFreeMemoryRegions: 3 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 -unclaimed_heap_memory: 21999616 +emmalloc_unclaimed_heap_memory : 27176960 diff --git a/test/core/test_emmalloc_memory_statistics64.out b/test/core/test_emmalloc_memory_statistics64.out index 15c9c34325c4..e3ca41e1f79b 100644 --- a/test/core/test_emmalloc_memory_statistics64.out +++ b/test/core/test_emmalloc_memory_statistics64.out @@ -1,7 +1,7 @@ -1 -validate_memory_regions: 0 -dynamic_heap_size: 106971712 -free_dynamic_memory: 4211104 +valid allocs: 1 +emmalloc_validate_memory_regions: 0 +emmalloc_dynamic_heap_size : 106971712 +emmalloc_free_dynamic_memory : 4211104 numFreeMemoryRegions: 3 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 -unclaimed_heap_memory: 21999616 +emmalloc_unclaimed_heap_memory : 27176960 diff --git a/test/core/test_emmalloc_trim.out b/test/core/test_emmalloc_trim.out index efefc75eda11..160a42927987 100644 --- a/test/core/test_emmalloc_trim.out +++ b/test/core/test_emmalloc_trim.out @@ -1,35 +1,35 @@ heap size: 134217728 dynamic heap 0: 4096 free dynamic memory 0: 4096 -unclaimed heap memory 0: 2142175232 -sbrk 0: 0x501000 +unclaimed heap memory 0: 2147352576 +sbrk 0: 0x11000 1 dynamic heap 1: 37752832 free dynamic memory 1: 4096 -unclaimed heap memory 1: 2104426496 -sbrk 1: 0x2901000 +unclaimed heap memory 1: 2109603840 +sbrk 1: 0x2411000 1st trim: 1 dynamic heap 1: 37752832 free dynamic memory 1: 0 -unclaimed heap memory 1: 2104426496 -sbrk 1: 0x2901000 +unclaimed heap memory 1: 2109603840 +sbrk 1: 0x2411000 2nd trim: 0 dynamic heap 2: 37752832 free dynamic memory 2: 0 -unclaimed heap memory 2: 2104426496 -sbrk 2: 0x2901000 +unclaimed heap memory 2: 2109603840 +sbrk 2: 0x2411000 3rd trim: 1 dynamic heap 3: 33656832 free dynamic memory 3: 102400 -unclaimed heap memory 3: 2104426496 -sbrk 3: 0x2901000 +unclaimed heap memory 3: 2109603840 +sbrk 3: 0x2411000 4th trim: 0 dynamic heap 4: 33656832 free dynamic memory 4: 102400 -unclaimed heap memory 4: 2104426496 -sbrk 4: 0x2901000 +unclaimed heap memory 4: 2109603840 +sbrk 4: 0x2411000 5th trim: 1 dynamic heap 5: 33558528 free dynamic memory 5: 0 -unclaimed heap memory 5: 2104426496 -sbrk 5: 0x2901000 +unclaimed heap memory 5: 2109603840 +sbrk 5: 0x2411000 diff --git a/test/core/test_memcpy3.c b/test/core/test_memcpy3.c index 6c2abb19731c..630793a54563 100644 --- a/test/core/test_memcpy3.c +++ b/test/core/test_memcpy3.c @@ -26,7 +26,7 @@ int main() { #define RUN(type) \ { \ - type buffer[TOTAL]; \ + static type buffer[TOTAL]; \ volatile int seed = 123; \ TEST(1, type); \ TEST(2, type); \ diff --git a/test/core/test_memorygrowth_geometric_step.out b/test/core/test_memorygrowth_geometric_step.out index 4cb463c65374..ee8918d5c5b2 100644 --- a/test/core/test_memorygrowth_geometric_step.out +++ b/test/core/test_memorygrowth_geometric_step.out @@ -1,2 +1,2 @@ Heap size before allocation: 16777216 -Ptr: 1, value: 16843009, Heap size now: 101777408 (increase: 85000192 bytes) \ No newline at end of file +Ptr: 1, value: 16843009, Heap size now: 96600064 (increase: 79822848 bytes) diff --git a/test/core/test_memset.c b/test/core/test_memset.c index cb48a8fa3f15..5c75fb8156f4 100644 --- a/test/core/test_memset.c +++ b/test/core/test_memset.c @@ -26,7 +26,7 @@ int main() { #define RUN(type) \ { \ - type buffer[TOTAL]; \ + static type buffer[TOTAL]; \ volatile int seed = 123; \ TEST(1, type); \ TEST(2, type); \ diff --git a/test/fs/test_mmap.c b/test/fs/test_mmap.c index 77e80cfe0bfd..1f697a444413 100644 --- a/test/fs/test_mmap.c +++ b/test/fs/test_mmap.c @@ -180,11 +180,12 @@ void test_mmap_shared_with_offset() { assert(fd >= 0); size_t offset = sysconf(_SC_PAGE_SIZE) * 2; - char buffer[offset + 33]; - memset(buffer, 0, offset + 33); - fread(buffer, 1, offset + 32, fd); + char buffer[33]; + memset(buffer, 0, 33); + fseek(fd, offset, SEEK_SET); + fread(buffer, 1, 32, fd); // expect text written from mmap operation to appear at offset in the file - printf("yolo/sharedoffset.txt content=%s %zu\n", buffer + offset, offset); + printf("yolo/sharedoffset.txt content=%s %zu\n", buffer, offset); fclose(fd); } } diff --git a/test/pthread/test_pthread_create_pthread.cpp b/test/pthread/test_pthread_create_pthread.cpp index a32bb15031b5..695f22e15bf6 100644 --- a/test/pthread/test_pthread_create_pthread.cpp +++ b/test/pthread/test_pthread_create_pthread.cpp @@ -32,6 +32,7 @@ static void *thread1_start(void *arg) return NULL; } +#define DEFAULT_STACK_SIZE (64*1024) int main() { pthread_t thr; @@ -43,7 +44,7 @@ int main() void *stack_addr; pthread_attr_getstack(&attr, &stack_addr, &stack_size); printf("stack_size: %d, stack_addr: %p\n", (int)stack_size, stack_addr); - if (stack_size != 2*1024*1024 || stack_addr == NULL) + if (stack_size != DEFAULT_STACK_SIZE || stack_addr == NULL) result = -100; // Report failure. pthread_join(thr, NULL); diff --git a/test/test_browser.py b/test/test_browser.py index d4fc007e87cc..4132dfba03d2 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -1283,6 +1283,9 @@ def test_webgl_context_attributes(self): temp_filepath = os.path.basename(filepath) shutil.copyfile(filepath, temp_filepath) + # testAntiAliasing uses a window-sized buffer on the stack + self.set_setting('STACK_SIZE', '1MB') + # perform tests with attributes activated self.btest_exit('test_webgl_context_attributes_glut.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglut', '-lGLEW']) self.btest_exit('test_webgl_context_attributes_sdl.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lSDL', '-lGLEW']) @@ -3316,7 +3319,7 @@ def test_async_2(self): # Error.stackTraceLimit default to 10 in chrome but this test relies on more # than 40 stack frames being reported. create_file('pre.js', 'Error.stackTraceLimit = 80;\n') - self.btest_exit('browser/async_2.cpp', args=['-O3', '--pre-js', 'pre.js', '-sASYNCIFY']) + self.btest_exit('browser/async_2.cpp', args=['-O3', '--pre-js', 'pre.js', '-sASYNCIFY', '-sSTACK_SIZE=1MB']) def test_async_virtual(self): for opts in [0, 3]: diff --git a/test/test_core.py b/test/test_core.py index 5d5b331fb224..bbd644d7a748 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -5333,6 +5333,7 @@ def test_printf(self): # needs to flush stdio streams self.emcc_args.append('-Wno-format') self.set_setting('EXIT_RUNTIME') + self.set_setting('STACK_SIZE', '1MB') self.do_run_in_out_file_test('printf/test.c') def test_printf_2(self): @@ -6608,7 +6609,7 @@ def test_sse2(self): self.run_process([shared.CLANG_CXX, src, '-msse2', '-Wno-argument-outside-range', '-o', 'test_sse2', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_sse2', stdout=PIPE).stdout - self.emcc_args += ['-I' + test_file('sse'), '-msse2', '-Wno-argument-outside-range'] + self.emcc_args += ['-I' + test_file('sse'), '-msse2', '-Wno-argument-outside-range', '-sSTACK_SIZE=1MB'] self.maybe_closure() self.do_runf(src, native_result) @@ -6652,7 +6653,7 @@ def test_sse4_1(self): self.run_process([shared.CLANG_CXX, src, '-msse4.1', '-Wno-argument-outside-range', '-o', 'test_sse4_1', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_sse4_1', stdout=PIPE).stdout - self.emcc_args += ['-I' + test_file('sse'), '-msse4.1', '-Wno-argument-outside-range'] + self.emcc_args += ['-I' + test_file('sse'), '-msse4.1', '-Wno-argument-outside-range', '-sSTACK_SIZE=1MB'] self.maybe_closure() self.do_runf(src, native_result) @@ -6683,7 +6684,7 @@ def test_avx(self): self.run_process([shared.CLANG_CXX, src, '-mavx', '-Wno-argument-outside-range', '-o', 'test_avx', '-D_CRT_SECURE_NO_WARNINGS=1'] + clang_native.get_clang_native_args(), stdout=PIPE) native_result = self.run_process('./test_avx', stdout=PIPE).stdout - self.emcc_args += ['-I' + test_file('sse'), '-mavx', '-Wno-argument-outside-range'] + self.emcc_args += ['-I' + test_file('sse'), '-mavx', '-Wno-argument-outside-range', '-sSTACK_SIZE=1MB'] self.maybe_closure() self.do_runf(src, native_result) diff --git a/test/test_other.py b/test/test_other.py index 562eca4c9fbf..6b1cd221197c 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2652,6 +2652,9 @@ def test_embind(self, extra_args): '--pre-js', test_file('embind/test.pre.js'), '--post-js', test_file('embind/test.post.js'), '-sWASM_ASYNC_COMPILATION=0', + # This test uses a `CustomSmartPtr` class which has 1MB of data embedded in + # it which means we need more stack space than normal. + '-sTOTAL_STACK=2MB', '-sIN_TEST_HARNESS'] + args) if '-sDYNAMIC_EXECUTION=0' in args: @@ -5850,7 +5853,7 @@ def test_massive_alloc(self, wasm): # just care about message regarding allocating over 1GB of memory output = self.run_js('a.out.js') if not wasm: - self.assertContained('Warning: Enlarging memory arrays, this is not fast! 16777216,1473314816\n', output) + self.assertContained('Warning: Enlarging memory arrays, this is not fast! 16777216,1468137472\n', output) def test_failing_alloc(self): for pre_fail, post_fail, opts in [