-
Notifications
You must be signed in to change notification settings - Fork 266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Emscripten jmp support in indirect function calls (invoke_xxx) #1611
Implement Emscripten jmp support in indirect function calls (invoke_xxx) #1611
Conversation
8d6c9fa
to
4ab68da
Compare
I think the tests currently fail because the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I assume the same from the failing tests.
stackSave
seems easy to stub out (do nothing), stackRestore
I have no idea if it's safe to just ignore.
Can you attach a wasm from built from your sample so can avoid figuring out how to build it? 😳 |
I think in the current tests both are safe to stub out, as the tests won't end up in the error branch. If we would make a separate test for the jumps we would have to implement them.
Here you go, compiled with latest emscripten using |
I think a better implementation would be as such: // Lookup the table index we will call.
t := m.Tables[0] // Note: Emscripten doesn't use multiple tables
f, err := m.Engine.LookupFunction(t, typeID, tableOffset)
if err != nil {
panic(err)
}
// Call: savedStack = stackSave()
var savedStack [2]uint64
err = mod.ExportedFunction("stackSave").CallWithStack(ctx, savedStack[:])
if err != nil {
panic(err) // stackSave failed
}
err = f.CallWithStack(ctx, stack)
if err != nil {
// Module closed: any calls will just fail with the same error
if _, ok := err.(*sys.ExitError); ok {
panic(err)
}
// Call: stackRestore(savedStack)
if err := mod.ExportedFunction("stackRestore").CallWithStack(ctx, savedStack[:]); err != nil {
panic(err) // stackRestore failed
}
if !errors.Is(err, ThrowLongjmpError) {
panic(err) // f failed
}
// Call: setThrew(1, 0)
savedStack[0] = 1
savedStack[1] = 0
err = mod.ExportedFunction("setThrew").CallWithStack(ctx, savedStack[:])
if err != nil {
panic(err) // setThrew failed
}
} This uses More importantly: And it's pointless to call |
My changes, including updating tests so |
OK, so, sorry for the noise, but here's another idea: what if we just skip the entire dance if |
Fine with me, but it should never be nil if it comes into the invoke call (except for not real emscripten like the Wazero tests).
These changes sound good to me! |
Want to integrate them in your branch? Not sure I can. |
cbf94a1
to
4195138
Compare
it seems the failing tests legit but not directly relevant to this change (I guess it's something to do with unsafe.pointer/uintptr cast thingy) |
no luck so far. The only thing I can say is this is not compiler specific (happens to interpreter as well), but I hanve't been able to reproduce |
d7cfbcd
to
5d12187
Compare
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
…s about Emscripten implementation details Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
8f39227
to
f95ece8
Compare
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Otherwise, the table address might change and dangerous Signed-off-by: Takeshi Yoneda <[email protected]> Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Takeshi Yoneda <[email protected]> Signed-off-by: Jeroen Bobbeldijk <[email protected]>
This reverts commit 67b901a. Signed-off-by: Takeshi Yoneda <[email protected]> Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
f95ece8
to
47dd029
Compare
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
Signed-off-by: Jeroen Bobbeldijk <[email protected]>
This PR implements Emscripten jmp support from indirect function calls, which we have missed before. We missed this mainly due to me lazily patching out Emscripten methods in standalone builds, in this case
_emscripten_throw_longjmp
, which is a pretty vital part of doing setjmp/longjmp from indirect function calls.How that seems to work in the JS version:
longjmp
from an indirect function call_emscripten_throw_longjmp
, which is a host method (https://github.com/emscripten-core/emscripten/blob/6b6f7e7ed4aa8c1f2232443403fc8491056b01f6/system/lib/compiler-rt/emscripten_setjmp.c#L69),_emscripten_throw_longjmp
type, it rethrows the errorsetThrew
, probably to reset the throw status in C, because it wasn't actually a throw, it was a longjmpI have tried to implement it in a very similar way in Wazero, but I have to say that I'm not aware of any edge cases where this does not work.
Sample C code: