ReviewOS

zig-utils/zig-js

Intl.NumberFormat: compile immutable formatting options once

#563
Closed chris opened this 9 days ago ·
9 days ago

Parent: #475

Problem

Intl.NumberFormat validates and normalizes its user-visible option bag once at construction, but every format/formatToParts call then re-enters the generic property lookup and numeric/string conversion machinery for the same engine-owned null-prototype record. The frozen representative_intl family performs 360,000 steady calls per full single-lane row and currently takes roughly 725 ms median on the maintained host, making repeated internal-option decoding a distinct steady-state bottleneck rather than formatter construction work.

Scope

  • Add focused construction and steady-format controls that distinguish default, fixed-fraction, locale variant, and uncommon option combinations without weakening the frozen representative row.
  • Compile the validated NumberFormat state into an immutable, formatter-owned native record after every observable option getter/coercion has run in ECMA-402 order.
  • Make format, formatToParts, range formatting, and resolvedOptions consume one authoritative resolved state; do not leave diverging object/native representations.
  • Keep ownership realm-local and bounded, with correct GC finalization and safe read-only publication to shared-realm Threads.

No-workaround rules

  • No locale-specific benchmark branch, workload recognition, skipped option lookup/coercion, ICU/system-JSC delegation, mutable process-global cache, or hidden record that can diverge from resolvedOptions.
  • Preserve legacy Intl receiver unwrapping, subclass/newTarget behavior, numbering systems, rounding, grouping, sign, currency, unit, notation, and exact error/getter ordering.

Acceptance

  • Focused rows freeze exact checksums and measure construction separately from steady calls.
  • Exact-parent paired evidence covers the focused rows and the frozen representative_intl base/variant.
  • Intl.NumberFormat test262 is nonzero with zero regressions; focused semantic tests cover uncommon option combinations and constructor getter order.
  • OOM, bounded-heap/GC movement, no-GIL shared reads, TSan, and full unit gates pass.
  • Allocation ownership is reclaimed when a formatter dies; no unbounded cache or process-global mutable state is introduced.
9 days ago

Completed via 57eb69d5 and 7cf6b000. NumberFormat now publishes one immutable typed resolved record after all observable locale/option work; format/parts/ranges/resolvedOptions and BigInt locale formatting consume it. Variable strings are formatter-owned, failure-atomic, moving-GC safe, finalized, and release/acquire-published for read-only shared-realm use.\n\nSeven-pair exact-parent medians: frozen base 719,995,209 -> 529,092,375 ns (-26.51%); frozen variant 716,349,667 -> 524,449,208 ns (-26.79%). Focused steady default/fraction/locale/uncommon improve 19.68% / 22.11% / 23.15% / 22.19%. Construction is flat (-0.90% / +0.23% / -0.17% / -0.32%), and every checksum is unchanged.\n\nValidation: full units 1,644 pass + 1 skip, 0 fail/leak; focused normal and TSan 5/5; exact-parent Intl402 3,341 -> 3,341 with 0 failures; BigInt locale compatibility 11/11. Bounded precise-heap, moving nursery, OOM publication, and four-lane no-GIL shared-read witnesses pass.

Sign in to comment on this issue.