Commit Graph
5394 Commits
Author SHA1 Message Date
Chris Tate 928c30e908 Bind thisArg in the array callback methods of dynamic arrays
forEach, map, filter, some, every, find, findIndex, findLast,
findLastIndex and flatMap on a dynamic array, and through
Array.prototype.<method>.call on a native array, called the callback
without its thisArg, so `this` in the callback was not the second
argument. These methods now bind `this` to the thisArg, or undefined
when there is none, once per call, around all of the method's callbacks.
2026-10-26 10:19:57 -05:00
Chris Tate a59df23c71 Merge main 2026-10-26 07:21:12 -05:00
Chris Tate 636c7631b3 Keep program partitions local to the code an edit changes (#2328) 2026-10-26 06:35:05 -05:00
Chris Tate 067f146e87 Read builtin globals through the global object, and support Node's navigator (#2242) 2026-10-26 06:16:08 -05:00
Chris Tate e559baacde Skip repeated probes in lowering (#2330) 2026-10-26 05:47:59 -05:00
Chris Tate 66b6ca53ce Load a Node module's fallback declarations only when the program names it (#2256) 2026-10-26 05:37:36 -05:00
Chris Tate b8aaa5985a Merge main 2026-10-26 05:23:00 -05:00
Chris Tate addecf6a02 Skip repeated probes in lowering 2026-10-26 05:17:10 -05:00
Chris Tate 2d2343e36f Keep program partitions local to the code an edit changes 2026-10-26 05:03:24 -05:00
Chris Tate 9c3b336f76 Import callees of up to 40 instructions across program partitions (#2325) 2026-10-26 04:50:47 -05:00
Chris Tate 9f51ab61d9 Keep the integers of typed-array reads in locals for indices and loop guards (#2327) 2026-10-26 04:40:10 -05:00
Chris Tate 4553941d84 Merge main 2026-10-26 04:25:15 -05:00
Chris Tate ddf5b1f8e0 Keep the integers of typed-array reads in locals for indices and loop guards
A local that only holds exact integers or NaN, such as one assigned from
an integer typed-array read, now keeps whether it is NaN beside its
integer view. Its reads, and sums, differences and products of them,
carry an i64 that holds the integer whenever the number is not NaN, so
an index check or a counted loop's guard tests that integer and the
ordered bit instead of converting the double back and checking that it
is an exact integer.
2026-10-26 04:08:25 -05:00
Chris Tate c66ce24a73 Fix Array.prototype calls on native arrays, typeof on ambient names, and net connections to Unix sockets
Fixes #2116
Co-authored-by: 4ndual <44326858+4ndual@users.noreply.github.com>
Fixes #2134
Co-authored-by: dolphin278 <1130473+dolphin278@users.noreply.github.com>
Fixes #2142
2026-10-26 03:57:37 -05:00
Chris Tate 2ad699c98a Compile classes that extend Array (#2059) 2026-10-26 03:57:16 -05:00
Chris Tate ae3d388869 Merge main 2026-10-26 03:53:02 -05:00
Chris Tate ba2aadcb81 Import callees of up to 40 instructions across program partitions
The thin link imported a callee of up to 100 instructions, LLVM's default,
into every partition that calls it, and each partition then optimized and
compiled its imported copies again. Partitioned programs now import callees
of up to 40 instructions. Programs that compile as one module are
unchanged.
2026-10-26 03:32:39 -05:00
Chris Tate e289b03ddc Keep int32 fields in programs with adopting casts (#2324) 2026-10-26 03:27:40 -05:00
Chris Tate 56e3f3e5a0 Update the npm cases that reading builtin module members as globals changes
require("buffer").Blob and timers.setTimeout now read as their global
spellings, so island-web-plumbing and misc-shims run past the SC2020
they stopped at and reach a later deferred SC1090: require() inside a
function in plumbing, and constructing a value that is not a program
class in misczoo. fetch-destructure reads fetch from the aliased global
object and matches Node.
2026-10-26 03:14:33 -05:00
Chris Tate eec525dc6a Fix eight compiler and type bug reports (#2319) 2026-10-26 03:10:55 -05:00
Chris Tate 6c1ddbf390 Keep int32 fields in programs with adopting casts 2026-10-26 02:57:52 -05:00
Chris Tate acf19e2652 Merge main 2026-10-26 02:53:26 -05:00
Chris Tate 7a8ec3f3d2 Hold locals and module globals whose declared type does not compile as checked dynamic slots (#2292) 2026-10-26 02:49:06 -05:00
Chris Tate 7183a76422 Address review: missing strings in bindings and calls, evaluated recursive flags
- A string held in a binding or returned by a call can be a missing element
  read (undefined), so `head + PAD[j]` and `at(i) + PAD[j]` still add to NaN
  when both are missing. Only string literals, templates and sums with such
  an operand now count as always a string.
- `readdirSync(path, { recursive })` folds only the `true` and `false`
  keywords. Any other flag expression, including one typed as a literal,
  evaluates at run time for its effects and exceptions.
2026-10-26 02:42:04 -05:00
Chris Tate f52806988d Read typed-array header fields once at a speculative loop's entry (#2321) 2026-10-26 02:33:23 -05:00
Chris Tate 3512b288ad Order the native compiler's cold functions by how many builds run them (#2320) 2026-10-26 02:33:05 -05:00
Chris Tate 035d618517 Store a table entry for if/else chains that store literals to one element (#2317) 2026-10-26 02:21:51 -05:00
Chris Tate 8a37d54e65 Register classes and functions with dynamic slots when a reference flushes their type failures (#2293) 2026-10-26 02:14:26 -05:00
Chris Tate eaa8a44cdf Read typed-array header fields once at a speculative loop's entry
A speculative integer loop's fast copy exits to a copy that resumes the
failed iteration, and both read the header fields of the views they
access. GVN's load PRE moved the fast copy's read of a view's data
pointer ahead of the exit branch, to make the resume copy's read
redundant, and put a copy on the exit edge. The loop then kept its first
iteration in the loop, so the overflow checks of a value whose range is
known after one iteration stayed in every iteration, with a reload of the
data pointer.

A view held by a const local or a parameter that the loop does not rebind
is the same view in every iteration, and its length, data pointer and
shared storage never change. The loop's entry now reads them once, and the
element accesses of every copy use those values.
2026-10-26 02:02:46 -05:00
Chris Tate 71de76b813 Order the native compiler's cold functions by how many builds run them 2026-10-26 02:02:18 -05:00
Chris Tate e03afc25f3 Add range-proof regression cases for constant-choice tables 2026-10-26 01:51:53 -05:00
Chris Tate 055d1f9682 Fix eight compiler and type bug reports
Co-authored-by: dolphin278 <1130473+dolphin278@users.noreply.github.com>
Fixes #2139
Fixes #2131
Fixes #2132
Fixes #2133
Fixes #2140
Fixes #2141
Fixes #2159
2026-10-26 01:50:59 -05:00
Chris Tate 5d62d5a5f1 Read a constant choice's index as on every path when it is the compared local
The store a constant choice emits for its arms used the first arm's
index expression, with the ranges proven inside that arm. When the index
is the compared local, `j === 0` narrows it to [0, 0] there, so the one
store, which also runs on the final else's path, converted the index to
an int32 from that range. For `j` = 4294967297 that conversion has no
defined result, and the bounds check that follows could accept it: an
out-of-bounds write could reach a valid element.

The store now reads such an index through the first comparison's
operand: the same local, read before the chain branches, so its range
holds on every path. An index that is another local is not narrowed by
the comparisons and is unchanged.
2026-10-26 01:47:16 -05:00
Chris Tate 70eac263f7 Merge lf/l1-whole-slot 2026-10-26 01:43:44 -05:00
Chris Tate 771706cfbe Wait for the lookup connection's accept in 7515 before changing the server's mode (#2318) 2026-10-26 01:38:08 -05:00
Chris Tate 60bd974744 Wait for the lookup connection's accept in 7515 before changing the server's mode
7515-net-socket-backpressure's server picks each connection's handling from
`mode` when it accepts it. The lookup client's 70000 bytes fit in the
kernel's buffers, so its 'drain', and the step that sets `mode` to "pause",
can run before the server accepts that connection. On macOS the accept can
come in a later kqueue batch: the server then paused the lookup socket,
never read its EOF, and the open connection kept the program running after
server.close(). The program now waits for that accept before it changes
`mode`. Its output is unchanged.
2026-10-26 01:10:20 -05:00
Chris Tate a28afa0261 Find bridgePlainUnwindCalls' calls and mentions with indexOf (#2316) 2026-10-26 01:08:35 -05:00
Chris Tate 33be2a80ee Store a table entry for if/else chains that store literals to one element
An if/else-if chain that compares one number local with integer literals
and stores a number literal to the same typed-array element in every arm,
including a final else, such as

    if (x === 97) a[i] = 0;
    else if (x === 116) a[i] = 1;
    else if (x === 99) a[i] = 2;
    else a[i] = 3;

is now emitted as one store of an entry of a constant table indexed by
the local's value (constant-choices.ts). On input whose cases do not
repeat in a pattern, such as the bases of a DNA sequence, the branches
mispredict; LLVM keeps them, because cases this far apart are too sparse
for its own switch tables.

The chain needs at least three distinct values within 256 of each other.
The table covers the cases' span, or the local's proven integer range
when that range has at most 256 values, in which case no test is
emitted. Otherwise a value that is not an exact integer in the table's
span (NaN, a fraction, or a value outside it) stores the final else's
literal, chosen with a select. The first arm wins for a repeated
value, and -0 selects the arm for 0, as strict equality does. The store
is the arms' own (the same receiver and index), converted to the
element's type as each arm's would be. Debug builds keep the arms.

k-nucleotide's transform of the input sequence uses this form: its
median wall time drops from 2.71 s to 2.21 s.
2026-10-26 01:04:42 -05:00
Chris Tate 2a0d115629 Keep a candidate's generation when a limited cycle pass reaches it (#2315) 2026-10-26 00:55:26 -05:00
Chris Tate 2d24d6ad80 Merge main 2026-10-26 00:41:23 -05:00
Chris Tate 2e142d6121 Find bridgePlainUnwindCalls' calls and mentions with indexOf
bridgePlainUnwindCalls rewrites the module text after emission on Linux.
It split the text with a lookahead regular expression, ran a regular
expression over every line to find mentions of raising functions, and
split every function that has calls into lines to test each one.

- The text splits before each `define` line with indexOf.
- Mentions of raising functions are found by scanning for `@` and reading
  the name that follows it.
- A function without a plain call of a raising function rewrites only the
  lines that hold `call `, marking them nounwind. A function with such a
  call takes the line-by-line path as before.

The emitted text is unchanged.
2026-10-26 00:40:44 -05:00
Chris Tate e2a22aa1bc Localize merged program shards in process on Linux (#2310) 2026-10-26 00:31:57 -05:00
Chris Tate 77f65a7264 Skip the element read for array callbacks that never use it (#2286) 2026-10-26 00:29:20 -05:00
Chris Tate 7e3d10fa13 Lay out the native compiler's functions by the code each kind of run executes (#2265) 2026-10-26 00:29:02 -05:00
Chris Tate 11aa86d571 Cache named child nodes and text on AST nodes (#2314) 2026-10-26 00:26:48 -05:00
Chris Tate feb4501013 Keep a candidate's generation when a limited cycle pass reaches it
A limited pass (scr_cyc_collect_set, which freeing a LifetimeRegion runs
over the objects the region owned) takes only the candidates in its set.
Its walk can still reach other candidates, and one that is referenced from
outside is blackened by scan and promoted to the next generation while it
keeps its slot in its old generation's buffer. scr_cyc_on_dead finds a
candidate's buffer by its generation, so when that object died it removed
another buffer's entry and left its own slot pointing at the freed block,
which the next pass then read.

Such a candidate is no longer promoted: it keeps the generation of the
buffer it is in until a pass takes it.
2026-10-26 00:24:05 -05:00
Chris Tate e7b60a5302 Read and write shared typed-array elements at a counted loop's counter with plain accesses (#2309) 2026-10-26 00:23:15 -05:00
Chris Tate 21bce9e4fa Merge main 2026-10-26 00:21:24 -05:00
Chris Tate b090950ffe Read undeclared literal keys as undefined and keep filled-in JavaScript vars dynamic (#2311) 2026-10-26 00:08:06 -05:00
Chris Tate 04c0e5c66e Cache named child nodes and text on AST nodes
The frontend reads the same children of the same nodes many times: on a
tsc-ts build, `expression` is read 29.6M times over 253K nodes, `name`
16.4M times over 176K and `text` 26.8M times over 456K. Each read went
through AstFile.namedChildAt (the file check, the child mask, the packed
child table) and AstFile.node (the node table), and `text` through the
wire's kind switch and string table.

- AstNode.childNodeAt keeps the child nodes it has read, by wire slot, in
  a per-node array sized to the node's highest named child.
- AstNode.text keeps the text it has read.
- AstFile's packed child table is a Uint32Array from the start (empty
  until the first named child is read), so namedChildAt no longer
  retains and releases an optional value on every call.

Cold tsc-ts build with the native compiler, 16 interleaved rounds: lower
31.68 -> 30.46 s, wall 78.81 -> 76.56 s (faster in every round); peak RSS
+105 MB, which the frontend-dispose heap trim keeps below main's peak.
2026-10-25 23:57:36 -05:00