Skip to content

Perf: per-function-scope candidacy in ArrayLocalPromotionAnalyzer#871

Merged
nickna merged 1 commit into
mainfrom
wrk/array-promotion-per-scope
Jun 21, 2026
Merged

Perf: per-function-scope candidacy in ArrayLocalPromotionAnalyzer#871
nickna merged 1 commit into
mainfrom
wrk/array-promotion-per-scope

Conversation

@nickna

@nickna nickna commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Part of #856 (perf epic). Prerequisite for the array-methods typed-HOF-pipeline work.

Problem

The typed-array-local promotion (#857/#860) keyed candidacy whole-program per lexeme. A clean push/[i]/.length array was poisoned by an unrelated, escaping array of the same name elsewhere — another function, or another module in a bundle. So common array names (arr, data, items, result) routinely failed to promote in real multi-module programs; the optimization only landed when the name happened to be globally unique. (This is the same latent bug fixed for strings in #870 — surfaced there because stringWork's s collided with perf_hooks's const s.)

Fix

Key candidacy/disqualification by (function scope, lexeme): each Stmt.Function/Expr.ArrowFunction body is its own scope (module top level is scope 0), mirroring StringAccumulatorPromotionAnalyzer. Cross-scope references are captures, already handled by the IsVariableCaptured guard. Use-site emission is slot-type-keyed (so it's inherently scope-correct), which makes promoting more arrays safe.

Effect (IL-verified)

A clean const xs = [] (push/index/length) now promotes to List<double> even when another function has an escaping const xs — previously both stayed boxed/$Array. No change where names were already unique (e.g. count-primes' isPrime).

Tests / validation

  • ArrayLocalPromotionTests: +1 per-scope name-collision case; 24/24 green (both modes), no regression in the existing cases.
  • Full dotnet test: 13968 passed, 0 real regressions (the only failures are 2 tests that pass in isolation under parallel load, plus the documented stale Test262 baselines — drift is Array.isArray/proxy, present in interpreter mode too, i.e. unrelated to this compile-only change).
  • --verify passes on the promoted output.

Context

Step 1 of docs/plans/issue-861-array-methods-typed-pipeline.md (the last remaining benchmark gap, array-methods @ 2.79× Node). Common array names must promote before HOF receivers can be kept typed.

The typed-array-local promotion (#857/#860) keyed candidacy/disqualification
whole-program per lexeme: a clean push/index/length array was poisoned by an
unrelated, escaping array of the SAME NAME elsewhere (a different function, or a
different module in a bundle). Common array names (`arr`, `data`, `items`,
`result`) therefore frequently failed to promote in real multi-module programs —
the optimization only landed when the name happened to be globally unique.

Key candidacy by (function scope, lexeme) instead: each Stmt.Function /
Expr.ArrowFunction body is its own scope (module top level is scope 0), mirroring
StringAccumulatorPromotionAnalyzer. Cross-scope references are captures, already
handled by the IsVariableCaptured guard. Use-site emission is slot-type-keyed and
thus inherently scope-correct, so promoting more arrays is safe.

Effect (verified by IL): a clean `const xs = []` (push/index/length) now promotes
to List<double> even when another function has an escaping `const xs` — previously
both stayed boxed/$Array. No behavior change where names were already unique.

This is the prerequisite step (1) for the array-methods typed-HOF-pipeline work
(docs/plans/issue-861-array-methods-typed-pipeline.md): common array names must
promote before HOF receivers can stay typed.

Green on dotnet test (24 ArrayLocalPromotionTests incl. a new per-scope
name-collision case, both modes) except the pre-existing stale/flaky Test262
baselines (drift is Array.isArray/proxy, present in interpreter mode too →
unrelated to this compile-only change).
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