Simplify map-get.cc to only handle the regular OrderedHashMap#361
Open
szegedi wants to merge 2 commits into
Open
Simplify map-get.cc to only handle the regular OrderedHashMap#361szegedi wants to merge 2 commits into
szegedi wants to merge 2 commits into
Conversation
A JS Map always uses the regular OrderedHashMap as its backing table: V8's Map constructor hardcodes AllocateOrderedHashMap(), and the only path that could install a SmallOrderedHashMap (OrderedHashMapHandler / AdjustRepresentation) is test-only, never used by the JSMap/JSSet builtins. We only ever read AsyncContextFrame (CPED) maps, which are ordinary JS Maps, so the SmallOrderedHashMap handling was dead code. Drop the SmallOrderedHashMapLayout struct, IsSmallOrderedHashMap header sniffing, and the now-unnecessary templating on FindEntryByHash / FindValueByHash. The public GetValueFromMap signature is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Overall package sizeSelf size: 2.18 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | pprof-format | 2.2.2 | 500.53 kB | 500.53 kB | | source-map | 0.7.6 | 185.63 kB | 185.63 kB | | node-gyp-build | 4.8.4 | 13.86 kB | 13.86 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
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.
Summary
bindings/map-get.ccpreviously detected and parsed two V8 hash-table representations —SmallOrderedHashMapand the regularOrderedHashMap— and dispatched between them at runtime. The small-map handling is dead code: a JSMapalways uses the regularOrderedHashMap, and we only ever read AsyncContextFrame (CPED) maps, which are ordinary JSMaps.This drops:
SmallOrderedHashMapLayoutstruct,IsSmallOrderedHashMapheader sniffing,FindEntryByHash/FindValueByHash(one layout left → they takeconst OrderedHashMapLayout*directly),GetValueFromMap.Net: 24 insertions, 146 deletions. The public
GetValueFromMapsignature is unchanged, sowall.ccis unaffected.IsOrderedHashMapvalidation is retained as defensive hygiene (a mis-aimed pointer walk yields "not found", not garbage).Verified: addon builds cleanly,
clang-formatis idempotent, and all 7test-get-value-from-map-profilertests pass.Proof that a JS
Map's backing table is alwaysOrderedHashMap(neverSmallOrderedHashMap)Traced against Node's bundled V8 (the copies vendored under the sibling
v8/nodecheckouts; the relevant code is stable across Node v22–v26).1. An
AsyncContextFrameis just a JSMap.In
node/lib/internal/async_context_frame.jsthe hierarchy is:SafeMapis a frozen-method wrapper around the globalMap; its instances are ordinaryJSMapobjects with the identical backing store. The constructor (super(AsyncContextFrame.current()); this.set(store, data)) is justnew Map(iterable)+Map.prototype.set. So whatever V8 does for anyMapis what it does here.2. A
Map'stableis allocated as anOrderedHashMap, and stays one.In
v8/src/builtins/builtins-collections-gen.cc, the constructor path (GenerateConstructor→AddConstructorEntries→AllocateTable) does, for the Map variant:and
AllocateOrderedHashMap()(code-stub-assembler.cc) allocates anOrderedHashMapatkInitialCapacity. The stringsSmallOrderedHashMap/SmallOrderedHashSetdo not appear anywhere inbuiltins-collections-gen.cc— not in the constructor,set, nor the grow/shrink/rehash paths. The runtime fallbacks confirm the invariant:runtime-collections.ccunconditionally doesCast<OrderedHashMap>(holder->table())on every access (it would CHECK-fail if a Small table were ever installed).3. The only code that produces a
SmallOrderedHashMap-then-promotes is test-only.V8 does have a "start small, transition to large" abstraction —
OrderedHashMapHandler/OrderedHashSetHandlerwithAdjustRepresentation()(ordered-hash-table.cc). That is the only machinery that would place aSmallOrderedHashMapwhere anOrderedHashMapis later expected. The only callers ofOrderedHashMapHandler::Add/OrderedHashSetHandler::*in the entire tree are intest/cctest/test-orderedhashtable.cc. No production path — and specifically notJSMap/JSSet— uses these handlers.4. The Small variants are effectively unused in this build.
The Torque
AllocateSmallOrderedHashSet/AllocateSmallOrderedHashMapmacros have zero callers. The C++NewSmallOrderedHashSet/Mapfactory functions are reached only via the test-only handler. Remaining references (objects.cc) are just GC body-size descriptors. The genuinely-live "small ordered" type isSmallOrderedNameDictionary(dictionary-mode object property storage) — a different code path that never backs aMap.Why it was implemented but never used
V8 keeps two parallel families:
OrderedHashMap/OrderedHashSet(the canonical growable backing store for JSMap/Set) and the compactSmallOrderedHashMap/SmallOrderedHashSet. The "small first, promote on growth" optimization was implemented (the handler +AdjustRepresentation) but never wired into theJSMap/JSSetbuiltins — the CSA constructors hardcodeAllocateOrderedHashMap(). So a JSMapis born with a regularOrderedHashMapeven when empty, and grows in place as one.Caveat
This is a guarantee about V8's current implementation (the
AllocateTablehardcoding), not a spec-level invariant. The retainedIsOrderedHashMapvalidation keeps the reader resilient to future V8 drift: if the layout ever fails to validate,GetValueFromMapreturns 0 ("not found") rather than reading garbage.🤖 Generated with Claude Code