Skip to content

perf(map): specialize declared Map.get dispatch - #8830

Closed
proggeramlug wants to merge 2 commits into
perf/readonly-collection-loweringfrom
perf/readonly-map-get-dispatch
Closed

perf(map): specialize declared Map.get dispatch#8830
proggeramlug wants to merge 2 commits into
perf/readonly-collection-loweringfrom
perf/readonly-map-get-dispatch

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Summary

  • retain declared Map and ReadonlyMap candidates through nested class, interface, and object fields
  • brand-check the live receiver before entering the existing native Map lookup
  • preserve ordinary get method dispatch for structural values, subclasses, proxies, primitives, and nullish receivers

Why

A steady-state profile of the unchanged codehz/ecs 15k-command workload placed 1,015 samples in generic native method dispatch for this.ctx.entityToArchetype.get(entityId). The nested interface-typed field retained its Map declaration, but not the stronger native-layout proof used by the existing direct lowering.

This change uses the declaration only to select a guarded runtime operation. A receiver whose tracked GC type is exactly the built-in Map kind enters the existing generic Map key lookup directly. Every brand miss roots both operands and uses the ordinary method dispatcher. It does not add numeric-key classification or change Map layout, lookup semantics, or the existing proven-native path.

Correctness

  • full codegen library suite: 1,256 passed, 1 ignored, 0 failed
  • full serial runtime library suite: 2,690 passed, 4 ignored, 0 failed
  • focused generated-IR test for the nested interface-field case
  • compiled TypeScript semantics test for native Map, ReadonlyMap typing, structural receivers, subclass overrides, and nullish behavior
  • existing compiled ReadonlySet semantics regression
  • rustfmt and diff checks

The upstream ECS functional sweep passed 461/463 cases. Both failures reproduced identically on the exact parent binary. The candidate introduced no new performance-threshold failure: serialization and sparse-wildcard fail their existing upstream ceilings on both candidate and exact parent.

Performance

M1 Mac mini, unchanged codehz/ecs v0.13.0 at 58d729682eeb88d7361796de0420f3d673e27479, 15k-command comprehensive row, exact rebased #8826 control, two warmups and six measured rounds per process:

  • control median: 36.561 ms
  • candidate median: 31.833 ms
  • median paired improvement: 12.981%
  • paired range: 12.387% to 13.771%
  • candidate wins: 11/11
  • process semantic oracles: 22/22

A same-host Node 26.5.1 comparison measured 2.905 ms versus Perry at 31.828 ms, so this is an admitted incremental fix, not ECS command-path parity.

Stacked on #8826 for an isolated review diff.

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c77090c-b830-461a-aee2-7eb08ab111be

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

proggeramlug added a commit that referenced this pull request Aug 25, 2026
* perf(codegen): specialize branded ReadonlySet.has

* chore: add changelog for #8826

* chore(codegen): classify readonly Set type hint

* fix(async_hooks): address lifecycle review feedback

* refactor(async_hooks): split resource scopes

* fix(net): account only accepted socket writes

* fix(async_hooks): use scoped runtime handles

* chore(changelog): key async hooks fragment to PR

* fix(async_hooks): preserve scoped event coercion

* refactor(events): split scoped emit thunks

* test(async_hooks): classify forced GC trigger

* perf(map): specialize declared Map get dispatch

* chore: add changelog for #8830

* runtime(gc): resolve x19 frame-base roots in the fast fp-chain walk (#8770)

LLVM takes x19 as a frame base pointer for a function with a dynamic stack
allocation (a VLA or a spread-argument area). Its GC roots are stack slots
addressed via x19, and x19 is established as `mov x19, sp` immediately after
the fixed prologue and before the dynamic `sub sp, sp, xN`, with no
realignment — so x19 holds exactly the body SP the fp chain already
reconstructs (`fp - fp_to_sp_offset`).

Before this, any x19 root flipped the whole-image `chain_walkable` flag false
(it required EVERY root to be fp/sp), which globally disabled the fast x29-chain
root walk and forced every GC onto the platform unwinder. In cli.js just 63 of
72,812 functions use an x19 base, yet they disabled the correct fast walker for
all of them; the unwinder then mis-resolved compiled-JS stack-slot roots and
live young objects were swept (0xff-poison-receiver SIGSEGV /
`(number).get is not a function`).

Make `chain_walkable` accept x19 and resolve an x19 root like an SP root, gated
per frame by `x19_is_body_sp` (confirms the `mov x19, sp` prologue shape); a
frame that does not match still fails closed to the unwinder. Any other base
register still disables the chain walk.

Claude-Session: https://claude.ai/code/session_01TwxRkALrR9HKSF1zKLSTAF

* chore: runtime-validated verdict for is_declared_map_expr (#8830)

---------

Co-authored-by: Ralph Küpper <ralph@skelpo.com>
@proggeramlug

Copy link
Copy Markdown
Contributor Author

Landed on main via the #8835 batch.

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