ReviewOS

zig-utils/zig-js

Compiler: preserve proper tail calls in nested concise arrows

#1101
Closed glennmichael123 opened this 8 days ago ·
8 days ago

Summary

Nested synchronous concise arrows lose proper-tail-call lowering when compiled as function templates. The standalone plain-function path calls compileTailExpr, but Compiler.compileFunction currently lowers an expression body with compileExpr followed by ret. A strict recursive concise arrow therefore grows the native call stack in required-VM mode.

Parent roadmap: #491 Related bytecode eligibility work: #465 Related expression tier-agreement tranche: #1099

Reproduction

"use strict";
var recurse;
recurse = (n) => n === 0 ? 42 : recurse(n - 1);
recurse(20000);

Current zig-js:

  • tree walker: 42
  • required VM: RangeError: Maximum call stack size exceeded.

Oracles on the same machine:

  • JavaScriptCore: 42
  • Node: RangeError (Node does not implement optional proper tail calls)

Root cause

compilePlainFunctionInner lowers concise bodies through compileTailExpr, while nested plain templates in Compiler.compileFunction use compileExpr plus ret. The nested template retains is_arrow = true and is_strict = true, but its bytecode contains no tail-call opcode.

Definition of done

  • Nested strict concise arrows use canonical compileTailExpr lowering.
  • Sloppy arrows retain ordinary call semantics.
  • Async concise arrows remain excluded from proper-tail-call lowering.
  • Deep recursion agrees between tree walker and required VM.
  • Compiler-shape and end-to-end regression coverage pass under normal and TSan/GC-focused gates.
8 days ago

Fixed in 8c672e9 and pushed to origin/main.

The nested concise-arrow template now lowers expression bodies through canonical compileTailExpr, preserving tail_call/tail_call_with_this opcodes. The regression covers compiler shape plus a 20,000-deep strict recursive arrow.

Verification on the rebased tree:

  • JavaScriptCore: ok:42; Node: RangeError (Node lacks optional PTC)
  • forced tree and required VM: both return 42
  • focused Debug root gate: 4/4 passed
  • focused TSan root gate: 4/4 passed, no race report
  • full test262 expression tier witness: 0 diverge, 11038 agree
  • affected TCO gates: statements 16/16 and expressions 16/16 with 0 failures/divergences

Closing this child as complete.

8 days ago

Closed by 8c672e9; definition of done verified on the rebased main tree.

Sign in to comment on this issue.