mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-24 06:14:01 +08:00
Maps and Sets with number keys used as id tables (tsc-ts keeps node and symbol links in Map<number, Links>) hashed every key as a double. They now keep a direct index, dense[k] = entry index + 1, while every live key is an integer in [0, ndense) and the table stays within 8x the live count (64 slots minimum). The entries array, tombstones and iteration order are unchanged; only the lookup index differs. -0 lands on slot 0 (SameValueZero), and NaN, fractions, negatives and keys beyond the table are absent by construction. Inserting a key the table cannot hold moves the map to the bucket table; whenever that table would grow, compact integer keys move it back, so maps whose ids start far from zero switch over once their live count catches up. scr_map_entry_f64 and layout asserts expose the index to generated code. A randomized C test compares every operation with an ordered reference model across linear, direct and hashed indexes, and a corpus program pins the JavaScript-visible semantics around the transitions. Only growth moves a map to the direct index: an append that scr_map_reserve_append would absorb by compacting tombstones (a linear map with a dead entry, a bucket table at most half live, no iteration active) keeps the map's compact storage, so churn on a small number-keyed map no longer allocates a table. While an iteration is active nothing compacts, so a small map promotes to the direct index (integer keys) or the bucket table (other numbers) without moving entry indices. The runtime map test's small-storage script, which assumed bucket promotion and failed its two live-iteration checks, now runs with integer and fractional keys and checks both transitions, and the corpus program covers small maps growing and clearing mid-iteration.