mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-22 05:59:31 +08:00
% now checks at run time whether both operands are integers (dividend |x| <= 2^53, nonzero integer divisor) when the integer-range analysis cannot prove it, and then uses i64 srem with JS sign-of-zero semantics; fractions, NaN, Infinity, zero divisors and huge dividends keep frem. Proven integers whose divisor may be zero now only check for zero. push() appends inline while len < cap (the runtime append is exactly a dense store at len plus len+1 there) and keeps a cold runtime call that grows storage otherwise. Element writes were already inlined by H04. Built on the H04 commits cherry-picked from perf/h04-array-reads (d88b58a1, a6057a52, 9109cb5a, 657aa3fb). New corpus programs 3150-integer-remainder and 3151-array-push-writes. Marginal vs perf/h04-array-reads, 15 runs: | workload | macOS | Linux (focused) | | numeric-kernels | -18.3% | -10.3% | | functional-pipeline | -8.8% | -4.3% | | template-render | -2.9% | (layout, sweep -0.6%) | | alloc-trees | -2.0% | (layout, sweep +0.3%) | | records-sort | -1.5% | -0.3% | | csv-numbers | -0.3% | +0.1% | geomean marginal: macOS -2.8%, Linux full -0.6%. vs perf/harness (incl. H04): macOS -14.4% (1.222x Node), Linux -16.0% (1.160x Node). Linux .text growth <= 3.6%. Tests: LLVM differential corpus 2008/2008 (Linux, 6 shards, release+dev), sanitized 3140/3150/3151 pass, backend+ir unit tests pass except one load-flaky zig COFF cache test that passes in isolation.
82 lines
2.9 KiB
TypeScript
82 lines
2.9 KiB
TypeScript
// push() appends inline while the dense storage has room and keeps the
|
|
// runtime append when it is full; element writes keep the runtime path for
|
|
// holes, growth, and sparse indices. Lengths, holes, and reference counts
|
|
// must match Node at every boundary.
|
|
|
|
const nums: number[] = [];
|
|
let lengths = 0;
|
|
for (let i = 0; i < 100; i++) lengths += nums.push(i * 1.5);
|
|
console.log("nums", nums.length, lengths, nums[0], nums[99]);
|
|
|
|
// Return value used directly, and NaN / -0 payloads survive the store.
|
|
const special: number[] = [1];
|
|
console.log("push ret", special.push(NaN), special.push(-0), special.push(Infinity));
|
|
console.log("special", Object.is(special[2], -0), Number.isNaN(special[1]!), special[3]);
|
|
|
|
// Truncation, then pushes land at the new length.
|
|
const trunc: number[] = [1, 2, 3, 4, 5, 6, 7, 8];
|
|
trunc.length = 3;
|
|
trunc.push(40);
|
|
trunc.push(50);
|
|
console.log("trunc", trunc.length, JSON.stringify(trunc));
|
|
|
|
// Extending length creates holes; push lands after them.
|
|
const ext: number[] = [1, 2];
|
|
ext.length = 6;
|
|
ext.push(7);
|
|
console.log("ext", ext.length, 2 in ext, 5 in ext, 6 in ext, ext[6]);
|
|
|
|
// Writes creating holes, then push past them.
|
|
const holes: number[] = [];
|
|
holes[3] = 3;
|
|
holes.push(4);
|
|
holes[10] = 10;
|
|
holes.push(11);
|
|
console.log("holes", holes.length, JSON.stringify(holes), 0 in holes, 4 in holes, 9 in holes);
|
|
|
|
// pop() then push reuses the freed slot.
|
|
const pp: string[] = ["a", "b", "c"];
|
|
const popped = pp.pop();
|
|
pp.push("d" + popped);
|
|
pp.push("e");
|
|
console.log("pop push", pp.length, pp.join(","));
|
|
|
|
// Boolean and reference elements (strings, records, nested arrays).
|
|
const flags: boolean[] = [];
|
|
for (let i = 0; i < 37; i++) flags.push(i % 3 === 0);
|
|
console.log("flags", flags.length, flags.filter((f) => f).length, flags[36]);
|
|
interface Rec {
|
|
id: number;
|
|
tag: string;
|
|
}
|
|
const recs: Rec[] = [];
|
|
for (let i = 0; i < 50; i++) recs.push({ id: i, tag: "t" + (i % 7) });
|
|
const shared = recs[10]!;
|
|
recs.length = 5;
|
|
recs.push(shared);
|
|
recs.push(shared);
|
|
console.log("recs", recs.length, recs[5]!.id, recs[6] === shared, shared.tag);
|
|
const grid: number[][] = [];
|
|
for (let r = 0; r < 4; r++) {
|
|
const row: number[] = [];
|
|
for (let c = 0; c < 9; c++) row.push(r * c);
|
|
grid.push(row);
|
|
}
|
|
console.log("grid", grid.length, grid[3]!.length, grid[3]![8], JSON.stringify(grid[2]));
|
|
|
|
// Overwrite references in place (release of the replaced value).
|
|
const words: string[] = ["x", "y", "z"];
|
|
for (let i = 0; i < 1000; i++) words[i % 3] = "w" + i;
|
|
console.log("words", words.join(","));
|
|
|
|
// Cross the dense storage limit with push and keep counting correctly.
|
|
const big: number[] = [];
|
|
const limit = (1 << 20) + 17;
|
|
for (let i = 0; i < limit; i++) big.push(i & 1023);
|
|
let bigSum = 0;
|
|
for (let i = 0; i < big.length; i += 4099) bigSum += big[i]!;
|
|
console.log("big", big.length, big[limit - 1], bigSum, big.push(5), big[limit]);
|
|
big.length = 10;
|
|
big.push(99);
|
|
console.log("big trunc", big.length, big[10], 11 in big);
|