Skip to content

Add dense-array append fast path for computed-index writes#2608

Merged
lahma merged 2 commits into
sebastienros:mainfrom
lahma:perf-dense-append
Jul 9, 2026
Merged

Add dense-array append fast path for computed-index writes#2608
lahma merged 2 commits into
sebastienros:mainfrom
lahma:perf-dense-append

Conversation

@lahma

@lahma lahma commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

What

m[i] = v at exactly the current length — the array-building pattern of dromaeo-3d-cube's
MMulti/VMulti kernels (result arrays start empty, so every element write is an append) — previously
fell through the overwrite-only dense fast path into the full PutValue → Set → SetIndexValue
pipeline per element.

ArrayInstance.TryAppendDense appends in place: same doubling growth policy as
WriteArrayValueUnlikely's dense arm, length bumped via SetLengthValue. It declines — deferring
to the spec path and its errors — for non-append indices, non-extensible arrays, non-writable or
materialized-non-default length, sparse mode and the dense cap. The assignment fast path probes it
only after the existing overwrite arm misses, so overwrite-dominant workloads pay one
predicted-false branch on the miss path only.

Results

ElementAccessBenchmark A/B (default job, adjacent runs; AppendWrite row added by this PR — fresh
arrays, four appends each):

row before after
AppendWrite 44.78 ms 40.16 ms −10.3%
Write (overwrite guard) 112.74 ms 113.95 ms flat*
Read (guard) 111.02 ms 114.07 ms flat*
ReadModifyWrite 199.84 ms 187.93 ms −3..6%*
ChainedRead 158.14 ms 153.95 ms −2.6%*

* sign-mixed process-mode noise, resolved via --launchCount 5 medians; allocations byte-identical
on every row.

Tests

Append/lazy-array/a[a.length] shapes; strict-mode TypeErrors for
preventExtensions/non-writable-length/frozen; hole-fill and out-of-order writes keeping spec
behavior; element integrity across capacity growth.

Gating

All-TFM build ✅ · Jint.Tests ×2 ✅ · PublicInterface ×2 ✅ · Test262 99,426/0 ✅ (post-#2599 suite
baseline, run on latest main)

🤖 Generated with Claude Code

`m[i] = v` at exactly the current length - the array-building pattern
of dromaeo-3d-cube's MMulti/VMulti kernels (result arrays start empty
and every write is an append) - previously fell through the
overwrite-only dense fast path into the full PutValue -> Set ->
SetIndexValue pipeline per element.

ArrayInstance.TryAppendDense appends in place: same doubling growth
policy as WriteArrayValueUnlikely's dense arm, length bumped via
SetLengthValue. It declines (deferring to the spec path and its errors)
for non-append indices, non-extensible arrays, non-writable or
materialized-non-default length, sparse mode and the dense cap. The
assignment fast path probes it only after the existing overwrite arm
misses, so overwrite-dominant workloads pay one predicted-false branch
on the miss path only.

ElementAccessBenchmark A/B (default job, adjacent runs; AppendWrite row
added by this change - fresh arrays, four appends each):

| row             | before    | after     |            |
|-----------------|-----------|-----------|------------|
| AppendWrite     | 44.78 ms  | 40.16 ms  | -10.3%     |
| Write           | 112.74 ms | 113.95 ms | flat*      |
| Read            | 111.02 ms | 114.07 ms | flat*      |
| ReadModifyWrite | 199.84 ms | 187.93 ms | -3..6%*    |
| ChainedRead     | 158.14 ms | 153.95 ms | -2.6%*     |

*sign-mixed process-mode noise, resolved via --launchCount 5 (medians);
allocations byte-identical on every row.

Tests pin append/lazy-array/a[a.length] shapes, strict-mode TypeErrors
for preventExtensions/non-writable-length/frozen, hole-fill and
out-of-order writes keeping spec behavior, and element integrity across
capacity growth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lahma
lahma enabled auto-merge (squash) July 9, 2026 08:02
@lahma
lahma merged commit a6fccb7 into sebastienros:main Jul 9, 2026
4 checks passed
lahma added a commit that referenced this pull request Jul 9, 2026
Full re-run after the 2026-07 interpreter-parity campaign
(#2600-#2606, #2608-#2611). Highlights vs the 2026-07-07 refresh:
dromaeo-core-eval -40% (1.52 -> 0.92 ms, taking first place from
NiL.JS), dromaeo-3d-cube -19% time / -35% allocation (7.38 -> 5.99 ms,
moving ahead of NiL.JS - only the IL-compiling engine remains faster),
stopwatch -7% (tied with the best interpreter, ahead of Jurassic),
stopwatch-modern -13% (tied with Jurassic), object-array -10%,
object-regexp -13%, object-string -5%. Competitor versions unchanged;
their rows served as thermal canaries (all within a few percent of the
previous refresh).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@lahma
lahma deleted the perf-dense-append branch July 13, 2026 06:52
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