From d55182fb61f17003f4e85cc3fff52b7ffc09c462 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 19 Aug 2025 11:07:52 -0700 Subject: [PATCH] Make addRunDependency/removeRunDependency options This saves on code size is configurations where its not needed. i.e. in MODULARIZE mode where we use `await` to wait for instantiation, or in sync instantiation is used. --- ChangeLog.md | 3 ++ src/lib/libcore.js | 2 +- src/lib/libdylink.js | 2 +- src/lib/libfs_shared.js | 2 + src/lib/liblz4.js | 2 +- src/lib/libpthread.js | 4 ++ src/postamble.js | 6 ++- src/preamble.js | 4 +- test/code_size/test_codesize_cxx_ctors2.json | 4 +- test/code_size/test_codesize_cxx_wasmfs.json | 4 +- test/code_size/test_codesize_hello_O0.json | 4 +- test/code_size/test_codesize_hello_O1.json | 4 +- test/code_size/test_codesize_hello_O2.json | 4 +- test/code_size/test_codesize_hello_O3.json | 4 +- test/code_size/test_codesize_hello_Os.json | 4 +- .../code_size/test_codesize_hello_dylink.json | 8 ++-- .../test_codesize_hello_dylink_all.json | 6 +-- .../test_codesize_hello_single_file.json | 2 +- .../code_size/test_codesize_hello_wasmfs.json | 4 +- ...esize_libcxxabi_message_O3_standalone.json | 4 +- .../test_codesize_mem_O3_standalone_narg.json | 4 +- ..._codesize_mem_O3_standalone_narg_flto.json | 4 +- test/code_size/test_codesize_minimal_esm.json | 8 ++-- .../code_size/test_unoptimized_code_size.json | 14 +++--- .../test_codesize_minimal_O0.expected.js | 46 +++++++++---------- test/test_other.py | 1 + tools/link.py | 6 ++- 27 files changed, 87 insertions(+), 73 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index ab027eb37c5fb..45967c9956f15 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,9 @@ See docs/process.md for more on how version tagging works. 4.0.14 (in development) ----------------------- +- The `addRunDependency` and `removeRunDependency` API are now optional and need + to be included and/or exported using, for example, + `DEFAULT_LIBRARY_FUNCS_TO_INCLUDE` or `EXPORTED_RUNTIME_METHODS`. (#24974) - The `LOAD_SOURCE_MAP` setting was made an internal setting. This was always an internal detail of the sanitizers, which is enabled automatically when needed, so setting it explicitly should never be needed. (#24967) diff --git a/src/lib/libcore.js b/src/lib/libcore.js index 2bd7a037183e4..b47b597808d2f 100644 --- a/src/lib/libcore.js +++ b/src/lib/libcore.js @@ -2293,7 +2293,7 @@ addToLibrary({ $runDependencyWatcher: null, #endif - $addRunDependency__deps: ['$runDependencies', + $addRunDependency__deps: ['$runDependencies', '$removeRunDependency', #if ASSERTIONS '$runDependencyTracking', '$runDependencyWatcher', diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index c7da0f696bf80..71a484452f552 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -1174,7 +1174,7 @@ var LibraryDylink = { }, $loadDylibs__internal: true, - $loadDylibs__deps: ['$loadDynamicLibrary', '$reportUndefinedSymbols'], + $loadDylibs__deps: ['$loadDynamicLibrary', '$reportUndefinedSymbols', '$addRunDependency', '$removeRunDependency'], $loadDylibs: () => { if (!dynamicLibraries.length) { #if DYLINK_DEBUG diff --git a/src/lib/libfs_shared.js b/src/lib/libfs_shared.js index b44ca11e7ef14..09f9e8190008c 100644 --- a/src/lib/libfs_shared.js +++ b/src/lib/libfs_shared.js @@ -55,6 +55,8 @@ addToLibrary({ '$PATH_FS', '$FS_createDataFile', '$getUniqueRunDependency', + '$addRunDependency', + '$removeRunDependency', '$FS_handledByPreloadPlugin', ], $FS_preloadFile: async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => { diff --git a/src/lib/liblz4.js b/src/lib/liblz4.js index 3f466565aae06..8e4a85dc6748b 100644 --- a/src/lib/liblz4.js +++ b/src/lib/liblz4.js @@ -6,7 +6,7 @@ #if LZ4 addToLibrary({ - $LZ4__deps: ['$FS', '$preloadPlugins', '$getUniqueRunDependency'], + $LZ4__deps: ['$FS', '$preloadPlugins', '$getUniqueRunDependency', '$addRunDependency', '$removeRunDependency'], $LZ4: { DIR_MODE: {{{ cDefs.S_IFDIR | 0o777 }}}, FILE_MODE: {{{ cDefs.S_IFREG | 0o777 }}}, diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js index b006d07e8aff9..47c3b4eb6a919 100644 --- a/src/lib/libpthread.js +++ b/src/lib/libpthread.js @@ -69,6 +69,10 @@ var LibraryPThread = { '$addOnPreRun', #if MAIN_MODULE '$markAsFinished', +#endif +#if !MINIMAL_RUNTIME && PTHREAD_POOL_SIZE && !PTHREAD_POOL_DELAY_LOAD + '$addRunDependency', + '$removeRunDependency', #endif '$spawnThread', '_emscripten_thread_free_data', diff --git a/src/postamble.js b/src/postamble.js index 463de3182f2f9..5bea33d056f77 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -36,7 +36,9 @@ var mainArgs = undefined; {{{ asyncIf(ASYNCIFY == 2) }}}function callMain() { #endif #if ASSERTIONS +#if '$runDependencies' in addedLibraryItems assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])'); +#endif assert(typeof onPreRuns === 'undefined' || onPreRuns.length == 0, 'cannot call main when preRun functions remain to be called'); #endif @@ -133,7 +135,7 @@ function run(args = arguments_) { function run() { #endif -#if !BOOTSTRAPPING_STRUCT_INFO +#if '$runDependencies' in addedLibraryItems if (runDependencies > 0) { #if RUNTIME_DEBUG dbg('run() called, but dependencies remain, so not running'); @@ -159,7 +161,7 @@ function run() { preRun(); -#if !BOOTSTRAPPING_STRUCT_INFO +#if '$runDependencies' in addedLibraryItems // a preRun added a dependency, run will be called later if (runDependencies > 0) { #if RUNTIME_DEBUG diff --git a/src/preamble.js b/src/preamble.js index f85372cf03618..007ba92645df2 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -754,12 +754,12 @@ function getWasmImports() { #if DECLARE_ASM_MODULE_EXPORTS assignWasmExports(wasmExports); #endif -#if WASM_ASYNC_COMPILATION +#if WASM_ASYNC_COMPILATION && !MODULARIZE removeRunDependency('wasm-instantiate'); #endif return wasmExports; } -#if WASM_ASYNC_COMPILATION +#if WASM_ASYNC_COMPILATION && !MODULARIZE addRunDependency('wasm-instantiate'); #endif diff --git a/test/code_size/test_codesize_cxx_ctors2.json b/test/code_size/test_codesize_cxx_ctors2.json index e1e87786f233b..5e62ec3fe226a 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": 19731, - "a.out.js.gz": 8149, + "a.out.js.gz": 8148, "a.out.nodebug.wasm": 128935, "a.out.nodebug.wasm.gz": 48881, "total": 148666, - "total_gz": 57030, + "total_gz": 57029, "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 f9fa20ca72741..8a347b8c5141b 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": 3340, + "a.out.js.gz": 3337, "a.out.nodebug.wasm": 169796, "a.out.nodebug.wasm.gz": 63083, "total": 176939, - "total_gz": 66423, + "total_gz": 66420, "sent": [ "__cxa_throw", "_abort_js", diff --git a/test/code_size/test_codesize_hello_O0.json b/test/code_size/test_codesize_hello_O0.json index 7527a9950e0f2..67f643f67c28d 100644 --- a/test/code_size/test_codesize_hello_O0.json +++ b/test/code_size/test_codesize_hello_O0.json @@ -1,10 +1,10 @@ { "a.out.js": 22497, - "a.out.js.gz": 8330, + "a.out.js.gz": 8329, "a.out.nodebug.wasm": 15143, "a.out.nodebug.wasm.gz": 7452, "total": 37640, - "total_gz": 15782, + "total_gz": 15781, "sent": [ "fd_write" ], diff --git a/test/code_size/test_codesize_hello_O1.json b/test/code_size/test_codesize_hello_O1.json index 62ce2a0c3fab7..4e53d67be8d68 100644 --- a/test/code_size/test_codesize_hello_O1.json +++ b/test/code_size/test_codesize_hello_O1.json @@ -1,10 +1,10 @@ { "a.out.js": 6411, - "a.out.js.gz": 2477, + "a.out.js.gz": 2478, "a.out.nodebug.wasm": 2675, "a.out.nodebug.wasm.gz": 1491, "total": 9086, - "total_gz": 3968, + "total_gz": 3969, "sent": [ "fd_write" ], diff --git a/test/code_size/test_codesize_hello_O2.json b/test/code_size/test_codesize_hello_O2.json index 7bae54abde748..2ddadfd5c7ae7 100644 --- a/test/code_size/test_codesize_hello_O2.json +++ b/test/code_size/test_codesize_hello_O2.json @@ -1,10 +1,10 @@ { "a.out.js": 4369, - "a.out.js.gz": 2145, + "a.out.js.gz": 2146, "a.out.nodebug.wasm": 1979, "a.out.nodebug.wasm.gz": 1157, "total": 6348, - "total_gz": 3302, + "total_gz": 3303, "sent": [ "fd_write" ], diff --git a/test/code_size/test_codesize_hello_O3.json b/test/code_size/test_codesize_hello_O3.json index 95e299cd9dc81..1e497bc59fb0b 100644 --- a/test/code_size/test_codesize_hello_O3.json +++ b/test/code_size/test_codesize_hello_O3.json @@ -1,10 +1,10 @@ { "a.out.js": 4311, - "a.out.js.gz": 2102, + "a.out.js.gz": 2104, "a.out.nodebug.wasm": 1733, "a.out.nodebug.wasm.gz": 980, "total": 6044, - "total_gz": 3082, + "total_gz": 3084, "sent": [ "a (fd_write)" ], diff --git a/test/code_size/test_codesize_hello_Os.json b/test/code_size/test_codesize_hello_Os.json index b6eddff120b2e..128a92afd1599 100644 --- a/test/code_size/test_codesize_hello_Os.json +++ b/test/code_size/test_codesize_hello_Os.json @@ -1,10 +1,10 @@ { "a.out.js": 4311, - "a.out.js.gz": 2102, + "a.out.js.gz": 2104, "a.out.nodebug.wasm": 1723, "a.out.nodebug.wasm.gz": 985, "total": 6034, - "total_gz": 3087, + "total_gz": 3089, "sent": [ "a (fd_write)" ], diff --git a/test/code_size/test_codesize_hello_dylink.json b/test/code_size/test_codesize_hello_dylink.json index f4aefa9af7478..95ada301d2226 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": 27002, - "a.out.js.gz": 11463, + "a.out.js": 27001, + "a.out.js.gz": 11459, "a.out.nodebug.wasm": 18561, "a.out.nodebug.wasm.gz": 9167, - "total": 45563, - "total_gz": 20630, + "total": 45562, + "total_gz": 20626, "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 048a52c964999..fc84e23ca81bc 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": 246665, - "a.out.nodebug.wasm": 597720, - "total": 844385, + "a.out.js": 246666, + "a.out.nodebug.wasm": 597809, + "total": 844475, "sent": [ "IMG_Init", "IMG_Load", diff --git a/test/code_size/test_codesize_hello_single_file.json b/test/code_size/test_codesize_hello_single_file.json index 04fb309d10f67..99dfe30a82b3c 100644 --- a/test/code_size/test_codesize_hello_single_file.json +++ b/test/code_size/test_codesize_hello_single_file.json @@ -1,6 +1,6 @@ { "a.out.js": 6615, - "a.out.js.gz": 3612, + "a.out.js.gz": 3613, "sent": [ "a (fd_write)" ] diff --git a/test/code_size/test_codesize_hello_wasmfs.json b/test/code_size/test_codesize_hello_wasmfs.json index 95e299cd9dc81..1e497bc59fb0b 100644 --- a/test/code_size/test_codesize_hello_wasmfs.json +++ b/test/code_size/test_codesize_hello_wasmfs.json @@ -1,10 +1,10 @@ { "a.out.js": 4311, - "a.out.js.gz": 2102, + "a.out.js.gz": 2104, "a.out.nodebug.wasm": 1733, "a.out.nodebug.wasm.gz": 980, "total": 6044, - "total_gz": 3082, + "total_gz": 3084, "sent": [ "a (fd_write)" ], diff --git a/test/code_size/test_codesize_libcxxabi_message_O3_standalone.json b/test/code_size/test_codesize_libcxxabi_message_O3_standalone.json index 4c8b4d011af0f..02bfa94c54628 100644 --- a/test/code_size/test_codesize_libcxxabi_message_O3_standalone.json +++ b/test/code_size/test_codesize_libcxxabi_message_O3_standalone.json @@ -1,10 +1,10 @@ { "a.out.js": 3605, - "a.out.js.gz": 1714, + "a.out.js.gz": 1713, "a.out.nodebug.wasm": 132, "a.out.nodebug.wasm.gz": 140, "total": 3737, - "total_gz": 1854, + "total_gz": 1853, "sent": [ "proc_exit" ], 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 bd0cd9d9670a2..15ead1421988c 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": 1714, + "a.out.js.gz": 1713, "a.out.nodebug.wasm": 5267, "a.out.nodebug.wasm.gz": 2364, "total": 8872, - "total_gz": 4078, + "total_gz": 4077, "sent": [ "proc_exit" ], diff --git a/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json b/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json index c627d8f1dfcaf..cbca0311b8b5e 100644 --- a/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json +++ b/test/code_size/test_codesize_mem_O3_standalone_narg_flto.json @@ -1,10 +1,10 @@ { "a.out.js": 3605, - "a.out.js.gz": 1714, + "a.out.js.gz": 1713, "a.out.nodebug.wasm": 4080, "a.out.nodebug.wasm.gz": 2001, "total": 7685, - "total_gz": 3715, + "total_gz": 3714, "sent": [ "proc_exit" ], diff --git a/test/code_size/test_codesize_minimal_esm.json b/test/code_size/test_codesize_minimal_esm.json index d8909185eb0a7..e90a7cdc34d42 100644 --- a/test/code_size/test_codesize_minimal_esm.json +++ b/test/code_size/test_codesize_minimal_esm.json @@ -1,10 +1,10 @@ { - "a.out.js": 2522, - "a.out.js.gz": 1231, + "a.out.js": 2434, + "a.out.js.gz": 1181, "a.out.nodebug.wasm": 62, "a.out.nodebug.wasm.gz": 76, - "total": 2584, - "total_gz": 1307, + "total": 2496, + "total_gz": 1257, "sent": [], "imports": [], "exports": [ diff --git a/test/code_size/test_unoptimized_code_size.json b/test/code_size/test_unoptimized_code_size.json index 79a738c82b2de..7ace4455096db 100644 --- a/test/code_size/test_unoptimized_code_size.json +++ b/test/code_size/test_unoptimized_code_size.json @@ -1,16 +1,16 @@ { - "hello_world.js": 53807, - "hello_world.js.gz": 17007, + "hello_world.js": 53809, + "hello_world.js.gz": 17016, "hello_world.wasm": 15143, "hello_world.wasm.gz": 7452, - "no_asserts.js": 26385, + "no_asserts.js": 26387, "no_asserts.js.gz": 8797, "no_asserts.wasm": 12227, "no_asserts.wasm.gz": 6008, - "strict.js": 51845, - "strict.js.gz": 16336, + "strict.js": 51847, + "strict.js.gz": 16341, "strict.wasm": 15143, "strict.wasm.gz": 7438, - "total": 174550, - "total_gz": 63038 + "total": 174556, + "total_gz": 63052 } diff --git a/test/other/codesize/test_codesize_minimal_O0.expected.js b/test/other/codesize/test_codesize_minimal_O0.expected.js index 6735c7ab90767..d0af994ddd0fa 100644 --- a/test/other/codesize/test_codesize_minimal_O0.expected.js +++ b/test/other/codesize/test_codesize_minimal_O0.expected.js @@ -696,10 +696,33 @@ async function createWasm() { var runDependencies = 0; + + var dependenciesFulfilled = null; + var runDependencyTracking = { }; var runDependencyWatcher = null; + var removeRunDependency = (id) => { + runDependencies--; + + assert(id, 'removeRunDependency requires an ID'); + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + if (runDependencies == 0) { + if (runDependencyWatcher !== null) { + clearInterval(runDependencyWatcher); + runDependencyWatcher = null; + } + if (dependenciesFulfilled) { + var callback = dependenciesFulfilled; + dependenciesFulfilled = null; + callback(); // can add another dependenciesFulfilled + } + } + }; + + var addRunDependency = (id) => { runDependencies++; @@ -766,29 +789,6 @@ async function createWasm() { return '0x' + ptr.toString(16).padStart(8, '0'); }; - - var dependenciesFulfilled = null; - - - var removeRunDependency = (id) => { - runDependencies--; - - assert(id, 'removeRunDependency requires an ID'); - assert(runDependencyTracking[id]); - delete runDependencyTracking[id]; - if (runDependencies == 0) { - if (runDependencyWatcher !== null) { - clearInterval(runDependencyWatcher); - runDependencyWatcher = null; - } - if (dependenciesFulfilled) { - var callback = dependenciesFulfilled; - dependenciesFulfilled = null; - callback(); // can add another dependenciesFulfilled - } - } - }; - /** diff --git a/test/test_other.py b/test/test_other.py index 008c8992717d2..0a1aab66eaf2d 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -2865,6 +2865,7 @@ def test_prepost(self, no_initial_run, run_dep): # running. with open('pre.js', 'a') as f: f.write('Module["preRun"] = () => { out("add-dep"); addRunDependency("dep"); }\n') + self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', '$addRunDependency') output = self.do_runf('hello_world.c', cflags=['--pre-js', 'pre.js', '-sRUNTIME_DEBUG', '-sWASM_ASYNC_COMPILATION=0', '-O2', '--closure=1']) self.assertContained('add-dep\n', output) self.assertNotContained('hello, world!\n', output) diff --git a/tools/link.py b/tools/link.py index f57bba2d9ead0..b71154199d952 100644 --- a/tools/link.py +++ b/tools/link.py @@ -1127,11 +1127,13 @@ def limit_incoming_module_api(): settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$warnOnce'] settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$getValue', '$setValue'] - # TODO(sbc): Remove these forced dependencies. - settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$runDependencies', '$addRunDependency', '$removeRunDependency'] settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$ExitStatus'] + # Certain configurations require the removeRunDependency/addRunDependency system. + if settings.LOAD_SOURCE_MAP or (settings.WASM_ASYNC_COMPILATION and not settings.MODULARIZE) or options.preload_files: + settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$addRunDependency', '$removeRunDependency'] + if settings.ABORT_ON_WASM_EXCEPTIONS or settings.SPLIT_MODULE: settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$wasmTable']