Closed Bug 1571998 Opened 5 years ago Closed 9 months ago

Implement wasm tail calls

Categories

(Core :: JavaScript: WebAssembly, task, P1)

task

Tracking

()

RESOLVED FIXED
118 Branch
Tracking Status
firefox118 --- fixed

People

(Reporter: wingo, Assigned: yury)

References

(Depends on 1 open bug, Blocks 2 open bugs)

Details

Attachments

(5 files, 11 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

This patch will add parser and validator support for WebAssembly tail calls. Any attempt to compile a function with a tail call will MOZ_CRASH.

We also add a new #define, ENABLE_WASM_TAIL_CALLS, a new configure flag --enable-wasm-tail-calls which is on by default in nightly and off otherwise, and a new run-time flag --wasm-tail-calls which is off by default.

Priority: -- → P3
Assignee: wingo → lhansen
Status: NEW → ASSIGNED

Standard ifdeffery, some simple tests, and some placeholder logic that
implements return_call in terms of call+return. It does run, and will
appear to be correct, given unbounded stack space.

Depends on D138879

Depends on D138898

Attachment #9273039 - Attachment description: WIP: Bug 1571998 - Round up stack argument area 16 (WIP) → WIP: Bug 1571998 - Round up stack argument area size

Also more test cases.

Depends on D144158

Summary: Implement front-end support for wasm tail calls → Implement wasm tail calls
Attachment #9083638 - Attachment is obsolete: true
Attachment #9273396 - Attachment description: WIP: Bug 1571998 - Handle the multiple-value return area in Ion tail calls (WIP) → WIP: Bug 1571998 - Handle the multiple-value return area in Ion tail calls

Uncertain here still about whether more rawCaller / wasmCaller sites need to be handled
in the unwind logic.

Depends on D144399

Some of the code here belongs in the previous patch, because it cleans
up some mechanisms introduced there.

Friday night / pre-long weekend status: All my tests (included in the queue) pass on x86 and x64, but on arm64 there are assertions for test cases with return_call_indirect, so it looks like the unwind information is not right - not a surprise. Other platforms are not supported but arm, mips64, and loong64 will be like arm64, by and large, and there are very few platform dependencies for now.

The base rev is 0914de230f91.

Attachment #9274222 - Attachment description: WIP: Bug 1571998 - Tag and untag the FP at tail call site (WIP) → WIP: Bug 1571998 - Tail calls for the baseline compiler (WIP, but working)
Attachment #9276218 - Attachment is obsolete: true

Depends on D144946

Depends on: 1770688
Depends on: 1770919
Attachment #9264168 - Attachment description: WIP: Bug 1571998 - Tail-call scaffolding + simulate return_call by call+return → WIP: Bug 1571998 - Tail-call scaffolding + simulate return_call by call+return + test cases

Author of syntax and validation tests: Andy Wingo

Depends on D147199

Attachment #9264168 - Attachment description: WIP: Bug 1571998 - Tail-call scaffolding + simulate return_call by call+return + test cases → WIP: Bug 1571998 - Tail-call scaffolding + simulate return_call by call+return
Attachment #9274222 - Attachment description: WIP: Bug 1571998 - Tail calls for the baseline compiler (WIP, but working) → WIP: Bug 1571998 - Tail calls for the baseline compiler

The design document is "WebAssembly ABI 2022" and it outlines a strategy for implementing wasm tail calls without major compiler or ABI changes by executing the initial tail call in a chain of tail calls as a non-tail call (so that our same-instance-biased ABI that requires the caller to perform context restoration after return can continue to be used) and subsequent calls in the chain by collapsing the call frame after call setup and then jumping (thus minimizing compiler changes). Given that most calls take only register arguments this strategy is pretty good. More tweaks are possible for stack arguments; see the design document and comments in the code.

The patch queue on this bug implements the strategy for shared code and for the baseline compiler on all tier-1 platforms. The state of the queue is as follows:

  • The base revision for the patches is df9a51c997b9
  • While the patches are what they are so as to logically separate various ideas and pieces of functionality, it may sometimes be easier to view some changes through the entire patch stack, ie, apply the stack and hg diff -r <baserev>. This may in particular be true for the baseline compiler changes.
  • All test cases pass in the baseline compiler with arbitrary tail-call depths and the baseline code is assumed to be working correctly.
  • There are many optimizations possible in the baseline code, and these will make the generated code quite a bit tighter by removing redundancies. They are noted with TODO comments in the patch.
  • The greatest uncertainty is around unwinding support. The new FP tag needs to be removed during unwinding, and that logic is a little tricky, especially around rawCaller(). See commit message on the unwinding patch. Further insight might be found in patches on bug 1742053, but this is not an easy thing.
  • Ion code still needs to be implemented to correspond to the last baseline patch, and the "Ion sketches" patch is not complete, it really only is a sketch. See the design document for more information about this.
  • In the code, tail calls are variously called "tail calls" (this is what they are) and "return calls" (this is the wasm nomenclature). It would be meaningful to standardize on one or the other. Fixed this: it's return_call for the opcode name and in the opcode reader, "tail call" everywhere else.
Assignee: lhansen → nobody
Status: ASSIGNED → NEW
Assignee: nobody → ydelendik
Status: NEW → ASSIGNED
Severity: normal → S3
Severity: normal → S3
Attachment #9311387 - Attachment description: WIP: Bug 1571998 - WIP: Alternative return calls implementation. → WIP: Bug 1571998 - Alternative return calls implementation.
Depends on: 1816000
Attachment #9278089 - Attachment is obsolete: true
Attachment #9277289 - Attachment is obsolete: true
Attachment #9264168 - Attachment is obsolete: true
Attachment #9273039 - Attachment is obsolete: true
Attachment #9273395 - Attachment is obsolete: true
Attachment #9273396 - Attachment is obsolete: true
Attachment #9278084 - Attachment is obsolete: true
Attachment #9274222 - Attachment is obsolete: true

Changes JS->Wasm stubs logic to expect SP being clobbered by Wasm function.

Changes baseline code to use FP to restore SP to pre-call value.

Attachment #9278089 - Attachment is obsolete: false
Attachment #9311387 - Attachment description: WIP: Bug 1571998 - Alternative return calls implementation. → WIP: Bug 1571998 - Wasm return calls implementation.
Attachment #9312850 - Attachment description: WIP: Bug 1571998 - Alternative return calls implementation for Ion. → WIP: Bug 1571998 - Wasm return calls implementation for Ion.
Attachment #9319571 - Attachment description: WIP: Bug 1571998 - Use FramePointer to restore StackPointer after wasm calls. → Bug 1571998 - Use FramePointer to restore StackPointer after wasm calls. r?rhunt
Attachment #9311387 - Attachment description: WIP: Bug 1571998 - Wasm return calls implementation. → Bug 1571998 - Wasm return calls implementation. r?rhunt
Attachment #9278089 - Attachment description: WIP: Bug 1571998 - Test cases for tail calls → Bug 1571998 - Test cases for tail calls. r?rhunt
Attachment #9326350 - Attachment description: WIP: Bug 1571998 - Wasm return calls spec tests. → Bug 1571998 - Wasm return calls spec tests. r?rhunt
Attachment #9312850 - Attachment description: WIP: Bug 1571998 - Wasm return calls implementation for Ion. → Bug 1571998 - Wasm return calls implementation for Ion. r?jseward

Short description of the current approach:

  1. The wasmCollapseFrame is introduced at masm level: the operation will remove caller/middle frame by moving parameters, instance slots. RA and FP will be used to transfer control to the callee via direct jump.
  2. The return call caller will prepare parameters on the stack, which will still include its own private frame + its parameters, and then proceed with wasmCollapseFrame. This will also guarantee no data will be written before current SP.
  3. Every wasm callsite with slow path will be mark with special carefully selected instruction. During collapse frame, when heap registers and realm is changing, this mark is checked.
  4. In case when the caller of the caller (C0) has a fast path (no heap registers and realm will be recovered), new small frame will be inserted before transferring control to the C0 for the short trampoline that will restore heap registers and realm.
  5. The stack depth will be changing, so for Ion calls it will be required to restore SP based on its FP.
  6. Some consideration has to be taken for the entry stubs (from interpreter or JIT) as well, the SP can be changed, so the entry stub shall anticipate that.
Attachment #9328577 - Attachment is obsolete: true
Attachment #9343294 - Attachment description: WIP: Bug 1571998 - Track unwind info for tail calls. → WIP: Bug 1571998 - Track unwind info for tail calls. r?jseward
Attachment #9343294 - Attachment description: WIP: Bug 1571998 - Track unwind info for tail calls. r?jseward → WIP: Bug 1571998 - Track unwind info for tail calls. r?jseward,canaltinova
Attachment #9343294 - Attachment description: WIP: Bug 1571998 - Track unwind info for tail calls. r?jseward,canaltinova → Bug 1571998 - Track unwind info for tail calls. r?jseward,canaltinova
Attachment #9343294 - Attachment description: Bug 1571998 - Track unwind info for tail calls. r?jseward,canaltinova → Bug 1571998 - Track unwind info for tail calls. r?jseward,mstange
Depends on: 1846534

Comment on attachment 9343294 [details]
Bug 1571998 - Track unwind info for tail calls. r?jseward,mstange

Revision D183269 was moved to bug 1846534. Setting attachment 9343294 [details] to obsolete.

Attachment #9343294 - Attachment is obsolete: true
Pushed by ydelendik@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/8193b332f032
Use FramePointer to restore StackPointer after wasm calls. r=rhunt
https://hg.mozilla.org/integration/autoland/rev/0bc528704114
Wasm return calls implementation. r=rhunt
https://hg.mozilla.org/integration/autoland/rev/4171d4a90a77
Test cases for tail calls. r=rhunt
https://hg.mozilla.org/integration/autoland/rev/b819214797de
Wasm return calls spec tests. r=rhunt
https://hg.mozilla.org/integration/autoland/rev/89a227f6c1ab
Wasm return calls implementation for Ion. r=jseward
Severity: S3 → N/A
Type: enhancement → task
Priority: P3 → P1
Regressions: 1846730
Depends on: 1846795
Regressions: 1846911
Regressions: 1846936
Depends on: 1847330
Regressions: 1847480
Regressions: 1847478
Depends on: 1849759
Blocks: 1846795
No longer depends on: 1846795
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: