Add dense-array append fast path for computed-index writes#2608
Merged
Conversation
`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
enabled auto-merge (squash)
July 9, 2026 08:02
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>
This was referenced Jul 13, 2026
This was referenced Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
m[i] = vat exactly the current length — the array-building pattern of dromaeo-3d-cube'sMMulti/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 → SetIndexValuepipeline per element.
ArrayInstance.TryAppendDenseappends in place: same doubling growth policy asWriteArrayValueUnlikely's dense arm, length bumped viaSetLengthValue. It declines — deferringto 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;
AppendWriterow added by this PR — fresharrays, four appends each):
* sign-mixed process-mode noise, resolved via
--launchCount 5medians; allocations byte-identicalon every row.
Tests
Append/lazy-array/
a[a.length]shapes; strict-mode TypeErrors forpreventExtensions/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