A typed-array loop version runs a checked copy and one or two fast copies
of the loop, and each copy repeats every nested loop together with the
nested loop's own version. A loop whose guard proves only accesses outside
its nested loops, which run once per pass, now runs as written when a
nested loop accesses typed arrays; the nested loops still version their own
accesses. The loop versions as before when the guard proves the bounds of
an access inside a nested loop, or, in a worker program, the ownership of
an access inside a nested while loop, which never versions for ownership
alone.
Spectral-norm's paired row sums no longer copy their column loop for the
row loop's two stores. The worker program's au and atu functions are
102 KB of LLVM text instead of 236 KB each, and the program 519 KB instead
of 786 KB.
Corpus typed-array-nested-loop-versions covers row loops that store past
the end or at negative, fractional and NaN rows, views the nested loop
writes, and a nested while loop.
Main resolves computed createRequire specifiers at run time, so a computed
require inside a function no longer makes an island; one in module code
still does.
String.prototype.indexOf took its byte-search fast path on a proven-ASCII
receiver only when the start index was not positive. A positive start went
through the general path: ToIntegerOrInfinity, the surrogate-needle check,
and UTF-16 to byte conversions in both directions, although byte offsets
are UTF-16 indexes in an ASCII string. The fast path now covers every start
index: a positive start truncates and clamps to the length, where only the
empty needle is found, and the search runs from that byte offset.
Main resolves computed createRequire specifiers at run time, so the
package's computed require no longer makes an island; a spread argument
list still does.
Every unbounded recursion repeats some cycle of the call graph, so a
stack check in one function of each cycle bounds it. stackCheckedFunctions
now picks a feedback vertex set of the stack-check graph greedily (the
function with the most caller-callee pairs first) instead of checking
every function on a cycle, and adds a check where a run of unchecked cycle
functions would exceed 32 calls, so the stack used between two checks
stays of the same order as before.
Worker entry polls follow: a synchronous function on a cycle that may
throw needs no entry poll, since a descent that never returns ends at a
checked function of its cycle. NoThrow contracts keep the model in which
every function on a cycle checks, a superset that does not depend on the
choice.
An untyped write of a present declared field of a live record capsule now
stores into the native record through a per-shape `set` hook (checked like
the commit, refusing to the snapshot path for values the field cannot hold),
so the capsule keeps answering from the record instead of turning into a
permanent snapshot. Object.assign from a plain object takes the same path,
and checked conversions and matches read a capsule through a fresh,
uncached snapshot.
A checked conversion of a record capsule into a record type whose storage
is a same-offset prefix of the capsule's record (and whose extra fields hold
no references) passes the pointer: both names keep one object, writes show
through either, and the record remembers its own capsule parameters, so
every later box of it and the narrower type's reflective surfaces answer
for the whole object (decision D3). Other cross-layout conversions keep the
refreshed copy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`skip || (flag ? warnA() : warnB())`, with void calls in both arms, as
React's development warnings write it, failed with SC9001 "ternary must
not be void": the statement lowered the logical as a value, and a
conditional of void calls has none. A logical whose result is discarded
now lowers as `if (!skip) ...` (or `if (skip) ...` for `&&`) when its
right operand needs no value: its type maps to void, or it is a logical
or comma expression whose last operand needs none. This holds in
statements and in a for loop's initializer and update, and for a
generic callback's conditional whose type parameter maps to void.
Closes#2322
Co-authored-by: MathurAditya724 <57684218+MathurAditya724@users.noreply.github.com>