Fix late-binding symbols with JSPI (implementation 2)#24161
Fix late-binding symbols with JSPI (implementation 2)#24161hoodmane wants to merge 2 commits intoemscripten-core:mainfrom
Conversation
Late-binding symbols get a JS stub import that resolves the symbol and then makes an onward call. This breaks JSPI. This is a second approach to solving the problem by using WebAssembly.promising and WebAssembly.Suspending with a JS trampoline. Unfortunately, as far as I can tell there is no way to make it work for both a promising entrypoint and a non-promising entrypoint. This is due to a change in the JSPI spec: early versions said that if a suspending import does not return a promise, the suspender was allowed to be null. However, the new version of JSPI eagerly traps if the suspender is null, even if the function does not return a promise.
| } | ||
|
|
||
| EM_JS(void, js_trampoline, (), { | ||
| _not_promising(); |
There was a problem hiding this comment.
There was a problem hiding this comment.
Interesting, thanks... sounds like the JSPI spec changed and I haven't followed that closely.
@brendandahl is there some workaround for this issue?
If not, it sounds like this approach would need to add all late-binding symbols to JSPI_EXPORTS..?
There was a problem hiding this comment.
I think what would be needed would be to add all C functions that might call late-binding symbols to JSPI_EXPORTS? In this case the problem is fixed by adding -sJSPI_EXPORTS=not_promising.
If we wanted to go this way, we should probably make all exports JSPI_EXPORTS.
There was a problem hiding this comment.
One thing we could do is make a selector function with body like:
try (result restype)
local.get 0
local.get 1
call suspendingTrampoline
catch $SuspendError
local.get 0
local.get 1
call nonsuspendingTrampoline
endand then make both a suspending and nonsuspending version of the stub. But this still forces us to do most of the painful stuff in #23619 where we calculate the type and generate a dynamic wasm module.
Late-binding symbols get a JS stub import that resolves the symbol and then makes an onward call. This breaks JSPI.
This is a second approach to solving the problem by using WebAssembly.promising and WebAssembly.Suspending with a JS trampoline. Unfortunately, as far as I can tell there is no way to make it work for both a promising entrypoint and a non-promising entrypoint. This is due to a change in the JSPI spec: early versions said that if a suspending import does not return a promise, the suspender was allowed to be null. However, the new version of JSPI eagerly traps if the suspender is null, even if the function does not return a promise.