Commit Graph
6750 Commits
Author SHA1 Message Date
Chris Tate 8a2b6271a9 Merge perf/shape-table-dispatch 2026-10-26 12:29:35 -05:00
Chris Tate 68e2556fda Merge main 2026-10-26 12:24:22 -05:00
Chris Tate 53896238c4 Regenerate the IR field readers and fix the shard tests 2026-10-26 12:18:56 -05:00
Chris Tate 2cdd286f66 Talk to TypeScript 7.1's API server beside 7.0's
The TypeScript session reads initialize's answer to tell a 7.1 server
(caseSensitivity) from a 7.0 one (useCaseSensitiveFileNames), and on a
7.1 server sends 7.1's requests and reads its answers:

- snapshots: the first comes from createSnapshot and later ones from
  updateSnapshot with the latest snapshot as the base, which the server
  keeps until the next update. Each asks for current programs
  (ensurePrograms), and a project's root files and options come from its
  parsed command line. Projects an update does not list carry over from
  the base.
- symbols: a symbol is named by its reference, a source file or the
  snapshot and project that owns it plus its id. The semantic model keeps
  numeric symbol ids: each reference, and each compact reference other
  answers hold, gets a local id, and requests send the reference back.
  Symbol property methods take it in `symbol`.
- requests: getApparentType, getConstraintOfTypeParameter,
  getNonNullableType and getReturnTypeOfSignature name their type or
  signature in `objectId`, the diagnostics methods take `files`, and
  signatureToSignatureDeclaration's kind is a 7.1 SyntaxKind.
- answers: isTupleType is read from the type, JsxEmit's React and
  ReactNative values are swapped back, and parseConfigFile returns the
  options and file names.
- file system callbacks reply with {kind, value}: a value, "missing" for
  a hidden path, or "useOS" to delegate to the server.

