ReviewOS

zig-utils/zig-js

Date: format string conversions into one owned buffer

#526
Closed chris opened this 11 days ago ·
11 days ago

Parent: #475 Related: #460, #461, #480, #493

Problem

Date.prototype.toDateString, toTimeString, and toString currently enter one shared branch that formats both date and time halves before selecting the result. The selected half is then copied into a StringCell, while full toString concatenates a third arena buffer. toUTCString also allocates a temporary year string before its final output. In precise-GC contexts, an arena-formatted final buffer is copied again into realm-owned managed-string storage, so repeated conversions retain avoidable high-water backing until Context teardown.

Scope

  • Format toDateString, toTimeString, toString, toUTCString, and Annex B toGMTString directly into exactly one result byte buffer.
  • Render the year through bounded native storage so ordinary and extended years do not require a temporary allocation.
  • In precise-GC realms, allocate the result from the exact realm-owned backing allocator and transfer it into the managed StringCell; preserve arena ownership for standalone/non-GC interpreters.
  • Keep invalid-date behavior, UTC/local method routing, exact punctuation/padding, negative and six-digit years, and GC movement semantics unchanged.
  • Add deterministic 1K/2K/4K conversion rows that exercise every affected method and an unrelated Date getter control. Preserve cross-engine checksum equality by scoring only specification-stable UTC/date/time prefixes while still constructing every complete result.

No-workaround rules

  • No cached output, shared mutable formatting buffer, hard-coded benchmark result, skipped conversion, locale/time-zone omission, or benchmark-only engine path.
  • No borrowed pointer may outlive native storage; OOM must leave ownership exact and leak-free.

Acceptance

  • Each successful affected conversion owns one final byte buffer and one managed string cell, with no retained intermediate arena buffer in precise-GC mode.
  • Existing Date test262 remains regression-free; focused invalid, extended-year, alias, OOM, moving-GC, no-GIL, and TSan witnesses pass.
  • Exact-parent 1K/2K/4K instruction/wall evidence, 4K retained-RSS evidence, and allocation attribution are checked in under docs/.data/ with exact checksums.
  • The unrelated Date getter control remains neutral and all public claims identify exact parent/candidate revisions.
11 days ago

Benchmark parent landed as 9c840f80. The 1K/2K/4K all-conversion rows match JavaScriptCore at checksums 4,165,907 / 8,339,572 / 16,699,331; the 4K getter control matches at 8,360,941. Current zig-js single-context wall grows from about 56 ms to 211 ms across the widths, so the retained intermediate formatting work is directly visible before the engine change.

11 days ago

Completed on main.

Commits:

  • 9c840f80 and cdabd71f: deterministic cross-engine 1K/2K/4K six-result rows and getter control.
  • 0b01b789: bounded native year/ISO rendering and one directly transferred realm-owned result buffer for toDateString, toTimeString, toString, toUTCString/toGMTString, toISOString, and Date-fast toJSON.
  • 3a5fc50d: exact allocation-zero/allocation-one OOM cleanup witness.
  • c7705224: raw and rendered exact-parent evidence.

The scored 4K attribution removes 158,851,286 bytes (97.5%) of new retained Context backing and all 215 backing-growth events while preserving exactly 487,427 GC-cell allocations / 60,818,048 cell bytes. The ordinary 4K row records stable peak RSS at 0.9670x. Its separate retained-RSS observer is intentionally non-directional because parent/candidate RSD is 37.00%/43.95%; the noisy samples remain checked in. The unrelated getter control is 0.9987x instructions and 1.003x wall.

Validation: the implementation full unit run passed 1,568 with 1 skipped, 0 failed, and 0 leaked; Date test262 remains 594/594; moving nursery, 4 MiB reclamation, extended-year/invalid/alias semantics, focused no-GIL TSan, and the independent two-allocation OOM witness pass. Benchmark publication and allocation-arithmetic gates pass. The unrelated BunPress 0.1.21 to 0.2.0 manifest boundary discovered by the docs gate is isolated in #527.

Sign in to comment on this issue.