From ed49619a4c059a4dc46e8a4c9c0be2ab3a6506e8 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 7 Feb 2025 13:10:54 +0100 Subject: [PATCH 01/23] Fix late-binding symbols with JSPI Late-binding symbols get a JS stub import that resolves the symbol and then makes an onward call. This breaks JSPI. (It also canonicalizes NaNs by round tripping them through JS). To fix this, we have to walk the import table and make wasm module stubs for each of the missing function-type symbols. These stubs will call a JS function to resolve the symbol but then insert it into a table and return control back to the wasm stub which has to make the onward call. This currently relies on --experimental-wasm-type-reflection. To avoid that, we need to parse the import table of the wasm binary manually. Also, without wasm-type-reflection, we have no way to handle the case where someone calls `loadWebAssemblyModule()` on a WebAssembly module instead of a Uint8Array. --- src/lib/libdylink.js | 210 +++++++++++++++++++++++++++-- test/core/test_dlfcn_jspi.c | 9 +- test/core/test_dlfcn_jspi.out | 3 +- test/core/test_dlfcn_jspi_side.c | 7 - test/core/test_dlfcn_jspi_side_a.c | 7 + test/core/test_dlfcn_jspi_side_b.c | 7 + test/test_core.py | 16 ++- 7 files changed, 236 insertions(+), 23 deletions(-) delete mode 100644 test/core/test_dlfcn_jspi_side.c create mode 100644 test/core/test_dlfcn_jspi_side_a.c create mode 100644 test/core/test_dlfcn_jspi_side_b.c diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 07b40c2f50a84..a1a496a65dc44 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -596,7 +596,179 @@ var LibraryDylink = { } }, #endif + $getStubImportModule__postset: ` + var stubImportModuleCache = new Map(); + `, + $getStubImportModule__deps: [ + "$generateFuncType", + "$uleb128Encode" + ], + // We need to call out to JS to resolve the function, but then make the actual + // onward call from WebAssembly. The JavaScript $resolve function is + // responsible for putting the appropriate function in the table. When the sig + // is ii, the wat for the generated module looks like this: + // + // (module + // (type $r (func )) + // (type $ii (func (param i32) (result i32))) + // (import "e" "t" (table 0 funcref)) + // (import "e" "r" (func $resolve)) + // (global $isResolved (mut i32) i32.const 0) + // + // (func (export "o") (param $p1 i32) (result i32) + // global.get $isResolved + // i32.eqz + // if + // call $resolve + // i32.const 1 + // global.set $isResolved + // end + // local.get $p1 + // i32.const 0 + // call_indirect (type $ii) + // ) + // ) + $getStubImportModule: (sig) => { + var cached = stubImportModuleCache.get(sig); + if (cached) { + return cached; + } + const bytes = [ + 0x00, 0x61, 0x73, 0x6d, // Magic number + 0x01, 0x00, 0x00, 0x00, // version 1 + 0x01, // Type section code + ]; + var typeSectionBody = [ + 0x02, // count: 2 + ]; + generateFuncType('v', typeSectionBody); + generateFuncType(sig, typeSectionBody); + uleb128Encode(typeSectionBody.length, bytes); + bytes.push(...typeSectionBody); + + // static sections + bytes.push( + // Import section + 0x02, 0x0f, + 0x02, // 2 imports + 0x01, 0x65, // e + 0x01, 0x74, // t + // funcref table with no limits + 0x01, 0x70, 0x00, 0x00, + + 0x01, 0x65, // e + 0x01, 0x72, // r + 0x00, 0x00, // function of type 0 ('v') + + // Function section + 0x03, 0x02, + 0x01, 0x01, // One function of type 1 (sig) + + // Globals section + 0x06, 0x06, + 0x01, // one global + 0x7f, 0x01, // i32 mut + 0x41, 0x00, 0x0b, // initialized to i32.const 0 + + // Export section + 0x07, 0x05, + 0x01, // one export + 0x01, 0x6f, // o + 0x00, 0x01, // function at index 1 + ); + bytes.push(0x0a); // Code section + var codeBody = [ + 0x00, // 0 locals + 0x23, 0x00, // global.get 0 + 0x45, // i32.eqz + 0x04, // if + 0x40, 0x10, 0x00, // Call function 0 + 0x41, 0x01, // i32.const 1 + 0x24, 0x00, // global.set 0 + 0x0b, // end + ]; + for (let i = 0; i < sig.length - 1; i++) { + codeBody.push(0x20, i); + } + codeBody.push( + 0x41, 0x00, // i32.const 0 + 0x11, 0x01, 0x00, // call_indirect table 0, type 0 + 0x0b // end + ); + var codeSectionBody = [0x01]; + uleb128Encode(codeBody.length, codeSectionBody); + codeSectionBody.push(...codeBody); + uleb128Encode(codeSectionBody.length, bytes); + bytes.push(...codeSectionBody); + var result = new WebAssembly.Module(new Uint8Array(bytes)); + stubImportModuleCache.set(sig, result); + return result; + }, + + $wasmSigToEmscripten: (type) => { + var lookup = {i32: 'i', i64: 'j', f32: 'f', f64: 'd', externref: 'e'}; + var sig = 'v'; + if (type.results.length) { + sig = lookup[type.results[0]]; + } + for (var v of type.parameters) { + sig += lookup[v]; + } + return sig; + }, + $getStubImportResolver: (name, sig, table, resolveSymbol) => { + return function r() { + var res = resolveSymbol(name); + if (res.orig) { + res = res.orig; + } + try { + // Attempting to call this with JS function will cause table.set() to fail + table.set(0, res); + } catch (err) { + if (!(err instanceof TypeError)) { + throw err; + } + var wrapped = convertJsFunctionToWasm(res, sig); + table.set(0, wrapped); + } + }; + }, + $addStubImports__deps: [ + "$getStubImportModule", + "$wasmSigToEmscripten", + "$getStubImportResolver" + ], + $addStubImports: (mod, stubs, resolveSymbol) => { + // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). + // TODO: Make this work without it. + for (const {module, name, kind, type} of WebAssembly.Module.imports(mod)) { + if (module !== 'env') { + continue; + } + if (kind !== 'function') { + continue; + } + if (name in wasmImports && !wasmImports[name].stub) { + continue; + } +#if !DISABLE_EXCEPTION_CATCHING || SUPPORT_LONGJMP == 'emscripten' + if (name.startsWith("invoke_")) { + // JSPI + JS exceptions probably doesn't work but maybe nobody will + // attempt stack switch inside a try block. + stubs[name] = createInvokeFunction(name.split('_')[1]); + continue; + } +#endif + var sig = wasmSigToEmscripten(type); + var mod = getStubImportModule(sig); + const t = new WebAssembly.Table({element: 'funcref', initial: 1}); + const r = getStubImportResolver(name, sig, t, resolveSymbol); + const inst = new WebAssembly.Instance(mod, {e: {t, r}}); + stubs[name] = inst.exports.o; + } + }, // Loads a side module from binary data or compiled Module. Returns the module's exports or a // promise that resolves to its exports if the loadAsync flag is set. $loadWebAssemblyModule__docs: ` @@ -613,6 +785,9 @@ var LibraryDylink = { '$updateTableMap', '$wasmTable', '$addOnPostCtor', +#if JSPI + '$addStubImports', +#endif ], $loadWebAssemblyModule: (binary, flags, libName, localScope, handle) => { #if DYLINK_DEBUG @@ -697,6 +872,7 @@ var LibraryDylink = { // to add the indirection for, without inspecting what A's imports // are. To do that here, we use a JS proxy (another option would // be to inspect the binary directly). + const stubs = {}; var proxyHandler = { get(stubs, prop) { // symbols that should be local to this module @@ -728,16 +904,20 @@ var LibraryDylink = { // Return a stub function that will resolve the symbol // when first called. if (!(prop in stubs)) { +#if JSPI + throw new Error("Missing stub for " + prop); +#else var resolved; stubs[prop] = (...args) => { resolved ||= resolveSymbol(prop); return resolved(...args); }; +#endif } return stubs[prop]; } }; - var proxy = new Proxy({}, proxyHandler); + var proxy = new Proxy(stubs, proxyHandler); var info = { 'GOT.mem': new Proxy({}, GOTHandler), 'GOT.func': new Proxy({}, GOTHandler), @@ -877,16 +1057,28 @@ var LibraryDylink = { } if (flags.loadAsync) { - if (binary instanceof WebAssembly.Module) { - var instance = new WebAssembly.Instance(binary, info); - return Promise.resolve(postInstantiation(binary, instance)); - } - return WebAssembly.instantiate(binary, info).then( - (result) => postInstantiation(result.module, result.instance) - ); + return (async function() { + if (binary instanceof WebAssembly.Module) { +#if JSPI + addStubImports(binary, stubs, resolveSymbol); +#endif + var instance = new WebAssembly.Instance(binary, info); + return postInstantiation(binary, instance); + } +#if JSPI + var module = await WebAssembly.compile(binary); + addStubImports(module, stubs, resolveSymbol); + var instance = await WebAssembly.instantiate(module, info); +#else + var {module, instance} = await WebAssembly.instantiate(binary, info); +#endif + return postInstantiation(module, instance); + })(); } - var module = binary instanceof WebAssembly.Module ? binary : new WebAssembly.Module(binary); +#if JSPI + addStubImports(module, stubs, resolveSymbol); +#endif var instance = new WebAssembly.Instance(module, info); return postInstantiation(module, instance); } diff --git a/test/core/test_dlfcn_jspi.c b/test/core/test_dlfcn_jspi.c index 0c73aa6250fb7..81dd074991533 100644 --- a/test/core/test_dlfcn_jspi.c +++ b/test/core/test_dlfcn_jspi.c @@ -3,6 +3,7 @@ // University of Illinois/NCSA Open Source License. Both these licenses can be // found in the LICENSE file. +#include #include #include #include @@ -21,9 +22,11 @@ int test_wrapper() { typedef int (*F)(); int main() { - void* handle = dlopen("side.so", RTLD_NOW|RTLD_GLOBAL); - F side_module_trampoline = dlsym(handle, "side_module_trampoline"); - int res = side_module_trampoline(); + void* handle = dlopen("side_a.so", RTLD_NOW|RTLD_GLOBAL); + assert(handle != NULL); + F side_module_trampolinea = dlsym(handle, "side_module_trampoline_a"); + assert(side_module_trampolinea != NULL); + int res = side_module_trampolinea(); printf("done %d\n", res); return 0; } diff --git a/test/core/test_dlfcn_jspi.out b/test/core/test_dlfcn_jspi.out index 8daf1b9e7f8bf..2b184530b264d 100644 --- a/test/core/test_dlfcn_jspi.out +++ b/test/core/test_dlfcn_jspi.out @@ -1,4 +1,5 @@ -side_module_trampoline +side_module_trampoline_a +side_module_trampoline_b sleeping slept done 77 diff --git a/test/core/test_dlfcn_jspi_side.c b/test/core/test_dlfcn_jspi_side.c deleted file mode 100644 index de945dd7ec4ae..0000000000000 --- a/test/core/test_dlfcn_jspi_side.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -int test_wrapper(void); - -int side_module_trampoline() { - printf("side_module_trampoline\n"); - return test_wrapper(); -} diff --git a/test/core/test_dlfcn_jspi_side_a.c b/test/core/test_dlfcn_jspi_side_a.c new file mode 100644 index 0000000000000..528ee9d679b3a --- /dev/null +++ b/test/core/test_dlfcn_jspi_side_a.c @@ -0,0 +1,7 @@ +#include +int side_module_trampoline_b(void); + +int side_module_trampoline_a() { + printf("side_module_trampoline_a\n"); + return side_module_trampoline_b(); +} diff --git a/test/core/test_dlfcn_jspi_side_b.c b/test/core/test_dlfcn_jspi_side_b.c new file mode 100644 index 0000000000000..0e86e74425d29 --- /dev/null +++ b/test/core/test_dlfcn_jspi_side_b.c @@ -0,0 +1,7 @@ +#include +int test_wrapper(void); + +int side_module_trampoline_b() { + printf("side_module_trampoline_b\n"); + return test_wrapper(); +} diff --git a/test/test_core.py b/test/test_core.py index e6d9a1651c0d6..f7fabd69ca032 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3769,13 +3769,23 @@ def test_dlfcn_jspi(self): [ EMCC, "-o", - "side.so", - test_file("core/test_dlfcn_jspi_side.c"), + "side_a.so", + test_file("core/test_dlfcn_jspi_side_a.c"), "-sSIDE_MODULE", ] + self.get_emcc_args() ) - self.do_run_in_out_file_test("core/test_dlfcn_jspi.c", emcc_args=["side.so", "-sMAIN_MODULE=2"]) + self.run_process( + [ + EMCC, + "-o", + "side_b.so", + test_file("core/test_dlfcn_jspi_side_b.c"), + "-sSIDE_MODULE", + ] + + self.get_emcc_args() + ) + self.do_run_in_out_file_test("core/test_dlfcn_jspi.c", emcc_args=["side_a.so", "side_b.so", "-sMAIN_MODULE=2"]) @needs_dylink def test_dlfcn_rtld_local(self): From 8ca0942c7e5b69996d3ef3c0818703bdd475bf90 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 7 Feb 2025 21:23:06 +0100 Subject: [PATCH 02/23] Use single quotes --- test/test_core.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test_core.py b/test/test_core.py index f7fabd69ca032..7b56de7c6d474 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3768,24 +3768,24 @@ def test_dlfcn_jspi(self): self.run_process( [ EMCC, - "-o", - "side_a.so", - test_file("core/test_dlfcn_jspi_side_a.c"), - "-sSIDE_MODULE", + '-o', + 'side_a.so', + test_file('core/test_dlfcn_jspi_side_a.c'), + '-sSIDE_MODULE', ] + self.get_emcc_args() ) self.run_process( [ EMCC, - "-o", - "side_b.so", - test_file("core/test_dlfcn_jspi_side_b.c"), - "-sSIDE_MODULE", + '-o', + 'side_b.so', + test_file('core/test_dlfcn_jspi_side_b.c'), + '-sSIDE_MODULE', ] + self.get_emcc_args() ) - self.do_run_in_out_file_test("core/test_dlfcn_jspi.c", emcc_args=["side_a.so", "side_b.so", "-sMAIN_MODULE=2"]) + self.do_run_in_out_file_test('core/test_dlfcn_jspi.c', emcc_args=['side_a.so', 'side_b.so', '-sMAIN_MODULE=2']) @needs_dylink def test_dlfcn_rtld_local(self): From 435fdc3d91812fde064afb27016cd412c089db04 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 7 Feb 2025 21:23:57 +0100 Subject: [PATCH 03/23] Declare stubs closer to first use --- src/lib/libdylink.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index a1a496a65dc44..a100c37e3c3a2 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -872,7 +872,6 @@ var LibraryDylink = { // to add the indirection for, without inspecting what A's imports // are. To do that here, we use a JS proxy (another option would // be to inspect the binary directly). - const stubs = {}; var proxyHandler = { get(stubs, prop) { // symbols that should be local to this module @@ -917,6 +916,7 @@ var LibraryDylink = { return stubs[prop]; } }; + const stubs = {}; var proxy = new Proxy(stubs, proxyHandler); var info = { 'GOT.mem': new Proxy({}, GOTHandler), From b6173e27936706148c2ebb1904efbe7d84c26206 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 7 Feb 2025 21:24:42 +0100 Subject: [PATCH 04/23] Wrap with #if JSPI --- src/lib/libdylink.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index a100c37e3c3a2..c6ecf4166e623 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -596,6 +596,7 @@ var LibraryDylink = { } }, #endif +#if JSPI $getStubImportModule__postset: ` var stubImportModuleCache = new Map(); `, @@ -769,6 +770,7 @@ var LibraryDylink = { stubs[name] = inst.exports.o; } }, +#endif // Loads a side module from binary data or compiled Module. Returns the module's exports or a // promise that resolves to its exports if the loadAsync flag is set. $loadWebAssemblyModule__docs: ` From 0c35849d8f5b6bdb2fdc1aaedc0da9a0d893f761 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 7 Feb 2025 21:25:21 +0100 Subject: [PATCH 05/23] Combine two checks --- src/lib/libdylink.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index c6ecf4166e623..c3255f57fb07d 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -745,10 +745,7 @@ var LibraryDylink = { // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). // TODO: Make this work without it. for (const {module, name, kind, type} of WebAssembly.Module.imports(mod)) { - if (module !== 'env') { - continue; - } - if (kind !== 'function') { + if (module !== 'env' || kind !== 'function') { continue; } if (name in wasmImports && !wasmImports[name].stub) { From c0938e4d87e5f1eb7a40c78935605fcb152d215a Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 31 Mar 2025 15:27:24 +0200 Subject: [PATCH 06/23] Automatic rebaseline of codesize expectations. NFC This is an automatic change generated by tools/maint/rebaseline_tests.py. The following (2) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_hello_dylink.gzsize: 5860 => 5869 [+9 bytes / +0.15%] other/codesize/test_codesize_hello_dylink.jssize: 12839 => 12877 [+38 bytes / +0.30%] Average change: +0.22% (+0.15% - +0.30%) ``` --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index 3fb524c7bdfc3..f3ff04ee606a8 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -5860 +5869 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 9ccb3323f6fac..74d0dea01fa6e 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -12839 +12877 From 40b8a82661e46a1b08769e4feea85b533b94d445 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 1 Apr 2025 14:50:39 +0200 Subject: [PATCH 07/23] Use assertion --- src/lib/libdylink.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 132da7ea0de35..7e3ade4b21ba1 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -897,7 +897,9 @@ var LibraryDylink = { // when first called. if (!(prop in stubs)) { #if JSPI - throw new Error("Missing stub for " + prop); +#if ASSERTIONS + assert(prop in stubs, 'missing JSPI stub'); +#endif #else var resolved; stubs[prop] = (...args) => { From 02b975356916c22a500914e6bc11d6ec664f05c7 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 1 Apr 2025 14:51:38 +0200 Subject: [PATCH 08/23] Single quotes --- src/lib/libdylink.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 7e3ade4b21ba1..3db0d7f1b5c3f 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -723,9 +723,9 @@ var LibraryDylink = { }; }, $addStubImports__deps: [ - "$getStubImportModule", - "$wasmSigToEmscripten", - "$getStubImportResolver" + '$getStubImportModule', + '$wasmSigToEmscripten', + '$getStubImportResolver', ], $addStubImports: (mod, stubs, resolveSymbol) => { // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). From 25d5dfb27c01f6b48180ac0f83233365697807b2 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 1 Apr 2025 14:52:02 +0200 Subject: [PATCH 09/23] Don't check for module == 'env' --- src/lib/libdylink.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 3db0d7f1b5c3f..29ac9d75cbd0b 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -731,7 +731,7 @@ var LibraryDylink = { // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). // TODO: Make this work without it. for (const {module, name, kind, type} of WebAssembly.Module.imports(mod)) { - if (module !== 'env' || kind !== 'function') { + if (kind !== 'function') { continue; } if (name in wasmImports && !wasmImports[name].stub) { From 7902cebf4b763e9298613785b1d48cf31b76a0c4 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 1 Apr 2025 14:56:13 +0200 Subject: [PATCH 10/23] Improve guard condition --- src/lib/libdylink.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 29ac9d75cbd0b..8018f8c94dccd 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -730,11 +730,12 @@ var LibraryDylink = { $addStubImports: (mod, stubs, resolveSymbol) => { // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). // TODO: Make this work without it. - for (const {module, name, kind, type} of WebAssembly.Module.imports(mod)) { + for (const {name, kind, type} of WebAssembly.Module.imports(mod)) { if (kind !== 'function') { continue; } - if (name in wasmImports && !wasmImports[name].stub) { + if (resolveSymbol(name)) { + // We only need stubs for late-binding symbols. continue; } #if !DISABLE_EXCEPTION_CATCHING || SUPPORT_LONGJMP == 'emscripten' From efff88b5a677a938a8f768da523451307c8ca388 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 1 Apr 2025 16:05:46 +0200 Subject: [PATCH 11/23] Fixes --- src/lib/libdylink.js | 2 +- test/test_core.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 8018f8c94dccd..96cb89b6c61fe 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -847,7 +847,7 @@ var LibraryDylink = { resolved = localScope[sym]; } if (!resolved) { - resolved = moduleExports[sym]; + resolved = moduleExports?.[sym]; } #if ASSERTIONS assert(resolved, `undefined symbol '${sym}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`); diff --git a/test/test_core.py b/test/test_core.py index 6ba697be90952..2cddcca155272 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3775,8 +3775,8 @@ def test_dlfcn_jspi(self): [ EMCC, '-o', - 'side_a.so', - test_file('core/test_dlfcn_jspi_side_a.c'), + 'side_b.so', + test_file('core/test_dlfcn_jspi_side_b.c'), '-sSIDE_MODULE', ] + self.get_emcc_args() @@ -3785,13 +3785,14 @@ def test_dlfcn_jspi(self): [ EMCC, '-o', + 'side_a.so', 'side_b.so', - test_file('core/test_dlfcn_jspi_side_b.c'), + test_file('core/test_dlfcn_jspi_side_a.c'), '-sSIDE_MODULE', ] + self.get_emcc_args() ) - self.do_run_in_out_file_test('core/test_dlfcn_jspi.c', emcc_args=['side_a.so', 'side_b.so', '-sMAIN_MODULE=2']) + self.do_run_in_out_file_test('core/test_dlfcn_jspi.c', emcc_args=['-L.', 'side_a.so', '-sMAIN_MODULE=2']) @needs_dylink def test_dlfcn_rtld_local(self): From 7d07256d050299e42c4beff51f2d4e8f0ecf7092 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 1 Apr 2025 17:21:20 +0200 Subject: [PATCH 12/23] Return a func ref and call it via call_ref of using a table --- src/lib/libdylink.js | 60 +++++++++++++++++++------------------------- test/test_core.py | 3 +-- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 96cb89b6c61fe..5aba1ccfdc7f8 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -628,34 +628,35 @@ var LibraryDylink = { var typeSectionBody = [ 0x02, // count: 2 ]; - generateFuncType('v', typeSectionBody); + + // Type 0 is "sig" generateFuncType(sig, typeSectionBody); + // Type 1 is (void) => (func ref to function of signature sig) + typeSectionBody.push(0x60 /* form: func */); + typeSectionBody.push(0x00); // 0 args + typeSectionBody.push(0x01, 0x63, 0x00); // (ref nullable func type 0) + uleb128Encode(typeSectionBody.length, bytes); bytes.push(...typeSectionBody); // static sections bytes.push( // Import section - 0x02, 0x0f, - 0x02, // 2 imports - 0x01, 0x65, // e - 0x01, 0x74, // t - // funcref table with no limits - 0x01, 0x70, 0x00, 0x00, - + 0x02, 0x07, + 0x01, // 1 import 0x01, 0x65, // e 0x01, 0x72, // r - 0x00, 0x00, // function of type 0 ('v') + 0x00, 0x01, // function of type 0 ('f') // Function section 0x03, 0x02, - 0x01, 0x01, // One function of type 1 (sig) + 0x01, 0x00, // One function of type 0 (sig) // Globals section - 0x06, 0x06, + 0x06, 0x07, 0x01, // one global - 0x7f, 0x01, // i32 mut - 0x41, 0x00, 0x0b, // initialized to i32.const 0 + 0x63, 0x00, 0x01, // (ref nullable func type 0) mutable + 0xd0, 0x00, 0x0b, // initialized to ref.null (func type 0) // Export section 0x07, 0x05, @@ -667,10 +668,9 @@ var LibraryDylink = { var codeBody = [ 0x00, // 0 locals 0x23, 0x00, // global.get 0 - 0x45, // i32.eqz + 0xd1, // ref.is_null 0x04, // if 0x40, 0x10, 0x00, // Call function 0 - 0x41, 0x01, // i32.const 1 0x24, 0x00, // global.set 0 0x0b, // end ]; @@ -679,8 +679,8 @@ var LibraryDylink = { } codeBody.push( - 0x41, 0x00, // i32.const 0 - 0x11, 0x01, 0x00, // call_indirect table 0, type 0 + 0x23, 0x00, // global.get 0 + 0x14, 0x00, // call_ref type 0 0x0b // end ); var codeSectionBody = [0x01]; @@ -704,22 +704,13 @@ var LibraryDylink = { } return sig; }, - $getStubImportResolver: (name, sig, table, resolveSymbol) => { + $getStubImportResolver: (name, resolveSymbol) => { return function r() { var res = resolveSymbol(name); if (res.orig) { res = res.orig; } - try { - // Attempting to call this with JS function will cause table.set() to fail - table.set(0, res); - } catch (err) { - if (!(err instanceof TypeError)) { - throw err; - } - var wrapped = convertJsFunctionToWasm(res, sig); - table.set(0, wrapped); - } + return res; }; }, $addStubImports__deps: [ @@ -734,7 +725,7 @@ var LibraryDylink = { if (kind !== 'function') { continue; } - if (resolveSymbol(name)) { + if (resolveSymbol(name, true)) { // We only need stubs for late-binding symbols. continue; } @@ -748,9 +739,8 @@ var LibraryDylink = { #endif var sig = wasmSigToEmscripten(type); var mod = getStubImportModule(sig); - const t = new WebAssembly.Table({element: 'funcref', initial: 1}); - const r = getStubImportResolver(name, sig, t, resolveSymbol); - const inst = new WebAssembly.Instance(mod, {e: {t, r}}); + const r = getStubImportResolver(name, resolveSymbol); + const inst = new WebAssembly.Instance(mod, {e: {r}}); stubs[name] = inst.exports.o; } }, @@ -841,7 +831,7 @@ var LibraryDylink = { // need to import their own symbols var moduleExports; - function resolveSymbol(sym) { + function resolveSymbol(sym, allowUndefined) { var resolved = resolveGlobalSymbol(sym).sym; if (!resolved && localScope) { resolved = localScope[sym]; @@ -850,7 +840,9 @@ var LibraryDylink = { resolved = moduleExports?.[sym]; } #if ASSERTIONS - assert(resolved, `undefined symbol '${sym}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`); + if (!allowUndefined) { + assert(resolved, `undefined symbol '${sym}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`); + } #endif return resolved; } diff --git a/test/test_core.py b/test/test_core.py index 2cddcca155272..2b833076522ad 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -3786,13 +3786,12 @@ def test_dlfcn_jspi(self): EMCC, '-o', 'side_a.so', - 'side_b.so', test_file('core/test_dlfcn_jspi_side_a.c'), '-sSIDE_MODULE', ] + self.get_emcc_args() ) - self.do_run_in_out_file_test('core/test_dlfcn_jspi.c', emcc_args=['-L.', 'side_a.so', '-sMAIN_MODULE=2']) + self.do_run_in_out_file_test('core/test_dlfcn_jspi.c', emcc_args=['side_a.so', 'side_b.so', '-sMAIN_MODULE=2']) @needs_dylink def test_dlfcn_rtld_local(self): From 80d02f01be6e284ac9a7dbca5a16dc978a2837fc Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 2 Apr 2025 23:33:02 +0200 Subject: [PATCH 13/23] Fix closure --- src/lib/libdylink.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 5aba1ccfdc7f8..0e719b73457f5 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -831,7 +831,7 @@ var LibraryDylink = { // need to import their own symbols var moduleExports; - function resolveSymbol(sym, allowUndefined) { + function resolveSymbol(sym, allowUndefined=false) { var resolved = resolveGlobalSymbol(sym).sym; if (!resolved && localScope) { resolved = localScope[sym]; From 3dc7a4fdbaedfde80ec05682d9345ce41a59a0e0 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 2 Apr 2025 23:36:51 +0200 Subject: [PATCH 14/23] Update code size --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index f3ff04ee606a8..4ad949fb79496 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -5869 +5864 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index 74d0dea01fa6e..3d3ff56bb193a 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -12877 +12846 From d2c610207bce4202c94b6887be685ae7b8d89b9e Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 2 Apr 2025 23:37:57 +0200 Subject: [PATCH 15/23] Revert codesizes to main --- test/other/codesize/test_codesize_cxx_ctors1.gzsize | 2 +- test/other/codesize/test_codesize_cxx_ctors1.jssize | 2 +- test/other/codesize/test_codesize_cxx_ctors2.gzsize | 2 +- test/other/codesize/test_codesize_cxx_ctors2.jssize | 2 +- test/other/codesize/test_codesize_cxx_except.gzsize | 2 +- test/other/codesize/test_codesize_cxx_except.jssize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm.gzsize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm.jssize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize | 2 +- test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize | 2 +- test/other/codesize/test_codesize_cxx_lto.gzsize | 2 +- test/other/codesize/test_codesize_cxx_lto.jssize | 2 +- test/other/codesize/test_codesize_cxx_mangle.gzsize | 2 +- test/other/codesize/test_codesize_cxx_mangle.jssize | 2 +- test/other/codesize/test_codesize_cxx_noexcept.gzsize | 2 +- test/other/codesize/test_codesize_cxx_noexcept.jssize | 2 +- test/other/codesize/test_codesize_cxx_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_cxx_wasmfs.jssize | 2 +- test/other/codesize/test_codesize_files_js_fs.gzsize | 2 +- test/other/codesize/test_codesize_files_js_fs.jssize | 2 +- test/other/codesize/test_codesize_files_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_files_wasmfs.jssize | 2 +- test/other/codesize/test_codesize_hello_O0.gzsize | 2 +- test/other/codesize/test_codesize_hello_O0.jssize | 2 +- test/other/codesize/test_codesize_hello_O1.gzsize | 2 +- test/other/codesize/test_codesize_hello_O1.jssize | 2 +- test/other/codesize/test_codesize_hello_O2.gzsize | 2 +- test/other/codesize/test_codesize_hello_O2.jssize | 2 +- test/other/codesize/test_codesize_hello_O3.gzsize | 2 +- test/other/codesize/test_codesize_hello_O3.jssize | 2 +- test/other/codesize/test_codesize_hello_Os.gzsize | 2 +- test/other/codesize/test_codesize_hello_Os.jssize | 2 +- test/other/codesize/test_codesize_hello_Oz.gzsize | 2 +- test/other/codesize/test_codesize_hello_Oz.jssize | 2 +- test/other/codesize/test_codesize_hello_export_nothing.jssize | 2 +- test/other/codesize/test_codesize_hello_single_file.gzsize | 2 +- test/other/codesize/test_codesize_hello_single_file.jssize | 2 +- test/other/codesize/test_codesize_hello_wasmfs.gzsize | 2 +- test/other/codesize/test_codesize_hello_wasmfs.jssize | 2 +- test/other/codesize/test_codesize_libcxxabi_message_O3.jssize | 2 +- .../test_codesize_libcxxabi_message_O3_standalone.gzsize | 2 +- .../test_codesize_libcxxabi_message_O3_standalone.jssize | 2 +- test/other/codesize/test_codesize_mem_O3.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_grow.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_grow.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize | 2 +- test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize | 2 +- .../codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize | 2 +- .../codesize/test_codesize_mem_O3_standalone_narg_flto.jssize | 2 +- test/other/codesize/test_codesize_minimal_O0.gzsize | 2 +- test/other/codesize/test_codesize_minimal_O0.jssize | 2 +- test/other/codesize/test_codesize_minimal_pthreads.gzsize | 2 +- test/other/codesize/test_codesize_minimal_pthreads.jssize | 2 +- 59 files changed, 59 insertions(+), 59 deletions(-) diff --git a/test/other/codesize/test_codesize_cxx_ctors1.gzsize b/test/other/codesize/test_codesize_cxx_ctors1.gzsize index d8f3dc7482479..23a1595dfc22a 100644 --- a/test/other/codesize/test_codesize_cxx_ctors1.gzsize +++ b/test/other/codesize/test_codesize_cxx_ctors1.gzsize @@ -1 +1 @@ -8232 +8243 diff --git a/test/other/codesize/test_codesize_cxx_ctors1.jssize b/test/other/codesize/test_codesize_cxx_ctors1.jssize index 27c796a162b97..b5df5c55677b7 100644 --- a/test/other/codesize/test_codesize_cxx_ctors1.jssize +++ b/test/other/codesize/test_codesize_cxx_ctors1.jssize @@ -1 +1 @@ -19993 +19969 diff --git a/test/other/codesize/test_codesize_cxx_ctors2.gzsize b/test/other/codesize/test_codesize_cxx_ctors2.gzsize index 2b886f8252fa8..0d6da56ac50fd 100644 --- a/test/other/codesize/test_codesize_cxx_ctors2.gzsize +++ b/test/other/codesize/test_codesize_cxx_ctors2.gzsize @@ -1 +1 @@ -8221 +8230 diff --git a/test/other/codesize/test_codesize_cxx_ctors2.jssize b/test/other/codesize/test_codesize_cxx_ctors2.jssize index 7d5b516726c18..e3983efa4df58 100644 --- a/test/other/codesize/test_codesize_cxx_ctors2.jssize +++ b/test/other/codesize/test_codesize_cxx_ctors2.jssize @@ -1 +1 @@ -19971 +19947 diff --git a/test/other/codesize/test_codesize_cxx_except.gzsize b/test/other/codesize/test_codesize_cxx_except.gzsize index 0f05e3f519b14..fb7f839c5e626 100644 --- a/test/other/codesize/test_codesize_cxx_except.gzsize +++ b/test/other/codesize/test_codesize_cxx_except.gzsize @@ -1 +1 @@ -9231 +9233 diff --git a/test/other/codesize/test_codesize_cxx_except.jssize b/test/other/codesize/test_codesize_cxx_except.jssize index aa74b4197966a..5eff5fe7c4161 100644 --- a/test/other/codesize/test_codesize_cxx_except.jssize +++ b/test/other/codesize/test_codesize_cxx_except.jssize @@ -1 +1 @@ -23730 +23707 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm.gzsize b/test/other/codesize/test_codesize_cxx_except_wasm.gzsize index 964a1e5390897..9ed94d7fd7d14 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm.gzsize +++ b/test/other/codesize/test_codesize_cxx_except_wasm.gzsize @@ -1 +1 @@ -8177 +8187 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm.jssize b/test/other/codesize/test_codesize_cxx_except_wasm.jssize index e56210bf45015..abcbef7883bbf 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm.jssize +++ b/test/other/codesize/test_codesize_cxx_except_wasm.jssize @@ -1 +1 @@ -19885 +19861 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize index 964a1e5390897..9ed94d7fd7d14 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize +++ b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.gzsize @@ -1 +1 @@ -8177 +8187 diff --git a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize index e56210bf45015..abcbef7883bbf 100644 --- a/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize +++ b/test/other/codesize/test_codesize_cxx_except_wasm_legacy.jssize @@ -1 +1 @@ -19885 +19861 diff --git a/test/other/codesize/test_codesize_cxx_lto.gzsize b/test/other/codesize/test_codesize_cxx_lto.gzsize index 6f786d398902e..9a8bb2d120ca5 100644 --- a/test/other/codesize/test_codesize_cxx_lto.gzsize +++ b/test/other/codesize/test_codesize_cxx_lto.gzsize @@ -1 +1 @@ -8245 +8259 diff --git a/test/other/codesize/test_codesize_cxx_lto.jssize b/test/other/codesize/test_codesize_cxx_lto.jssize index 2f8cb06ad1fcd..780c5e3303c02 100644 --- a/test/other/codesize/test_codesize_cxx_lto.jssize +++ b/test/other/codesize/test_codesize_cxx_lto.jssize @@ -1 +1 @@ -20067 +20043 diff --git a/test/other/codesize/test_codesize_cxx_mangle.gzsize b/test/other/codesize/test_codesize_cxx_mangle.gzsize index 7f4fc4bd45847..4a0aaed28f063 100644 --- a/test/other/codesize/test_codesize_cxx_mangle.gzsize +++ b/test/other/codesize/test_codesize_cxx_mangle.gzsize @@ -1 +1 @@ -9268 +9272 diff --git a/test/other/codesize/test_codesize_cxx_mangle.jssize b/test/other/codesize/test_codesize_cxx_mangle.jssize index fe17b4115c2b8..d8302b3802c5a 100644 --- a/test/other/codesize/test_codesize_cxx_mangle.jssize +++ b/test/other/codesize/test_codesize_cxx_mangle.jssize @@ -1 +1 @@ -23844 +23821 diff --git a/test/other/codesize/test_codesize_cxx_noexcept.gzsize b/test/other/codesize/test_codesize_cxx_noexcept.gzsize index d8f3dc7482479..23a1595dfc22a 100644 --- a/test/other/codesize/test_codesize_cxx_noexcept.gzsize +++ b/test/other/codesize/test_codesize_cxx_noexcept.gzsize @@ -1 +1 @@ -8232 +8243 diff --git a/test/other/codesize/test_codesize_cxx_noexcept.jssize b/test/other/codesize/test_codesize_cxx_noexcept.jssize index 27c796a162b97..b5df5c55677b7 100644 --- a/test/other/codesize/test_codesize_cxx_noexcept.jssize +++ b/test/other/codesize/test_codesize_cxx_noexcept.jssize @@ -1 +1 @@ -19993 +19969 diff --git a/test/other/codesize/test_codesize_cxx_wasmfs.gzsize b/test/other/codesize/test_codesize_cxx_wasmfs.gzsize index ce6800c84df61..d4b320b1e2b3c 100644 --- a/test/other/codesize/test_codesize_cxx_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_cxx_wasmfs.gzsize @@ -1 +1 @@ -3440 +3424 diff --git a/test/other/codesize/test_codesize_cxx_wasmfs.jssize b/test/other/codesize/test_codesize_cxx_wasmfs.jssize index cbe97cf27b005..eeea19ff558c7 100644 --- a/test/other/codesize/test_codesize_cxx_wasmfs.jssize +++ b/test/other/codesize/test_codesize_cxx_wasmfs.jssize @@ -1 +1 @@ -7429 +7366 diff --git a/test/other/codesize/test_codesize_files_js_fs.gzsize b/test/other/codesize/test_codesize_files_js_fs.gzsize index 8b822a3f7bf83..9d4a5d9241728 100644 --- a/test/other/codesize/test_codesize_files_js_fs.gzsize +++ b/test/other/codesize/test_codesize_files_js_fs.gzsize @@ -1 +1 @@ -7542 +7540 diff --git a/test/other/codesize/test_codesize_files_js_fs.jssize b/test/other/codesize/test_codesize_files_js_fs.jssize index 69a8a69a318fa..afd43f8827d5b 100644 --- a/test/other/codesize/test_codesize_files_js_fs.jssize +++ b/test/other/codesize/test_codesize_files_js_fs.jssize @@ -1 +1 @@ -18551 +18547 diff --git a/test/other/codesize/test_codesize_files_wasmfs.gzsize b/test/other/codesize/test_codesize_files_wasmfs.gzsize index 1f62501d6c9d3..c452dc725c538 100644 --- a/test/other/codesize/test_codesize_files_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_files_wasmfs.gzsize @@ -1 +1 @@ -2682 +2681 diff --git a/test/other/codesize/test_codesize_files_wasmfs.jssize b/test/other/codesize/test_codesize_files_wasmfs.jssize index da710c1aba587..212ad991fe2af 100644 --- a/test/other/codesize/test_codesize_files_wasmfs.jssize +++ b/test/other/codesize/test_codesize_files_wasmfs.jssize @@ -1 +1 @@ -5753 +5749 diff --git a/test/other/codesize/test_codesize_hello_O0.gzsize b/test/other/codesize/test_codesize_hello_O0.gzsize index b59bd0a89971a..69779c2df0ed3 100644 --- a/test/other/codesize/test_codesize_hello_O0.gzsize +++ b/test/other/codesize/test_codesize_hello_O0.gzsize @@ -1 +1 @@ -7940 +7775 diff --git a/test/other/codesize/test_codesize_hello_O0.jssize b/test/other/codesize/test_codesize_hello_O0.jssize index d90ba01dfb58c..13c91e65d2408 100644 --- a/test/other/codesize/test_codesize_hello_O0.jssize +++ b/test/other/codesize/test_codesize_hello_O0.jssize @@ -1 +1 @@ -21295 +20699 diff --git a/test/other/codesize/test_codesize_hello_O1.gzsize b/test/other/codesize/test_codesize_hello_O1.gzsize index efbf27c074661..803264bb4c322 100644 --- a/test/other/codesize/test_codesize_hello_O1.gzsize +++ b/test/other/codesize/test_codesize_hello_O1.gzsize @@ -1 +1 @@ -2547 +2546 diff --git a/test/other/codesize/test_codesize_hello_O1.jssize b/test/other/codesize/test_codesize_hello_O1.jssize index 0590e000d1be1..20028371a8cb4 100644 --- a/test/other/codesize/test_codesize_hello_O1.jssize +++ b/test/other/codesize/test_codesize_hello_O1.jssize @@ -1 +1 @@ -6584 +6580 diff --git a/test/other/codesize/test_codesize_hello_O2.gzsize b/test/other/codesize/test_codesize_hello_O2.gzsize index 6230c73f166e0..06f43a4271d0e 100644 --- a/test/other/codesize/test_codesize_hello_O2.gzsize +++ b/test/other/codesize/test_codesize_hello_O2.gzsize @@ -1 +1 @@ -2204 +2202 diff --git a/test/other/codesize/test_codesize_hello_O2.jssize b/test/other/codesize/test_codesize_hello_O2.jssize index 42e82cc24d931..62e0c8f9c901b 100644 --- a/test/other/codesize/test_codesize_hello_O2.jssize +++ b/test/other/codesize/test_codesize_hello_O2.jssize @@ -1 +1 @@ -4546 +4542 diff --git a/test/other/codesize/test_codesize_hello_O3.gzsize b/test/other/codesize/test_codesize_hello_O3.gzsize index 1ff3df5453eed..0b460a920465c 100644 --- a/test/other/codesize/test_codesize_hello_O3.gzsize +++ b/test/other/codesize/test_codesize_hello_O3.gzsize @@ -1 +1 @@ -2162 +2161 diff --git a/test/other/codesize/test_codesize_hello_O3.jssize b/test/other/codesize/test_codesize_hello_O3.jssize index 4a4c5f9fbad97..6232a061d728e 100644 --- a/test/other/codesize/test_codesize_hello_O3.jssize +++ b/test/other/codesize/test_codesize_hello_O3.jssize @@ -1 +1 @@ -4488 +4484 diff --git a/test/other/codesize/test_codesize_hello_Os.gzsize b/test/other/codesize/test_codesize_hello_Os.gzsize index 1ff3df5453eed..0b460a920465c 100644 --- a/test/other/codesize/test_codesize_hello_Os.gzsize +++ b/test/other/codesize/test_codesize_hello_Os.gzsize @@ -1 +1 @@ -2162 +2161 diff --git a/test/other/codesize/test_codesize_hello_Os.jssize b/test/other/codesize/test_codesize_hello_Os.jssize index 4a4c5f9fbad97..6232a061d728e 100644 --- a/test/other/codesize/test_codesize_hello_Os.jssize +++ b/test/other/codesize/test_codesize_hello_Os.jssize @@ -1 +1 @@ -4488 +4484 diff --git a/test/other/codesize/test_codesize_hello_Oz.gzsize b/test/other/codesize/test_codesize_hello_Oz.gzsize index 1ff3df5453eed..0b460a920465c 100644 --- a/test/other/codesize/test_codesize_hello_Oz.gzsize +++ b/test/other/codesize/test_codesize_hello_Oz.gzsize @@ -1 +1 @@ -2162 +2161 diff --git a/test/other/codesize/test_codesize_hello_Oz.jssize b/test/other/codesize/test_codesize_hello_Oz.jssize index 4a4c5f9fbad97..6232a061d728e 100644 --- a/test/other/codesize/test_codesize_hello_Oz.jssize +++ b/test/other/codesize/test_codesize_hello_Oz.jssize @@ -1 +1 @@ -4488 +4484 diff --git a/test/other/codesize/test_codesize_hello_export_nothing.jssize b/test/other/codesize/test_codesize_hello_export_nothing.jssize index 9867a63213fcc..da2fd1a7999ae 100644 --- a/test/other/codesize/test_codesize_hello_export_nothing.jssize +++ b/test/other/codesize/test_codesize_hello_export_nothing.jssize @@ -1 +1 @@ -3419 +3415 diff --git a/test/other/codesize/test_codesize_hello_single_file.gzsize b/test/other/codesize/test_codesize_hello_single_file.gzsize index efeb812131571..bb7949a47215f 100644 --- a/test/other/codesize/test_codesize_hello_single_file.gzsize +++ b/test/other/codesize/test_codesize_hello_single_file.gzsize @@ -1 +1 @@ -3690 +3687 diff --git a/test/other/codesize/test_codesize_hello_single_file.jssize b/test/other/codesize/test_codesize_hello_single_file.jssize index b77214bd80413..5c0c90dc6f27f 100644 --- a/test/other/codesize/test_codesize_hello_single_file.jssize +++ b/test/other/codesize/test_codesize_hello_single_file.jssize @@ -1 +1 @@ -6783 +6779 diff --git a/test/other/codesize/test_codesize_hello_wasmfs.gzsize b/test/other/codesize/test_codesize_hello_wasmfs.gzsize index 1ff3df5453eed..0b460a920465c 100644 --- a/test/other/codesize/test_codesize_hello_wasmfs.gzsize +++ b/test/other/codesize/test_codesize_hello_wasmfs.gzsize @@ -1 +1 @@ -2162 +2161 diff --git a/test/other/codesize/test_codesize_hello_wasmfs.jssize b/test/other/codesize/test_codesize_hello_wasmfs.jssize index 4a4c5f9fbad97..6232a061d728e 100644 --- a/test/other/codesize/test_codesize_hello_wasmfs.jssize +++ b/test/other/codesize/test_codesize_hello_wasmfs.jssize @@ -1 +1 @@ -4488 +4484 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize b/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize index 940846629fe66..ac5764e2098c7 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3.jssize @@ -1 +1 @@ -3773 +3769 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize index 93752caf01bd5..8479ac6d2b4f3 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.gzsize @@ -1 +1 @@ -1798 +1795 diff --git a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize index 069ccfea1e738..e953d33731a03 100644 --- a/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize +++ b/test/other/codesize/test_codesize_libcxxabi_message_O3_standalone.jssize @@ -1 +1 @@ -3816 +3812 diff --git a/test/other/codesize/test_codesize_mem_O3.gzsize b/test/other/codesize/test_codesize_mem_O3.gzsize index 37e23e5ef7eee..65ea5f0d30d84 100644 --- a/test/other/codesize/test_codesize_mem_O3.gzsize +++ b/test/other/codesize/test_codesize_mem_O3.gzsize @@ -1 +1 @@ -2211 +2214 diff --git a/test/other/codesize/test_codesize_mem_O3.jssize b/test/other/codesize/test_codesize_mem_O3.jssize index ff84458304aa8..f201ebe0c4417 100644 --- a/test/other/codesize/test_codesize_mem_O3.jssize +++ b/test/other/codesize/test_codesize_mem_O3.jssize @@ -1 +1 @@ -4644 +4640 diff --git a/test/other/codesize/test_codesize_mem_O3_grow.gzsize b/test/other/codesize/test_codesize_mem_O3_grow.gzsize index 9174391f5931e..7d945b944dabc 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_grow.gzsize @@ -1 +1 @@ -2358 +2359 diff --git a/test/other/codesize/test_codesize_mem_O3_grow.jssize b/test/other/codesize/test_codesize_mem_O3_grow.jssize index a635065fa4aa4..18af9a218e8c4 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow.jssize +++ b/test/other/codesize/test_codesize_mem_O3_grow.jssize @@ -1 +1 @@ -4928 +4924 diff --git a/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize b/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize index b742f79e29933..8cb1ed86567e4 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_grow_standalone.gzsize @@ -1 +1 @@ -2058 +2056 diff --git a/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize b/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize index cbc92e3811d9b..20de14b506ee8 100644 --- a/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize +++ b/test/other/codesize/test_codesize_mem_O3_grow_standalone.jssize @@ -1 +1 @@ -4341 +4337 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone.jssize b/test/other/codesize/test_codesize_mem_O3_standalone.jssize index d99ef68f083f3..a76a74af11768 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone.jssize @@ -1 +1 @@ -4273 +4269 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize index f6f19007d10bc..81f2d5209ce41 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_lib.gzsize @@ -1 +1 @@ -1793 +1792 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize b/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize index 60a2cc58753fa..aee76db7d6772 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_lib.jssize @@ -1 +1 @@ -3829 +3825 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize index 93752caf01bd5..8479ac6d2b4f3 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg.gzsize @@ -1 +1 @@ -1798 +1795 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize b/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize index 069ccfea1e738..e953d33731a03 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg.jssize @@ -1 +1 @@ -3816 +3812 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize index 93752caf01bd5..8479ac6d2b4f3 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.gzsize @@ -1 +1 @@ -1798 +1795 diff --git a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize index 069ccfea1e738..e953d33731a03 100644 --- a/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize +++ b/test/other/codesize/test_codesize_mem_O3_standalone_narg_flto.jssize @@ -1 +1 @@ -3816 +3812 diff --git a/test/other/codesize/test_codesize_minimal_O0.gzsize b/test/other/codesize/test_codesize_minimal_O0.gzsize index 3352be8311244..970b63c54d9b8 100644 --- a/test/other/codesize/test_codesize_minimal_O0.gzsize +++ b/test/other/codesize/test_codesize_minimal_O0.gzsize @@ -1 +1 @@ -6284 +6134 diff --git a/test/other/codesize/test_codesize_minimal_O0.jssize b/test/other/codesize/test_codesize_minimal_O0.jssize index 94f278be21096..0826d08d7b4c3 100644 --- a/test/other/codesize/test_codesize_minimal_O0.jssize +++ b/test/other/codesize/test_codesize_minimal_O0.jssize @@ -1 +1 @@ -16651 +16118 diff --git a/test/other/codesize/test_codesize_minimal_pthreads.gzsize b/test/other/codesize/test_codesize_minimal_pthreads.gzsize index 7a4e7818cfbdd..4a3a63211e267 100644 --- a/test/other/codesize/test_codesize_minimal_pthreads.gzsize +++ b/test/other/codesize/test_codesize_minimal_pthreads.gzsize @@ -1 +1 @@ -4045 +4043 diff --git a/test/other/codesize/test_codesize_minimal_pthreads.jssize b/test/other/codesize/test_codesize_minimal_pthreads.jssize index e71810d76035f..c71bb725b3810 100644 --- a/test/other/codesize/test_codesize_minimal_pthreads.jssize +++ b/test/other/codesize/test_codesize_minimal_pthreads.jssize @@ -1 +1 @@ -8382 +8379 From 9833523876c42d32cb7de47aed38fb345eeac3eb Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 18 Apr 2025 16:18:59 -0400 Subject: [PATCH 16/23] Update code size --- test/other/codesize/test_codesize_hello_dylink.gzsize | 2 +- test/other/codesize/test_codesize_hello_dylink.jssize | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index a5755921eac44..27dfac602e314 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11735 +11736 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index c82e0d84da885..7cb5c3b2b7ba6 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -27774 +27776 From 9dcde849f5d05b829d9dfc5eea043878c4dec6c6 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 18 Apr 2025 16:52:12 -0400 Subject: [PATCH 17/23] Address some comments --- src/lib/libdylink.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 9b4fe29facc1c..cc0eb895c022c 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -593,13 +593,13 @@ var LibraryDylink = { } }, #endif + #if JSPI - $getStubImportModule__postset: ` - var stubImportModuleCache = new Map(); - `, + $stubImportModuleCache: new Map(), $getStubImportModule__deps: [ "$generateFuncType", - "$uleb128Encode" + "$uleb128Encode", + "$stubImportModuleCache", ], // We need to call out to JS to resolve the function, but then make the actual // onward call from WebAssembly. The JavaScript $resolve function is @@ -715,19 +715,9 @@ var LibraryDylink = { } return sig; }, - $getStubImportResolver: (name, resolveSymbol) => { - return function r() { - var res = resolveSymbol(name); - if (res.orig) { - res = res.orig; - } - return res; - }; - }, $addStubImports__deps: [ '$getStubImportModule', '$wasmSigToEmscripten', - '$getStubImportResolver', ], $addStubImports: (mod, stubs, resolveSymbol) => { // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). @@ -750,12 +740,13 @@ var LibraryDylink = { #endif var sig = wasmSigToEmscripten(type); var mod = getStubImportModule(sig); - const r = getStubImportResolver(name, resolveSymbol); + const r = () => resolveSymbol(name); const inst = new WebAssembly.Instance(mod, {e: {r}}); stubs[name] = inst.exports.o; } }, -#endif +#endif // JSPI + // Loads a side module from binary data or compiled Module. Returns the module's exports or a // promise that resolves to its exports if the loadAsync flag is set. $loadWebAssemblyModule__docs: ` @@ -854,6 +845,11 @@ var LibraryDylink = { if (!allowUndefined) { assert(resolved, `undefined symbol '${sym}'. perhaps a side module was not linked in? if this global was expected to arrive from a system library, try to build the MAIN_MODULE with EMCC_FORCE_STDLIBS=1 in the environment`); } +#endif +#if JSPI + if (res.orig) { + res = res.orig; + } #endif return resolved; } From 5e968c87c74846e38831e9153fa1c77f531a736a Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 18 Apr 2025 17:03:25 -0400 Subject: [PATCH 18/23] Fix --- src/lib/libdylink.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index cc0eb895c022c..04c67f44a25aa 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -847,8 +847,8 @@ var LibraryDylink = { } #endif #if JSPI - if (res.orig) { - res = res.orig; + if (resolved?.orig) { + resolved = resolved.orig; } #endif return resolved; From c00c75b64496f392828df8eac947d48f79071c03 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 18 Apr 2025 17:42:22 -0400 Subject: [PATCH 19/23] Update wat --- src/lib/libdylink.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 04c67f44a25aa..8a49ee339adf6 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -607,23 +607,19 @@ var LibraryDylink = { // is ii, the wat for the generated module looks like this: // // (module - // (type $r (func )) // (type $ii (func (param i32) (result i32))) - // (import "e" "t" (table 0 funcref)) - // (import "e" "r" (func $resolve)) - // (global $isResolved (mut i32) i32.const 0) - // + // (func $resolveFunc (import "e" "r") (result (ref null $ii))) + // (global $resolved (mut (ref null $ii)) (ref.null $ii)) // (func (export "o") (param $p1 i32) (result i32) - // global.get $isResolved - // i32.eqz + // global.get $resolved + // ref.is_null // if - // call $resolve - // i32.const 1 - // global.set $isResolved + // call $resolveFunc + // global.set $resolved // end // local.get $p1 - // i32.const 0 - // call_indirect (type $ii) + // global.get $resolved + // call_ref $ii // ) // ) $getStubImportModule: (sig) => { From 185c3627561d7d3fd8d1868d129db8f22227a147 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 21 Apr 2025 15:21:53 -0400 Subject: [PATCH 20/23] Generate stub imports lazily --- src/lib/libdylink.js | 53 ++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/src/lib/libdylink.js b/src/lib/libdylink.js index 8a49ee339adf6..85d6cacf140b2 100644 --- a/src/lib/libdylink.js +++ b/src/lib/libdylink.js @@ -627,7 +627,7 @@ var LibraryDylink = { if (cached) { return cached; } - const bytes = [ + var bytes = [ 0x00, 0x61, 0x73, 0x6d, // Magic number 0x01, 0x00, 0x00, 0x00, // version 1 0x01, // Type section code @@ -681,7 +681,7 @@ var LibraryDylink = { 0x24, 0x00, // global.set 0 0x0b, // end ]; - for (let i = 0; i < sig.length - 1; i++) { + for (var i = 0; i < sig.length - 1; i++) { codeBody.push(0x20, i); } @@ -711,35 +711,17 @@ var LibraryDylink = { } return sig; }, - $addStubImports__deps: [ - '$getStubImportModule', - '$wasmSigToEmscripten', - ], - $addStubImports: (mod, stubs, resolveSymbol) => { + $getStubImportTypes: (mod) => { // Assumes --experimental-wasm-type-reflection to get type field of WebAssembly.Module.imports(). // TODO: Make this work without it. - for (const {name, kind, type} of WebAssembly.Module.imports(mod)) { + var stubTypes = {} + for (var {name, kind, type} of WebAssembly.Module.imports(mod)) { if (kind !== 'function') { continue; } - if (resolveSymbol(name, true)) { - // We only need stubs for late-binding symbols. - continue; - } -#if !DISABLE_EXCEPTION_CATCHING || SUPPORT_LONGJMP == 'emscripten' - if (name.startsWith("invoke_")) { - // JSPI + JS exceptions probably doesn't work but maybe nobody will - // attempt stack switch inside a try block. - stubs[name] = createInvokeFunction(name.split('_')[1]); - continue; - } -#endif - var sig = wasmSigToEmscripten(type); - var mod = getStubImportModule(sig); - const r = () => resolveSymbol(name); - const inst = new WebAssembly.Instance(mod, {e: {r}}); - stubs[name] = inst.exports.o; + stubTypes[name] = type; } + return stubTypes; }, #endif // JSPI @@ -760,7 +742,9 @@ var LibraryDylink = { '$wasmTable', '$addOnPostCtor', #if JSPI - '$addStubImports', + '$getStubImportModule', + '$wasmSigToEmscripten', + '$getStubImportTypes', #endif ], $loadWebAssemblyModule: (binary, flags, libName, localScope, handle) => { @@ -850,6 +834,9 @@ var LibraryDylink = { return resolved; } +#if JSPI + var stubImportTypes = {}; +#endif // TODO kill ↓↓↓ (except "symbols local to this module", it will likely be // not needed if we require that if A wants symbols from B it has to link // to B explicitly: similarly to -Wl,--no-undefined) @@ -894,8 +881,12 @@ var LibraryDylink = { if (!(prop in stubs)) { #if JSPI #if ASSERTIONS - assert(prop in stubs, 'missing JSPI stub'); + assert(prop in stubImportTypes, 'missing JSPI stub'); #endif + var mod = getStubImportModule(wasmSigToEmscripten(stubImportTypes[prop])); + var r = () => resolveSymbol(prop); + var inst = new WebAssembly.Instance(mod, {e: {r}}); + stubs[prop] = inst.exports.o; #else var resolved; stubs[prop] = (...args) => { @@ -907,7 +898,7 @@ var LibraryDylink = { return stubs[prop]; } }; - const stubs = {}; + var stubs = {}; var proxy = new Proxy(stubs, proxyHandler); var info = { 'GOT.mem': new Proxy({}, GOTHandler), @@ -1052,13 +1043,13 @@ var LibraryDylink = { var instance; if (binary instanceof WebAssembly.Module) { #if JSPI - addStubImports(binary, stubs, resolveSymbol); + stubImportTypes = getStubImportTypes(binary); #endif instance = new WebAssembly.Instance(binary, info); } else { #if JSPI binary = await WebAssembly.compile(binary); - addStubImports(binary, stubs, resolveSymbol); + stubImportTypes = getStubImportTypes(binary); instance = await WebAssembly.instantiate(binary, info); #else // Destructuring assignment without declaration has to be wrapped @@ -1072,7 +1063,7 @@ var LibraryDylink = { } var module = binary instanceof WebAssembly.Module ? binary : new WebAssembly.Module(binary); #if JSPI - addStubImports(module, stubs, resolveSymbol); + stubImportTypes = getStubImportTypes(module); #endif var instance = new WebAssembly.Instance(module, info); return postInstantiation(module, instance); From 84ab556a41c11a5a32b74486e54c8e975cac7d9c Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 21 Apr 2025 17:33:47 -0400 Subject: [PATCH 21/23] Bring in test that doesn't work in #24161 and does work here --- test/core/test_dlfcn_jspi.c | 41 +++++++++++++++++++++++++----- test/core/test_dlfcn_jspi_side.c | 7 +++++ test/core/test_dlfcn_jspi_side_a.c | 9 ++++--- test/core/test_dlfcn_jspi_side_b.c | 7 ++--- 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 test/core/test_dlfcn_jspi_side.c diff --git a/test/core/test_dlfcn_jspi.c b/test/core/test_dlfcn_jspi.c index 81dd074991533..9238a8f0bdd38 100644 --- a/test/core/test_dlfcn_jspi.c +++ b/test/core/test_dlfcn_jspi.c @@ -8,25 +8,52 @@ #include #include -EM_ASYNC_JS(int, test, (), { +EM_ASYNC_JS(int, test_suspending, (), { console.log("sleeping"); await new Promise(res => setTimeout(res, 0)); console.log("slept"); return 77; }); -int test_wrapper() { - return test(); +int test_suspending_wrapper() { + return test_suspending(); } +EM_JS(int, test_sync, (), { + console.log("sync"); + return 77; +}) + +int test_sync_wrapper() { + return test_sync(); +} + + typedef int (*F)(); +typedef int (*G)(F f); -int main() { +void helper(F f) { void* handle = dlopen("side_a.so", RTLD_NOW|RTLD_GLOBAL); assert(handle != NULL); - F side_module_trampolinea = dlsym(handle, "side_module_trampoline_a"); + G side_module_trampolinea = dlsym(handle, "side_module_trampoline_a"); assert(side_module_trampolinea != NULL); - int res = side_module_trampolinea(); - printf("done %d\n", res); + int res = side_module_trampolinea(f); + printf("okay %d\n", res); +} + + +EMSCRIPTEN_KEEPALIVE void not_promising() { + helper(test_sync_wrapper); +} + +EM_JS(void, js_trampoline, (), { + _not_promising(); +}) + +int main() { + helper(test_suspending_wrapper); + js_trampoline(); + printf("done\n"); return 0; } + diff --git a/test/core/test_dlfcn_jspi_side.c b/test/core/test_dlfcn_jspi_side.c new file mode 100644 index 0000000000000..de945dd7ec4ae --- /dev/null +++ b/test/core/test_dlfcn_jspi_side.c @@ -0,0 +1,7 @@ +#include +int test_wrapper(void); + +int side_module_trampoline() { + printf("side_module_trampoline\n"); + return test_wrapper(); +} diff --git a/test/core/test_dlfcn_jspi_side_a.c b/test/core/test_dlfcn_jspi_side_a.c index 528ee9d679b3a..ae9c04be15735 100644 --- a/test/core/test_dlfcn_jspi_side_a.c +++ b/test/core/test_dlfcn_jspi_side_a.c @@ -1,7 +1,10 @@ #include -int side_module_trampoline_b(void); -int side_module_trampoline_a() { +typedef int (*F)(); + +int side_module_trampoline_b(F f); + +int side_module_trampoline_a(F f) { printf("side_module_trampoline_a\n"); - return side_module_trampoline_b(); + return side_module_trampoline_b(f); } diff --git a/test/core/test_dlfcn_jspi_side_b.c b/test/core/test_dlfcn_jspi_side_b.c index 0e86e74425d29..16354428cd417 100644 --- a/test/core/test_dlfcn_jspi_side_b.c +++ b/test/core/test_dlfcn_jspi_side_b.c @@ -1,7 +1,8 @@ #include -int test_wrapper(void); -int side_module_trampoline_b() { +typedef int (*F)(); + +int side_module_trampoline_b(F f) { printf("side_module_trampoline_b\n"); - return test_wrapper(); + return f(); } From 7532906610abf7374f22c0af087d50754cac184d Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 21 Apr 2025 17:37:53 -0400 Subject: [PATCH 22/23] Update test expectation --- test/core/test_dlfcn_jspi.out | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/core/test_dlfcn_jspi.out b/test/core/test_dlfcn_jspi.out index 2b184530b264d..d8633e7f5e78a 100644 --- a/test/core/test_dlfcn_jspi.out +++ b/test/core/test_dlfcn_jspi.out @@ -2,4 +2,9 @@ side_module_trampoline_a side_module_trampoline_b sleeping slept -done 77 +okay 77 +side_module_trampoline_a +side_module_trampoline_b +sync +okay 77 +done From 4fb2c77d3d857e2c19d27b5bcdceadcfd3792ca9 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 21 Apr 2025 17:38:42 -0400 Subject: [PATCH 23/23] Update test expectations --- test/core/test_dlfcn_jspi.c | 2 ++ test/core/test_dlfcn_jspi.out | 2 ++ 2 files changed, 4 insertions(+) diff --git a/test/core/test_dlfcn_jspi.c b/test/core/test_dlfcn_jspi.c index 9238a8f0bdd38..0458ddb5ba550 100644 --- a/test/core/test_dlfcn_jspi.c +++ b/test/core/test_dlfcn_jspi.c @@ -51,7 +51,9 @@ EM_JS(void, js_trampoline, (), { }) int main() { + printf("Suspending test\n"); helper(test_suspending_wrapper); + printf("Non suspending test\n"); js_trampoline(); printf("done\n"); return 0; diff --git a/test/core/test_dlfcn_jspi.out b/test/core/test_dlfcn_jspi.out index d8633e7f5e78a..6b7fe1dbd519a 100644 --- a/test/core/test_dlfcn_jspi.out +++ b/test/core/test_dlfcn_jspi.out @@ -1,8 +1,10 @@ +Suspending test side_module_trampoline_a side_module_trampoline_b sleeping slept okay 77 +Non suspending test side_module_trampoline_a side_module_trampoline_b sync