Skip to content

perf(runtime): promise resolution with an object pays a 78.5% thenable-probe tax (~9% of asyncpipe) #7910

Description

@proggeramlug

Summary

Resolving a promise with an object costs +78.5% instructions versus resolving with a number, on identical topology — identical promise, microtask and closure counts. The only differing counter is thenable_probe: 0 vs 24 000.

The cost is the spec-mandated Get(resolution, "then") assimilation check. Per probe it pays: a setjmp frame, re-interning the "then" key string, the generic dynamic getter's preamble, and a name-keyed miss walk into Object.prototype — roughly 72 000 times, answering undefined every time.

~9% of asyncpipe.

Why it was not fixed in #7906

The safe version needs an Object.prototype mutation-generation counter covering assignment, defineProperty, delete, and setPrototypeOf. Getting that wrong makes a genuine thenable stop being assimilated, and the failure mode is a hang rather than a wrong value — which is exactly the kind of thing that must not be landed against a deadline where each validation cycle is ~40 minutes.

Acceptance

  • A fast path for the overwhelmingly common case (plain object, no then anywhere on the chain) guarded by a generation counter that is invalidated by every mutation route into Object.prototype.
  • A test that mutates Object.prototype.then after the fast path has been taken and proves assimilation resumes.
  • Negative test: a real thenable still assimilates.

Evidence

gc-handoff/ASYNC2-NOTES.md, with counters and file:line pointers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    performanceRuntime, compile-time, build-size, or memory performance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions