← All reports

DateInstance packs its broken-down time inline

Component: JSC Date runtime | 6124a5f

DateInstance backs every JavaScript Date object. Converting a UTC timestamp into local year/month/day/hour requires a timezone lookup that is far too expensive to repeat per accessor, so the engine caches a "broken-down" calendar representation. Previously that cache lived in a separately allocated, reference-counted DateInstanceData block shared through a DateInstanceCache, which forced DateInstance to be a destructible GC object — heavier for JSC's collector — and meant a timezone change only invalidated instances still reachable from the cache.

This commit removes the RefPtr<DateInstanceData> entirely. Both the local and UTC breakdowns are packed into two inline 64-bit words (PlainGregorianDateTime) stored directly on the object, using bit-packed sentinel values to distinguish "never computed" from "stale", which makes DateInstance non-destructible. A new DFG/FTL node, DateGetStorage, takes an isUTC flag and lets compiled code read the matching packed word directly. Timezone changes now invalidate every live DateInstance via a heap scan rather than only the cache-reachable ones.

Date objects lose both their destructor and their heap allocation, and JIT-compiled accessors read a field with one inline load instead of chasing a pointer to a separate block. The load and its validity check can be shared across all accessors on the same Date, and the heap-scan invalidation fixes a real correctness bug where cached local-time fields could stay stale after a host timezone change.

The forward-facing pattern is an out-of-line cache collapsed into bit-packed inline storage with sentinel-encoded validity. Narrow: the encoding now carries three meanings in one word — never computed, stale, and a real date — so audit the sentinel choice against the full range of representable PlainGregorianDateTime values, since a collision would make stale data read as valid without any check firing. Wider: DateGetStorage makes the validity check the JIT's responsibility, and sharing that check across accessors on the same Date means the compiler must prove nothing between them can invalidate the word — enumerate the operations that write the packed fields or trigger the timezone heap scan, and check each against the effect declarations the node carries. Widest: every object that moves from an out-of-line refcounted cache to inline packed storage inherits the same two questions (sentinel disjointness and shared-check invalidation), so the same review applies to any future non-destructible conversion; the tell is a JIT node that returns storage rather than a value, since the validity check then lives at the use site rather than at the load.