ReviewOS

zig-utils/zig-js

Date: make setter coercion allocation-free and arity-exact

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

Parents: #475, #493, #480

Related evidence/matrix: #460

Problem

Every Date.prototype.set* call currently copies the complete supplied argument list into context-arena storage before applying the setter. Repeated setter calls therefore retain proportional backing until context teardown even though each specification algorithm consumes at most four values.

The same loop coerces arguments beyond the method's specification arity. For example, setUTCFullYear(year, month, date, extra) invokes extra.valueOf(); ECMA-262 only converts year, month, and date, so an ignored extra argument must not run user code or throw.

Current exact witness:

let calls = 0;
const extra = { valueOf() { calls++; throw new Error("coerced"); } };
const date = new Date(0);
date.setUTCFullYear(1970, 0, 1, extra); // currently throws in zig-js
if (calls !== 0 || date.getTime() !== 0) throw new Error("wrong");

Scope

  • Replace per-call arena argument copies with bounded native storage selected by the exact setter algorithm arity.
  • Coerce only specification-consumed arguments, once each and left-to-right.
  • Preserve the required ordering where [[DateValue]] is read before ToNumber, including callbacks that mutate the receiver and invalid-Date behavior.
  • Cover omitted optionals, extra arguments, abrupt completion, negative zero, rollover, and every local/UTC setter family.
  • Add deterministic 1K/2K/4K setter-churn witnesses with exact checksums plus an ordinary no-setter allocation control.
  • Publish exact-parent CPU, allocation, peak-RSS, and retained-RSS evidence.

Acceptance

  • Extra arguments past each setter's ECMA-262 arity are not observed.
  • Required arguments are coerced exactly once in specification order, and abrupt completion leaves later conversions/unobservable stores undone.
  • Setter churn performs no per-call argument-buffer allocation and does not retain memory proportional to call count.
  • 1K/2K/4K exact checksums establish the expected growth curve without a benchmark-specific engine path.
  • Focused Date test262, unit, OOM, moving/full GC, no-GIL, and TSan gates pass with zero regressions.
  • Seven balanced exact-parent pairs report CPU/allocation/peak/retained effects and include an ordinary control.

No-workaround rules

No skipped in-arity coercion, cached callback result, disabled GC, unbounded scratch buffer, hard count limit, swallowed abrupt completion/OOM, strong retention of transient arguments, source/workload recognition, or benchmark-only fast path.

9 days ago

Implemented and published on main.

Commits:

  • e2348ffd — deterministic 1K/2K/4K setUTCHours churn rows plus the identical 4K setTime control.
  • ddaae8a5 — arity-exact, allocation-free Date component coercion with all-setter and no-GIL witnesses.
  • 0e2ed155 — seven-pair CPU/allocation/peak/retained exact-parent evidence.

Correctness:

  • all 15 local/UTC/Annex-B component setter forms ignore beyond-arity objects without invoking valueOf;
  • in-arity values remain converted once, left-to-right, after the captured [[DateValue]] and before any store;
  • direct former failure now returns OK 0;
  • Date test262: 594/594;
  • full unit gate: 1,565 passed, 1 skipped, 0 failed, 0 leaked;
  • four-lane no-GIL 2,048-call witness passes normally and under TSan.

Exact-parent evidence:

  • ten 4K warmup passes retain 9,273,552 fewer backing bytes and require 70 fewer growth events; GC-cell calls/bytes are identical;
  • 4K observed retained RSS is 0.9468× and peak RSS is 0.9469×;
  • identical setTime control is 1.0043× for retained and peak RSS;
  • 1K/2K/4K instruction ratios are 0.991× / 0.994× / 1.007× and control is 1.000×, establishing neutral CPU cost;
  • every seven-pair checksum matched, with no discarded samples.

Evidence is under docs/.data/exact-parent-date-*. No skipped in-arity coercion, cache, unbounded scratch storage, count limit, swallowed failure, strong retention, source recognition, or benchmark-only path was introduced.

Sign in to comment on this issue.