Keep builtin-shape deopt lazy: unmaterialized function slots stay deferred#2588
Merged
Merged
Conversation
…erred DeoptBuiltinShape previously materialized EVERY slot, forcing all of a host''s dispatcher functions into existence the moment user code added or removed one own property (e.g. `Math.x = 1` instantiated all ~35 Math functions). For upcoming shaped hosts where deopt is routine — the global object deopts on any top-level var — an eager deopt would be strictly worse than the dictionary path it replaces. Now already-materialized slots keep their descriptor instance (inline caches and spec identity depend on it); unmaterialized function slots become LazyBuiltinSlotDescriptor wrappers that create the dispatcher on first value read; unmaterialized accessors (rare) still materialize eagerly since a data-descriptor wrapper cannot defer them; aliases share their target''s instance — materialized or lazy — so name pairs keep one function identity across the deopt. Like LazyPropertyDescriptor, the wrapper clears CustomJsValue once materialized so it becomes a plain data descriptor. Deopt-triggering script (Math/JSON/Reflect mutation, fresh engine): 43.7 -> 32.3 KB/iter (-26%). BuiltinShape/EngineConstruction/MinimalScript suites: allocations byte-identical, times within run-to-run noise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 6, 2026
This was referenced Jul 13, 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.
DeoptBuiltinShapepreviously materialized every slot when a shaped built-in fell back to dictionary mode, forcing all of the host's dispatcher functions into existence the moment user code added or removed one own property —Math.x = 1instantiated all ~35 Math functions nobody asked for. For upcoming shaped hosts where deopt is routine (the global object deopts on any top-levelvar), an eager deopt would be strictly worse than the dictionary path it replaces, so this is a prerequisite for flippingGlobalObject/FunctionPrototypeto shapes.LazyBuiltinSlotDescriptorwrappers that create the dispatcher on first value read (mirroringLazyPropertyDescriptor, including clearingCustomJsValueonce materialized).Set.prototype.keys === Set.prototype.valueskeep one function identity across the deopt.Measurements
Deopt-triggering script (
Math.x = 1; JSON.x = 1; Reflect.x = 1+ calls, fresh engine per iteration): 43.7 -> 32.3 KB/iter (-26%), matching the dispatcher functions no longer force-created.No-regression gates (BenchmarkDotNet default jobs, A/B vs main + A/B/A noise check):
BuiltinShapeBenchmark,EngineConstructionBenchmark,MinimalScriptBenchmark— allocations byte-identical on every row, times within the suites'' observed run-to-run bands (the deopt path is not on any of their execution paths).Verification
Jint.Testsgreen (net10.0 + net472),Jint.Tests.PublicInterfacegreengetOwnPropertyNamesverified against a live engine🤖 Generated with Claude Code