Build the yield argument handler once, not per evaluation#2593
Merged
Conversation
JintYieldExpression called JintExpression.Build(expression.Argument) inside
EvaluateInternal — on every single yield evaluation. Build only returns a
cached handler when the AST node''s UserData was pre-populated (prepared
scripts), so for ordinary execution every `yield <expr>` reconstructed the
argument''s whole handler subtree per iteration: for `yield { a: i, b: i+1 }`
that is a JintObjectExpression + ObjectProperty[] + ExpressionCache +
JintIdentifierExpression and JintBinaryExpression handlers — every time the
generator produced a value. The handler also lost all its per-node inline
caches each rebuild.
The argument handler is now built once in the constructor like every other
expression handler.
Generator-producing-object-literals workload (fresh engine per iteration):
132.2 -> 52.9 MB/iter (-60%), 98.4 -> 67.9 ms/iter (-31%).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lahma
enabled auto-merge (squash)
July 6, 2026 20:52
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.
\JintYieldExpression\ called \JintExpression.Build(expression.Argument)\ inside \EvaluateInternal\ — on every yield evaluation. \Build\ only returns a cached handler when the AST node's \UserData\ was pre-populated (prepared scripts), so for ordinary execution every \yield \ reconstructed the argument's whole handler subtree per iteration: for \yield { a: i, b: i + 1 }\ that is a \JintObjectExpression\ + \ObjectProperty[]\ + \ExpressionCache\ + identifier/binary handlers — every time the generator produced a value — and the handler lost all its per-node inline caches on each rebuild. The allocation census flagged this as ~51% of a generator-producing-literals workload (handler types should never appear in steady-state allocation profiles at all).
The argument handler is now built once in the constructor, like every other expression handler.
Measurements
Generator yielding object literals (100k yields, fresh engine per iteration, A/B/A/B alternating binaries): 132.2 → 52.9 MB/iter (−60%), 98.4 → 67.9 ms/iter (−31%). All AST-handler types disappear from the allocation profile; what remains is the literal's dictionary-path descriptors and the user-visible generator result objects.
Verification
🤖 Generated with Claude Code