You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Stack Switching] Add basic support for resume/suspend in the interpreter (#7771)
It turns out we can implement suspend/resume on the current
interpreter with only a small amount of changes, basically using
the same idea as Asyncify: pause and resume structured control
flow by rewinding the stack in a "resume" mode that skips normal
execution. That is, this does not use a program counter (no goto),
nor continuation-passing style, and instead adds interpreter
support to unwind and rewind the stack. This is not the fastest
way to do things, but it is the simplest by far.
The basic idea is the same as in this 2019 blogpost:
https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html
This is quite efficient in the things we care about: suspend/
resume is slow, but normal execution hardly regresses, which is
important to keep the Precompute pass from getting slower.
While the more intrusive experiment #7762 made that pass 2x
slower, this only adds 10-15% overhead. The main reason is that
this pass keeps us down to a single indirect call per instruction,
while e.g. separating decoding and execution - to maintain a
normal value stack - ends up doing two indirect calls. The "trick"
in this PR is that, yes, we do need a value stack (that is the only
practical way to stash the values on the stack when suspending),
but we can populate that stack only when inside a coroutine
(when we might suspend). So we still use the normal way of
getting child instruction values - just calling `visit(curr->child)`
from the parent's `visitFoo()` method - and do not lose that
speed, but still have a stack of values when we need it.
(10-15% is still significant, but it is just on a single pass, so it
seems acceptable, and there might be ways to optimize this further.)
Notes:
* Flow now has a "suspendTag" property, which denotes the tag we are
suspending, when we suspend.
* As part of this change, `callFunction` in the interpreter returns a
Flow, so that we can propagate suspensions out of functions.
* For testing, this adds `assert_suspension` support in `wasm-shell`.
* For testing, add part of `cont.wast` from the test suite, and minor
fixes for it in `wasm.cpp`.
* This only adds basic support: `resume_throw` and various other parts
of the stack switching proposal are TODOs, but I think this PR does the
hard parts.
0 commit comments