Store array length inline to avoid a per-array PropertyDescriptor#2540
Merged
Conversation
Every array allocated one PropertyDescriptor for its `length` own property (in the ArrayInstance constructors), which is the dominant descriptor cost of array-heavy code — e.g. ~27k descriptors in the dromaeo-object-array benchmark come from array creation, not element storage (the dense element path is already descriptor-free). length is always a data property (it is non-configurable, so it can never become an accessor) with only two states: writable (default) or non-writable. Store the value inline (_lengthValue) and materialize + cache a descriptor (_lengthDescriptor) only when a caller needs the object: [[GetOwnProperty]], [[DefineOwnProperty]] (including ArraySetLength and making length non-writable), or reflection. Once materialized the descriptor is authoritative. Inline state is always the default attributes, because the only ways to change length's attributes go through DefineLength, which materializes first. The hot paths (construction, push, length=, GetLength) use the inline value with no descriptor allocation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 24, 2026
This was referenced Jul 2, 2026
This was referenced Jul 10, 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.
Problem
Every array allocates one
PropertyDescriptorfor itslengthown property (in theArrayInstanceconstructors). This is the dominant descriptor cost of array-heavy code: e.g. of the ~27kPropertyDescriptors allocated by thedromaeo-object-arraybenchmark, essentially all come from array creation ([],new Array(n), species-create), not element storage — the dense element path is already descriptor-free.Approach
lengthis always a data property (it is non-configurable, so it can never become an accessor) with only two states: writable (default) or non-writable. So the value is stored inline (_lengthValue) and a descriptor (_lengthDescriptor) is materialized and cached only when a caller needs the object —[[GetOwnProperty]],[[DefineOwnProperty]](includingArraySetLengthand makinglengthnon-writable), or reflection. Once materialized the descriptor is authoritative.Inline state always carries the default attributes, because the only ways to change
length's attributes go throughDefineLength, which materializes the descriptor first. The hot paths — construction,push,length=,GetLength— read/write the inline value with no descriptor allocation.Array.prototypekeeps an explicit descriptor (one-time per realm, preserves its exact attributes).Benchmarks
ArrayAllocBenchmark(added here), default job, net10.0, 200k arrays/op:LiteralEmpty([]; a.length=4)NewArray(new Array(8))LiteralSmall([i,i+1,i+2])PushLoop([]; push×2)Each array creation drops one 32 B
PropertyDescriptor; time is neutral.Testing
test262 0 failures (99,260 passed) — including the full array suite;
Jint.Tests0 (net10.0 3131 / net472 3069);Jint.Tests.PublicInterface0.🤖 Generated with Claude Code