Rebase JS promise integration onto stack switching proposal
Categories
(Core :: JavaScript: WebAssembly, task, P1)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox151 | --- | fixed |
People
(Reporter: rhunt, Assigned: rhunt)
References
(Blocks 2 open bugs)
Details
Attachments
(8 files, 17 obsolete files)
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
557.77 KB,
patch
|
Details | Diff | Splinter Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
In the process of reviewing and refactoring our JS-PI implementation I've rewritten most of the code. The new version implements a subset of the core stack switching proposal [1] and uses that in self-hosted code to implement the JS-PI interfaces.
Some things improved:
- The old implementation would give incorrect stack traces when you switched to the main thread
- Suspendable stack memory now has guard pages before/after the allocation
- Lots of comments, documentation, and assertions
- Tracing is a little bit simpler
| Assignee | ||
Comment 1•1 month ago
|
||
| Assignee | ||
Comment 2•1 month ago
|
||
| Assignee | ||
Comment 3•1 month ago
|
||
| Assignee | ||
Comment 4•1 month ago
|
||
| Assignee | ||
Comment 5•1 month ago
|
||
| Assignee | ||
Comment 6•1 month ago
|
||
| Assignee | ||
Comment 7•1 month ago
|
||
Updated•1 month ago
|
Updated•1 month ago
|
Updated•1 month ago
|
Updated•1 month ago
|
Updated•1 month ago
|
Updated•1 month ago
|
| Assignee | ||
Comment 8•1 month ago
|
||
These patches are almost ready, I just need to find some way to split the second-to-last patch into more reviewable chunks. It's tricky though, it's all connected.
| Assignee | ||
Comment 9•1 month ago
|
||
| Assignee | ||
Comment 10•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Add ContStack, ContObject, Handlers, Handler, StackTarget, and SwitchTarget.
Update wasm::Context to track the set of created ContStacks, the current
ContStack, the base Handlers, and the current stack limits.
See the big [SMDOC] for an overview of the architecture.
| Assignee | ||
Comment 11•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Add builtins for creating builtins and unwinding a handler.
| Assignee | ||
Comment 12•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Adds a 'ThrowSuspendError' trap that will be used later.
Adds a 'Unimplemented' trap that will be used later.
| Assignee | ||
Comment 13•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
A DebuggerFrame can point at a wasm frame using a cloned FrameIter object. The
FrameIter is tied to the activation the wasm frame lived in. If a wasm frame is
suspended on a continuation and no longer has an activation, the FrameIter is
invalid and cannot be used anymore.
JS-PI previously handled this by iterating the stack to search for debugger
frames to detach, and then reattach on resume. This patch takes an alternate
approach the changes a DebuggerFrame created for a frame on a continuation to
have a 'WASM_FRAME_PTR_SLOT' instead of 'FRAME_ITER_SLOT'. The AbstractFramePtr
is used lazily to re-create a FrameIter. We also return false for isOnStack
if the frame is suspended.
| Assignee | ||
Comment 14•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Continuations are not exposable across the JS boundary, but technically
a null can still be passed to a nullable contref.
One hack here is that JS-PI has a builtin which takes a contref,
which uses these functions. So we allow the contref through even
though we technically shouldn't. We will need a proper solution
before we ship stack-switching.
| Assignee | ||
Comment 15•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
JS-PI will need a globally defined JS Promise Tag type which can
be used for passing a promise to react to and resume the
continuation.
| Assignee | ||
Comment 16•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
See the [SMDOC] in WasmStacks.cpp for more details.
| Assignee | ||
Comment 17•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
ProfilingFrameIter needs to be aware of continuations. It must
know how to handle the ContBaseFrame which links the continuation
stack to the previous stack.
| Assignee | ||
Comment 18•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
- Rework the dynamic switch to the main stack
- Push 2 slots for saving/restoring the (baseHandlers, currentStack)
- Move alignment handling into GenerateExit* to centralize the logic
- Remove the wasmExitSuspender on JitActivation
- No longer needed for saving/restoring from main stack switches, we have
the dedicated slots. - Use wasm::Context to find a continuation whenever you have an FP
- No longer needed for saving/restoring from main stack switches, we have
- Update FrameIter to support continuations
- ContBaseFrame unwinding
- Tracking the current continuation stack
| Assignee | ||
Comment 19•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Add tracing for continuation stacks.
When a stack is active, it will be found and traced through the normal
FrameIter loop.
When a stack is suspended, we need to manually trace it. See the
[SMDOC] in WasmStacks.cpp for the full GC considerations.
| Assignee | ||
Comment 20•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Add a resume barrier builtin which immediately traces a suspended
stack if an incremental GC is in progress. This ensures all stack
slots have been traced before an unbarriered write could happen
to them.
| Assignee | ||
Comment 21•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Update unwinding so it:
- destroys an active stack when we unwind over it
- switches to an active stack when it catches an exception
| Assignee | ||
Comment 22•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Add
- MWasmFindHandler - searches for a handler that matches a tag
- MWasmSuspend - suspends the current continuation and jumps to a handler
- MWasmResume - resumes a suspended continuation
All of these will call masm helpers in WasmStacks.cpp to do
the actual work. This will happen in the next patch.
Anything that's not supported yet will result in an unimplemented
trap in ion.
| Assignee | ||
Comment 23•1 month ago
|
||
This commit doesn't compile on it's own. It has been split for ease-of-review.
Add the masm helpers for FindHandlers, Suspend, and Resume.
| Assignee | ||
Comment 24•1 month ago
|
||
This commit now finally compiles and passes tests.
Update the self-hosted JS-PI code to use stack-switching instructions,
and remove the previous instructions. The comments are updated for the
new structure of the suspending/promising modules.
Some of the JS-PI promise builtins were re-organized too.
Updated•1 month ago
|
| Assignee | ||
Comment 25•23 days ago
|
||
This commit was split into easier to review parts that don't compile on their
own and then merged back together. The following are the commit messages for
the pieces.
- Add basic continuation types.
Add ContStack, ContObject, Handlers, Handler, StackTarget, and SwitchTarget.
Update wasm::Context to track the set of created ContStacks, the current
ContStack, the base Handlers, and the current stack limits.
See the big [SMDOC] for an overview of the architecture.
- Add continuation builtins.
Add builtins for creating builtins and unwinding a handler.
- Add new errors messages and traps.
Adds a 'ThrowSuspendError' trap that will be used later.
Adds a 'Unimplemented' trap that will be used later.
- Rework debugger integration.
A DebuggerFrame can point at a wasm frame using a cloned FrameIter object. The
FrameIter is tied to the activation the wasm frame lived in. If a wasm frame is
suspended on a continuation and no longer has an activation, the FrameIter is
invalid and cannot be used anymore.
JS-PI previously handled this by iterating the stack to search for debugger
frames to detach, and then reattach on resume. This patch takes an alternate
approach the changes a DebuggerFrame created for a frame on a continuation to
have a 'WASM_FRAME_PTR_SLOT' instead of 'FRAME_ITER_SLOT'. The AbstractFramePtr
is used lazily to re-create a FrameIter. We also return false for isOnStack
if the frame is suspended.
- Add ToJSValue/ToWebAssemblyValue support for cont.
Continuations are not exposable across the JS boundary, but technically
a null can still be passed to a nullable contref.
One hack here is that JS-PI has a builtin which takes a contref,
which uses these functions. So we allow the contref through even
though we technically shouldn't. We will need a proper solution
before we ship stack-switching.
- Add JS Promise Tag.
JS-PI will need a globally defined JS Promise Tag type which can
be used for passing a promise to react to and resume the
continuation.
- Add cont base frame stubs.
See the [SMDOC] in WasmStacks.cpp for more details.
- Update ProfilingFrameIter.
ProfilingFrameIter needs to be aware of continuations. It must
know how to handle the ContBaseFrame which links the continuation
stack to the previous stack.
- Frame unwinding and dynamic switches.
- Rework the dynamic switch to the main stack
- Push 2 slots for saving/restoring the (baseHandlers, currentStack)
- Move alignment handling into GenerateExit* to centralize the logic
- Remove the wasmExitSuspender on JitActivation
- No longer needed for saving/restoring from main stack switches, we have
the dedicated slots. - Use wasm::Context to find a continuation whenever you have an FP
- No longer needed for saving/restoring from main stack switches, we have
- Update FrameIter to support continuations
- ContBaseFrame unwinding
- Tracking the current continuation stack
- Tracing for continuation stacks.
When a stack is active, it will be found and traced through the normal
FrameIter loop.
t rebase --continue
When a stack is suspended, we need to manually trace it. See the
[SMDOC] in WasmStacks.cpp for the full GC considerations.
- Add resume barrier.
Add a resume barrier builtin which immediately traces a suspended
stack if an incremental GC is in progress. This ensures all stack
slots have been traced before an unbarriered write could happen
to them.
- Update unwinding for continuation stacks.
Update unwinding so it:
- destroys an active stack when we unwind over it
- switches to an active stack when it catches an exception
- Add MIR/LIR nodes for stack switching.
Add
- MWasmFindHandler - searches for a handler that matches a tag
- MWasmSuspend - suspends the current continuation and jumps to a handler
- MWasmResume - resumes a suspended continuation
All of these will call masm helpers in WasmStacks.cpp to do
the actual work. This will happen in the next patch.
Anything that's not supported yet will result in an unimplemented
trap in ion.
- Add codegen for stack switching instructions.
Add the masm helpers for FindHandlers, Suspend, and Resume.
- Update JS-PI to use stack-switching.
Update the self-hosted JS-PI code to use stack-switching instructions,
and remove the previous instructions. The comments are updated for the
new structure of the suspending/promising modules.
Some of the JS-PI promise builtins were re-organized too.
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Updated•23 days ago
|
Comment 26•22 days ago
|
||
Comment 27•22 days ago
|
||
Comment 28•22 days ago
|
||
Backed out for causing SM bustages @CodeGenerator-shared.h.
| Assignee | ||
Comment 29•22 days ago
|
||
Mid-aired with a change to OOM handling with LambdaOutOfLineCode.
Comment 30•22 days ago
|
||
Comment 31•22 days ago
|
||
Comment 32•22 days ago
|
||
Backed out for causing build bustages @WasmStacks.cp.
| Assignee | ||
Comment 33•22 days ago
|
||
Non-unified build bustage on Win64 (didn't know we had that job)
Comment 34•22 days ago
|
||
Comment 35•22 days ago
|
||
Comment 36•22 days ago
|
||
Backed out for causing sm bustages @many-outstanding.js.
- Backout link
- Push with failures
- Failure Log@many-outstanding.js.
- Failure Log @harness.js
| Assignee | ||
Comment 37•22 days ago
|
||
A real failure in concurrent marking. I thought that was tier-2 though? I can try and figure out what's going on with it. The CGC issue looks unrelated.
| Assignee | ||
Comment 38•20 days ago
|
||
The wasm JS-PI resume barrier calls PerformIncrementalPreWriteBarrierAllChildren
to trace a suspended continuation's stack before resuming it, maintaining the
incremental GC snapshot-at-beginning invariant. It skipped this work if the
ContObject was already marked black, assuming its children had been traced.
With concurrent marking, this assumption is wrong. The background marking thread
marks objects black upon discovery but defers trace hooks to a main-thread buffer
(mainThreadBuffer) which is only drained during the next GC slice. A ContObject
can therefore be black while its trace hook hasn't yet run, meaning the suspended
stack's GC references are untraced. When the resume barrier saw isMarkedBlack()
and returned early, those references could be collected, causing a SIGSEGV when
wasm code later accessed them.
Fix by only skipping the barrier when the Concurrent barrier flag is not set.
This flag is set during incremental GC with concurrent marking enabled, exactly
the condition under which black objects may have unprocessed trace hooks.
Updated•19 days ago
|
Comment 39•18 days ago
|
||
Comment 40•18 days ago
|
||
| Assignee | ||
Comment 42•17 days ago
|
||
Ugh. Intermittent issue in CGC builds (didn't show up in my previous try pushes). The issue is real and serious though.
The saved stack slots in the trap exit were being statically addressed through FP, which is totally incorrect (trap exit runs at a dynamic offset from FP, not static). This resulted in us writing a random 0 word into the stack. For some reason this only showed up on that one asm.js test with CGC (CGC triggers interrupts which uses the trap exit). The fix is to use SP to address the stack slots.
| Assignee | ||
Comment 43•17 days ago
|
||
Comment 44•17 days ago
|
||
Comment 45•17 days ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/84fd26e25744
https://hg.mozilla.org/mozilla-central/rev/18f387555b03
https://hg.mozilla.org/mozilla-central/rev/1363afeac631
https://hg.mozilla.org/mozilla-central/rev/ea5cd32a383c
https://hg.mozilla.org/mozilla-central/rev/6d71954ff221
https://hg.mozilla.org/mozilla-central/rev/18304ad58d24
https://hg.mozilla.org/mozilla-central/rev/b419da3aa6b0
| Assignee | ||
Updated•17 days ago
|
Updated•11 days ago
|
Description
•