-
Notifications
You must be signed in to change notification settings - Fork 745
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
Support try-catch blocks in Asyncify. #5143
Conversation
Convert (try (...) catch $i (...)) into (try (...) catch $i (set tag 1)) (if (or (eq tag 1) (rewinding)) (...))
Good point. I think converting all the Edit: except this doesn't work for |
One idea I had (not sure if it make sense) is to re-run the throw. We sort of do that for calls - we have to re-run calls so that the call stack is rewound, and only after that can we resume execution from there. So perhaps similarly we could re-run relevant throws, which would have the effect of recreating the "exception state"..? |
A rethrow in an important catch_all block is a lost cause. This mishandles rethrows in catch blocks when the exception has arguments. Need to futz around with multivalues.
Every throw would have to throw the original value and also a full set of Asyncify unwind data describing how to get back to the throw (including the data for any previous throws). This data would have to be collected eagerly, since there would be no way to go back and collect it at the suspension point. I think it would be simpler to lower away EH entirely before applying the Asyncify transformation. |
For If we could save |
Yeah, exception references would have made this simpler, but they were removed from the final EH spec and do not exist. |
I pushed a sketch dealing with rethrows in catch but not catch_all blocks, but I don't see a way to handle the full exception handling WebAssembly feature, so I'm closing this PR. |
Makes sense. This is very hard to do in Asyncify. I guess the solutions are either
|
How do you lower away EH? Do you mean removing landingpads like |
No, I mean a binaryen pass to lower away EH but preserve semantics as much as possible, probably by instrumenting functions to return an extra value signaling an exception and instrumenting all function calls to check that value. Exception payloads could go on a stack in a second memory or could be stored in GC data. This lowering could not possibly do the right thing for exceptions entering the module from the outside, but that might be ok for some use cases where the only exceptions are expected to come from the Wasm module itself. |
You think we can handle |
Yeah, I think so. If we take all the engine-internal state from the EH proposal and put it in a secondary memory or in GC objects, then we should have everything we need to implement |
How can we access the engine-internal state from user code? |
If we lower away EH in a Binaryen pass, there won't be any EH-internal state at runtime. It will all be stored in data locations introduced by the Binaryen pass instead. |
To lower away EH in Binaryen, we need to access the engine-internal state to make |
By “take all the engine-internal state from the EH proposal and put it in a secondary memory or in GC objects” I meant “lower EH operations so that what would have been engine-internal state at runtime will instead be user-level state in a secondary memory or in GC objects.” |
So, exceptions is not supported with asyncify? |
Wasm exceptions don't work with Asyncify, correct. The older "emscripten exceptions" (using JS) do work. Reopening as this is worth working on. |
Actually we should have an issue open for this, not a PR. Closing this, will open an issue. |
Previously, when the Asyncify pass ran on a wasm file that includes try blocks (in a position such that asyncify has to un/re-wind through those try blocks), an error would be produced:
WASM_UNREACHABLE("unexpected expression type");
This PR adds support for the try case in Asyncify.
Fixes #4470
I was not sure how to add tests for this feature to the repository; it runs without crashing and produces reasonable-looking output on one sample file I have. This feature deserves tests: if someone will explain how to add them I will.
This should have no effect on previously successful applications of Asyncify (the behavior change here is from a crash to producing code), but if the implementation is wrong could produce broken code.
Convert
into