Skip to content

Skip covariant store checks when populating exact JsValue arrays#2683

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:perf-stelemref-arg-stores
Jul 14, 2026
Merged

Skip covariant store checks when populating exact JsValue arrays#2683
lahma merged 1 commit into
sebastienros:mainfrom
lahma:perf-stelemref-arg-stores

Conversation

@lahma

@lahma lahma commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

JsValue is not sealed, so every array[i] = value store into a JsValue[] pays a runtime covariant-store check (CastHelpers.StelemRef_Helper) — ETW-measured at ~1.4% of program time on call-heavy workloads, 62% of it from call-argument population.

Adds Arguments.WriteNoTypeCheck — explicit bounds check plus a ref write via MemoryMarshal.GetArrayDataReference on net8+ (plain store on older TFMs), with a Debug.Assert and a documented exactness precondition — and uses it where the array is provably exactly JsValue[]: the interpreter's argument-building loop (ExpressionCache.BuildArguments, arrays freshly allocated or rented from JsValueArrayPool, whose factories only create exact arrays — verified) and RegExp.Replace's functional-replace paths, which also drop a List<JsValue> + ToArray() double allocation per match in favor of exact-sized arrays.

Orthogonal to argument pooling/lifetime (which stays on JsValueArrayPool with return-after-call semantics) — this changes only the store instruction.

Benchmarks (default jobs, adjacent A/B on latest main)

Benchmark main PR Δ
Recursion DeepSum 225.27 ms 211.78 ms −6.0%
SunSpider controlflow-recursive 65.48 ms 61.92 ms −5.4%
SunSpider access-binary-trees 49.96 ms 47.56 ms −4.8%
Recursion Fib 487.74 ms 469.83 ms −3.7%
Recursion Tak 14.33 ms 13.84 ms −3.4%
SunSpider 3d-raytrace 77.72 ms 77.61 ms neutral

Gates

  • Jint.Tests: 3,569 (net10.0) + 3,506 (net472) passed, 0 failed
  • Jint.Tests.PublicInterface / CommonScripts: green both TFMs
  • Test262: 99,421/8 under 4-way parallel suite contention (the 8 = known S7.8.5 regexp-literal 30 s timeout flakes); all 476 regexp-literal tests pass in 10 s when re-run isolated — 0 real failures

🤖 Generated with Claude Code

@lahma
lahma enabled auto-merge (squash) July 14, 2026 07:15
JsValue is not sealed, so every args[i] = value store into a JsValue[]
pays a runtime stelemref covariance check - measured at ~1.4% of program
time on call-heavy workloads, 62% of it from call-argument population.

Add Arguments.WriteNoTypeCheck (explicit bounds check + ref write via
MemoryMarshal.GetArrayDataReference on net8+) for arrays that are provably
exact JsValue[] - freshly allocated or rented from JsValueArrayPool, whose
factories only create such arrays - and use it in the interpreter's
argument-building loop. RegExp.Replace functional-replace paths also drop
a List<JsValue> + ToArray() per match in favor of exact-sized arrays.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lahma
lahma force-pushed the perf-stelemref-arg-stores branch from 2526e0f to 5da3cf1 Compare July 14, 2026 07:33
@lahma
lahma merged commit 3ff192b into sebastienros:main Jul 14, 2026
10 of 12 checks passed
@lahma
lahma deleted the perf-stelemref-arg-stores branch July 14, 2026 08:09
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