Skip to content

Forward pointer-union wraps of call arguments to the callee's parameter proof - #2048

Merged
ctate merged 2 commits into
mainfrom
ctate/forward-pointer-union-e3cb4f
Oct 24, 2026
Merged

ctate merged 2 commits into
mainfrom
ctate/forward-pointer-union-e3cb4f

Conversation

@ctate

@ctate ctate commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator
  • A record or instance wrapped into a nullable-pointer union at a call (T | undefined, T | null) passes its pointer unchanged, so the call-lifetimes analysis now forwards it to the callee's parameter proof like the bare binding; callees that only read the argument let it keep its frame storage and result slot.
  • value-objects runs 16.2% faster (95% CI −16.7% .. −15.7%) with 20.9% fewer instructions and no size change; the other runtime workloads and the self-built TypeScript compiler are unchanged.

…er proof

A call argument that wraps a binding into a nullable-pointer union passes
the binding's pointer itself. The call-lifetimes analysis now treats it
like the bare binding, so a record or instance passed to a `T | undefined`
parameter that is only projected keeps its frame storage and result slot.
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
scriptc Ready Ready Preview, v0 Oct 24, 2026 6:28am UTC

@vercel-security-reviewer

Copy link
Copy Markdown

Security review details

Comment thread packages/compiler/src/backend/llvm/call-lifetimes.ts Outdated
@ctate ctate changed the title Forward pointer-union wraps of call arguments to the callee's Forward pointer-union wraps of call arguments to the callee's parameter proof Oct 23, 2026
… narrowed payload

A union parameter's proof covered the union, not its payload: narrowing it
and storing, returning or pushing the result, a narrowed nullish read, and a
store into a nullable-pointer field all counted as projections. That holds
for a boxed union, whose payload is a separate object. A record passed
through a nullable-pointer union is that payload, so forwarding it to such a
callee let a record in its caller's frame escape the frame.

A pointer-wrapped argument now needs a second fact from the callee's union
parameter: its payload stays in place too. The payload is in place when it
is only tested, narrowed for a field read (directly or through the checked
narrowing a field read of a `T | undefined` parameter compiles to), or passed
on to a parameter that is proved in turn. The facts that other arguments use
are unchanged.

Corpus 7663 has callees that push (directly and through a non-null
assertion), default, store in a global record field or a class field, or
pass on the narrowed record, and one that only reads it.
@ctate
ctate merged commit 0e0bedc into main Oct 24, 2026
63 of 66 checks passed
@ctate
ctate deleted the ctate/forward-pointer-union-e3cb4f branch October 24, 2026 06:56

This branch was successfully deployed

1 active deployment
Preview — 9496e429 Deployed Oct 24, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant