Skip to content

Mark dead completion values at script/eval top level#2606

Merged
lahma merged 2 commits into
sebastienros:mainfrom
lahma:perf-loop-floor-toplevel
Jul 9, 2026
Merged

Mark dead completion values at script/eval top level#2606
lahma merged 2 commits into
sebastienros:mainfrom
lahma:perf-loop-floor-toplevel

Conversation

@lahma

@lahma lahma commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Rebased onto latest main after #2605 merged.

What

A top-level statement's Normal completion value can never become the script/eval result when a
later sibling always produces one (an expression statement): nothing at top level can jump over
later siblings — break/continue cannot target past them, and throw abandons the value
entirely. Such statements now execute with completion-value elision on, which lets the for-statement
tight loop (#2605) engage at script/eval top level — the dromaeo-core-eval payload shape (a
string-append loop followed by ret = str;).

Soundness

The analysis applies only to Observable (top-level) lists, never to nested Inherit lists: a
labeled break out of a block skips the block's remaining statements while carrying an Empty value,
so an earlier statement's value can still surface through UpdateEmpty — a test pins that exact
shape. Only expression statements count as always-valued (untaken ifs complete with undefined
and would also qualify per UpdateEmpty(stmt, undefined), but the conservative set covers the
target shapes).

Results

EvalExecutionBenchmarks A/B (default job, adjacent runs):

row before after
EvalHotReusedEngine 732.7 µs 422.7 µs −42.3%
EvalFreshEngine 718.0 µs 498.4 µs −30.6%
NewFunctionHotReusedEngine (guard) 415.9 µs 416.9 µs flat
PlainFunctionLoopReference (guard) 413.8 µs 420.6 µs +1.6%
ParseOnlyTmp (guard) 38.7 µs 39.8 µs flat

dromaeo-core-eval driver: 11.12 → 10.06 ms/iter (−9.5%). Allocations byte-identical on every row.

Eval bodies now hit the same per-iteration floor as function bodies, closing the historic ~13%
eval-vs-function execution gap. Composed onto the dromaeo-core-eval row (2 parses + eval-exec +
newFunction-exec): ≈ −20% on the row, to be confirmed at the next EngineComparison refresh.

Tests

Dead-marked top-level loop running tight with a trailing value read (script and eval), the
labeled-break-out-of-block shape that must NOT be dead-marked, and the spec undefined completion
of untaken trailing ifs.

Gating

All-TFM build ✅ · Jint.Tests ×2 ✅ · PublicInterface ×2 ✅ · Test262 99,260/0 ✅

🤖 Generated with Claude Code

@lahma
lahma force-pushed the perf-loop-floor-toplevel branch from 883db14 to 96eab98 Compare July 9, 2026 07:27
@lahma
lahma enabled auto-merge (squash) July 9, 2026 08:00
A top-level statement's Normal completion value can never become the
script/eval result when a LATER sibling always produces one (an
expression statement): nothing at top level can jump over later
siblings - break/continue cannot target past them and throw abandons
the value entirely. Such statements now execute with completion-value
elision on, which lets the for-statement tight loop (previous commit)
engage at script/eval top level - the dromaeo-core-eval payload shape
(a string-append loop followed by `ret = str;`).

The analysis deliberately applies ONLY to Observable (top-level) lists,
never to nested Inherit lists: a labeled break out of a block skips the
block's remaining statements while carrying an Empty value, so an
earlier statement's value can still surface through UpdateEmpty - a
test pins that exact shape. Only expression statements count as
always-valued (untaken ifs complete with undefined and would also
qualify per UpdateEmpty(stmt, undefined), but the conservative set is
sufficient for the target shapes).

EvalExecutionBenchmarks A/B (default job, adjacent runs):

| row                        | before    | after     |        |
|----------------------------|-----------|-----------|--------|
| EvalHotReusedEngine        | 732.7 us  | 422.7 us  | -42.3% |
| EvalFreshEngine            | 718.0 us  | 498.4 us  | -30.6% |
| NewFunctionHotReusedEngine | 415.9 us  | 416.9 us  | flat   |
| PlainFunctionLoopReference | 413.8 us  | 420.6 us  | +1.6%  |
| ParseOnlyTmp               | 38.7 us   | 39.8 us   | flat   |

dromaeo-core-eval driver: 11.12 -> 10.06 ms/iter (-9.5%). Allocations
byte-identical on every row. Eval bodies now hit the same per-iteration
floor as function bodies, closing the historic ~13% eval-vs-function
execution gap.

Tests pin the dead-marked top-level loop running tight with a trailing
value read (script and eval), the labeled-break-out-of-block shape that
must NOT be dead-marked, and the spec undefined completion of untaken
trailing ifs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lahma
lahma force-pushed the perf-loop-floor-toplevel branch from 96eab98 to 05bb3b3 Compare July 9, 2026 08:09
@lahma
lahma merged commit 4731d43 into sebastienros:main Jul 9, 2026
4 checks passed
@lahma
lahma deleted the perf-loop-floor-toplevel branch July 9, 2026 08:42
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>
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