Conversation
| // Helper passes that can be run after Asyncify. | ||
|
|
||
| template<bool neverRewind, bool neverUnwind, bool importsAlwaysUnwind> | ||
| struct PostAsyncify |
There was a problem hiding this comment.
If I'm understanding this at a high level, these are passes that run on already-asyncified code, in order to bake in assumptions about when the code is called, so we can optimize the runtime overhead away.
I'm not sure if "post asyncify" is a great name for this pass. That just says "this runs afterward" but doesn't explain why, or what it does. In particular it seems reasonable to assume that PostAsyncify always runs and does some sort of necessary fixup, rather than optimizing.
So maybe "optimize asyncify"? That's not quite right either because it misses the connotation of baking in assumptions.
Similarly, there's three bools here, but we only instantiate it two ways. Another way to factor this is as explicitly supporting the lazy-load case, and then the pass can be called "lazy load asyncify", parameterized on whether this is the loader or the loadee. If this is expected to be more general, and have options or configurations added, it would make sense to go the other way and have this take an options struct (or bitfield of flags) to keep the parameter list shorter.
There was a problem hiding this comment.
Yeah, that's a good point, "post" is not clear enough.
I think this is more general than lazy loading, though, so I'd prefer something more general somehow.
Maybe PostAsyncify => AsyncifyAssume because it bakes assumptions into asyncified code?
|
Interesting, I force-pushed this branch, and it seems to hit a github bug where it closed the PR as if it was merged... which it was not. |
|
..and it can't be reopened :) Opening a new PR... |
|
.. but I can't open a new PR as it thinks this code was already merged :( |
These two passes are meant to be run after Asyncify has been run. One pass assumes that we will unwind if we reach an import, but never rewind. The other pass assumes that we may rewind but will never unwind.
This is meant to help with lazy code loading, that is, the ability for an initially-downloaded wasm to not contain all the code, and if code not present there is called, we download all the rest and continue with that. That could work something like this:
--post-asyncify-always-and-only-unwind: if the special import for lazy code loading is called, we will definitely unwind, and we won't rewind in this binary.--post-asyncify-never-unwind: we will rewind into this binary, but no longer need support for unwinding.These
--post-asyncifypasses allow the optimizer to do a lot of work, especially for the initially downloaded wasm if we have lots of calls to the lazy code loading import. In that case the optimizer will see that those calls unwind, which means the code after them is not reached, potentially making lots of code dead and removable.This requires some runtime code to load the second wasm etc., which for Emscripten I'll implement in a PR there, but in principle this could be used in other runtimes too, just like Asyncify itself.
cc @surma @RReverser