Unify module splitting implementation for JSPI#26396
Unify module splitting implementation for JSPI#26396brendandahl merged 4 commits intoemscripten-core:mainfrom
Conversation
Previously, module splitting with JSPI required a special built-in function `__load_secondary_module` and wasm-split setting to coordinate the loading of the secondary module. This change updates the `splitModuleProxyHandler` to support JSPI by wrapping the generated placeholder functions in `WebAssembly.Suspending`. The placeholder will then automatically load the secondary module asynchronously. A standalone `save_profile_data.js` script is extracted from existing tests for reuse, and a new test `test_split_module_embind_jspi` is added to ensure module splitting functions correctly alongside embind and JSPI.
|
For some more context: The old version of JSPI required changes to wasm so this new approach wasn't possible. |
aheejin
left a comment
There was a problem hiding this comment.
Sorry for the delay!
By the way, what made this possible? In other words, why did we have to resort to __load_secondary_module function before and not anymore?
| @@ -0,0 +1,2 @@ | |||
| deferred_function: [object Promise] | |||
| deferred_function await: 82 No newline at end of file | |||
There was a problem hiding this comment.
And it's a little weird that we have this here as a file and we also check this in the code after the split:
self.assertIn('primary_function: 42\n' +
'Custom handler for loading split module.\n' +
'deferred_function: [object Promise]\n' +
'deferred_function await: 82', result)How about checking both of the cases (before and after the split) in code to be consistent? Also they have a slightly different outputs, so..
There was a problem hiding this comment.
I moved it all into the test now. The pre/post part should be the same now with only the middle being different.
Co-authored-by: Heejin Ahn <aheejin@gmail.com>
When JSPI was first introduced there was a concept of a "suspender object" that had to be passed around in wasm as an argument. To handle that we had to run a binaryen pass to modify the wasm and change the export/import signatures. I forget the details, but something about that caused issues with the proxy and replacing the function with a different signature. Anyway, JSPI was changed to be fully on the JS side so nothing in Wasm needed to change. That made it easier to dynamically adjust what will have JSPI wrappers at runtime and just inject them in the proxy object that the original split used. |
| '--enable-mutable-globals', '--enable-bulk-memory', '--enable-nontrapping-float-to-int', | ||
| '--export-prefix=%', 'test_split_module.wasm.orig', '-o1', 'primary.wasm', '-o2', 'secondary.wasm', '--profile=profile.data'] | ||
| if jspi: | ||
| wasm_split_run += ['--jspi', '--enable-reference-types'] |
There was a problem hiding this comment.
Does this mean we can delete this binaryen pass now too?
Previously, module splitting with JSPI required a special built-in function
__load_secondary_moduleand wasm-split setting to coordinate the loading of the secondary module.This change updates the
splitModuleProxyHandlerto support JSPI by wrapping the generated placeholder functions inWebAssembly.Suspending. The placeholder will then automatically load the secondary module asynchronously.A standalone
save_profile_data.jsscript is extracted from existing tests for reuse, and a new testtest_split_module_embind_jspiis added to ensure module splitting functions correctly alongside embind and JSPI.