The session, checker and semantic checker tests run against tsc 7.0.2 and
against tsc 7.1.0-beta, from the typescript-7.1 test dependency.
2026-10-26 12:13:27 -05:00
Chris Tate 9b4a6ffdf1 Regenerate the IR field readers for dynCheck's inferred site (#2347) 2026-10-26 12:08:27 -05:00
Chris Tate 5b29eb1bae Merge main 2026-10-26 12:07:21 -05:00
Chris Tate 91014dfb66 Read TypeScript 7.1's binary AST format beside 7.0's (#2346) 2026-10-26 11:59:28 -05:00
Chris Tate 06f7b8631f Merge perf/shape-overlay-cost 2026-10-26 11:53:34 -05:00
Chris Tate a15c6aba4a Regenerate the IR field readers and fix the shard tests 2026-10-26 11:52:15 -05:00
Chris Tate 34c2f9851d Have the native CLI packages depend on their LLVM helper and runtime pack (#2333) 2026-10-26 11:47:34 -05:00
Chris Tate 18755e0599 Allocate object groups that die together in arenas 2026-10-26 11:41:21 -05:00
Chris Tate 6dbdf39120 Track a stream's 'data' listeners instead of looking them up per chunk (#2344) 2026-10-26 11:38:04 -05:00
Chris Tate 2f13edd058 Merge main 2026-10-26 11:36:06 -05:00
Chris Tate 341ddd41ae Regenerate the IR field readers for dynCheck's inferred site 2026-10-26 11:34:57 -05:00
Chris Tate de6cdf1156 Add the shape overlay: typed JavaScript from analysis-proven facts (opt-in) (#2176) 2026-10-26 11:33:47 -05:00
Chris Tate ce1f3c4d2b Read TypeScript 7.1's binary AST format beside 7.0's
The AST reader accepts protocol 9, TypeScript 7.1's encoding, as well as
protocol 5 (7.0's), so scriptc can read either checker's responses:

- the 64-byte header of protocol 9;
- its node kinds, which count 7.1's SourceKeyword: each kind above it
  reads as 7.0's, and node handles name the response's own kinds;
- a module declaration's child mask, whose attributes slot moves the
  body to slot 3.

A protocol 9 response with a node 7.0 has no form for (a SourceKeyword
node, import attributes on a module declaration, or an `import source`
clause) throws an AstDecodeError that names it.
2026-10-26 11:27:36 -05:00
Malte UblandClaude Opus 5.5 dc1e8acc1d Store ordinary objects as a layout plus value slots
A checked object (SCR_DYN_OBJ) now starts in layout mode: v.obj.layout names
its key sequence, a node of the thread's interned transition tree, and
v.obj.slots holds one 8-byte value per key, where every property used to take
a 48-byte entry. All properties of a layout-mode object are writable,
enumerable, configurable data properties. An accessor, a non-default
attribute, a delete, more than 64 keys, spent layout budgets, publication to
other threads, or any code that reads entries directly moves the object to
dictionary mode (today's entries) for good, so unported paths stay correct.

Layouts replace the dynamic tier's lazily computed hidden classes (ScrJsShape)
and keep their budgets. Inline caches key on the layout pointer and read the
slot directly; JSON.parse builds objects along layouts; stringify, key
enumeration, release, trace and the runtime read cache read slots in place.
The emitted index-signature checks read members through runtime accessors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:18:53 -07:00
Chris Tate d163df4674 Merge perf/shape-table-dispatch 2026-10-26 11:18:17 -05:00
Chris Tate a5971450ec Tear down self-recursive records and classes in one loop (#2343) 2026-10-26 11:14:35 -05:00
Chris Tate d1963dc8a5 Test a scalar optional left of ?? in JavaScript on the typed path
In JavaScript, `counts.get(key) ?? 0` on a Map the compiler types as
Map<string, number> is typed `any` by the checker, so `??` was lowered
on checked-dynamic values: the `number | undefined` read converted to a
dynamic value, which allocated a heap union for every read, and the test
ran on that value.

When the left of such a `??` is a union of one number, boolean or string
arm with undefined or null, and the default has the same type, the test
and the default now run on the typed path, where the read needs no heap
union, and only the result converts to a dynamic value. Other defaults
keep the dynamic path.

New corpus program: untyped-nullish-scalar-defaults.mjs.
2026-10-26 11:12:57 -05:00
Chris Tate 6622ae4e22 Merge perf/static-objects 2026-10-26 11:10:12 -05:00
Chris Tate b1b6b98c0d Compare canonical mapping with mapType in an opt-in shadow mode (#2334) 2026-10-26 11:03:38 -05:00
Chris Tate cc5c81fb4d Keep frontend snapshots stable when a file is read before and after it settles (#2342) 2026-10-26 11:02:20 -05:00
Chris Tate 37131030ff Merge perf/shape-overlay-core 2026-10-26 11:01:59 -05:00
Chris Tate e7f3ab29c2 Track a stream's 'data' listeners instead of looking them up per chunk
Each chunk a readable side delivered looked up its 'data' listeners by
name twice: once to decide whether a flowing stream emits directly, and
again in emit('data'), which scans the stream's event names even when a
piped stream has no 'data' listener at all. The stream now keeps a
data_listeners flag, set from the emitter registry's empty/nonempty
transitions through scr_emitter_observe, and reads it on those paths;
emit('data') is skipped when the stream has no 'data' listener.
2026-10-26 10:59:32 -05:00
Chris Tate fbd82745e3 Merge the island stack base 2026-10-26 10:58:36 -05:00
Chris Tate 1e2887c22b Degrade the types of a statement's own expressions where the statement commits (#2308) 2026-10-26 10:57:29 -05:00
Chris Tate 09a73ab6ed Fix Array.prototype calls on native arrays, typeof on ambient names, and net connections to Unix sockets (#2326) 2026-10-26 10:56:58 -05:00
Chris Tate 6e4fdf95d0 Link the exported bootstrap package's helper and runtime pack dependencies
The native bootstrap's package checks copy the seed's distribution into a
package directory outside the workspace and, since the CLI packages depend
on their LLVM helper and runtime pack, drop the bundled copies. Nothing in
that directory resolved @scriptc/llvm-linux-x64-gnu, so
verify-native-cli.mjs failed with 'Cannot find module'. The test now links
both packages into the directory's node_modules, as pnpm links a workspace
package's dependencies.
2026-10-26 10:56:27 -05:00
Chris Tate 36273adc8f Unroll counted loops by the period of a guard on the counter's low bits (#2341) 2026-10-26 10:56:09 -05:00
Chris Tate d5dc896576 Merge main 2026-10-26 10:53:46 -05:00
Chris Tate a17b727e91 Address review feedback 2026-10-26 10:51:18 -05:00
Chris Tate 48c521dc27 Address review feedback 2026-10-26 10:43:59 -05:00
Chris Tate 9b96314c20 Tear down self-recursive records and classes in one loop
The teardown of a type with children of its own type called itself for
each child: a call, its register saves and the segment bookkeeping per
node, 45 instructions per node in a binary tree.

A record or standalone class whose every reference field holds its own
type and that has no collector header now tears down in one loop. A child
whose last reference the dead node held goes onto a pending list linked
through its own count word, which it no longer needs, and the loop takes
the list's first node next, so nodes are visited parent first. Each node
frees its block as before (dispose observers, the RC audit, blocks of
other arenas), the calling thread's blocks go into the teardown segment
in visit order, and the segment goes onto the free list in one step, so a
structure built parent first takes the blocks in its allocation order.
Shared and immortal children keep their release. The loop needs no depth
budget. Other teardowns keep the recursive form.
2026-10-26 10:42:41 -05:00
Chris Tate dec2b8a454 Record one probe for two reads of a file that saw the same content
A read within IDENTITY_SETTLE_MS of a file's last write records no
identity, and a later read of the same bytes in the same frontend does.
FrontendInputTracker.record compared the two probes as JSON and marked
the snapshot unstable. A build or coverage run that read its entry
before and after that point then published no cache entry: the exact
repeat of a build lowered again, and a coverage verdict was not replayed.
Two file probes with the same digest now merge into one that keeps the
settled identity; any other difference still marks the snapshot
unstable.
2026-10-26 10:33:02 -05:00
Chris Tate 6fa88c7243 Observe every top-level mapping in the canonical shadow 2026-10-26 10:32:41 -05:00
Chris Tate 4c5c0823ce Address review feedback 2026-10-26 10:20:11 -05:00
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 be293e3dfb Unroll counted loops by the period of a guard on the counter's low bits
A counted loop whose body branches on `(i & M) === C`, with M one of 1, 3
and 7 (a check every second, fourth or eighth iteration), now asks LLVM to
unroll it by M + 1 (llvm.loop.unroll.count on its back edge). In each
unrolled copy the counter's low bits are known, so the guard folds to a
constant and only one copy per period keeps the check. Before, LLVM tested
the guard on every iteration and, when the guarded condition was cheap,
evaluated that condition on every iteration too.

The loop must step by 1 from a multiple of the period, have no nested
loop, and stay under 4096 IR nodes once unrolled. Loops with the same
period share one loop ID node, which the module emits only when a back
edge refers to it.
2026-10-26 10:19:25 -05:00
Chris Tate cd4950c25f Never let the shape overlay break compilation (#2219) 2026-10-26 10:19:06 -05:00
Chris Tate 0b12340ead Merge the libnode loader and mark e04 as a race 2026-10-26 10:18:44 -05:00
Chris Tate 26b2fdcc67 Read IR nodes' fields by name in three llvm-emit passes (#2336) 2026-10-26 10:17:48 -05:00
Chris Tate 1947bf66c7 Release a substitution's operands when it returns (#2337) 2026-10-26 10:17:28 -05:00
Chris Tate b926722ad3 Evaluate writes and indices through missing asserted elements in Node's order
`xs[i]!.name = v` threw while it evaluated the receiver, so a missing
element skipped the value's side effects and hid an error the value threw.
Node evaluates the array, the index, the key and the value, then the write
throws "Cannot set properties of undefined". Such a write, in statement or
value position, now evaluates them in that order and then tests the
element: a missing one throws Node's TypeError, a present one takes the
write. The array and the index are held only when the key or the value
can assign a binding or field, and a key or value whose evaluation is
unobservable stays in the write. A key of any number or string value is
named in the message, since the write holds it.

An index that replaces the array binding or field (`xs[(xs = other, 0)]!`)
ran before the member access and the string conversion read the array, so
they read the replacement. The array is now held before such an index, as
JavaScript reads it first; an index that cannot assign keeps the plain
read.

Corpus 7395 covers both orders.
2026-10-26 10:16:54 -05:00
Chris Tate c1ad72e1a4 Build the candidate's own compiler source in the zero-cost gate (#2339) 2026-10-26 10:15:57 -05:00
Malte UblandClaude Opus 5.5 812aa3a7bb Close the largest canonical-mapping gaps the shadow census found
- 'this' in a class body maps through the nominal table (it is the class).
- An unbound type parameter maps through the lowerer's IR-level binding,
  which is how generic class instances bind their parameters.
- An intersection that refines a class (a mixin instance, 'T & Class') is
  that class, not a merged record.
- An object whose members do not map structurally (an interface over Map
  or Set, method-only interfaces) keeps its per-type recognition.

On a 160-program sample of the corpus (generic classes, interfaces, Maps),
the shadow census goes from 78.7% equal (2,936 canonical failures, 943
divergences) to 98.0% equal (25 failures, 343 divergences).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 07:21:05 -07:00
Malte UblandClaude Opus 5.5 5aa6699b3d Build the candidate's own compiler source in the zero-cost gate
The self program compiles the compiler source of the checkout the programs
come from (the baseline by default), so a change adding compiler code the
self-hosted frontend cannot lower passed the gate and failed CI's
self-hosting tests. With the self set, the gate now also builds the
candidate's packages/compiler/src/native/cli.ts with the candidate (LLVM
only, not compared) and fails when that build fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 07:09:02 -07:00
Malte Ubl 1c0f911897 Merge remote-tracking branch 'origin/lf/l4-expressions' into lf/n2-fallback 2026-10-26 07:08:25 -07:00
Malte UblandClaude Opus 5.5 08cc15d872 Keep canonical degraded entries when a declaration retry rolls back
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 07:07:50 -07:00
Chris Tate 823ebd50dc Resolve each shipped declaration path once (#2335) 2026-10-26 08:42:47 -05:00