LLVM's WebAssembly pass that gives multiple-entry loops a single entry
first records, for every block, every block it can reach. Its time and
memory grow with the square of a function's block count even when the
function has no such loop. In the three.js nodes fixture a module
initializer of 40,000 blocks spent four minutes and 22 GB in it, which
set the helper's peak and most of its wall time.
The helper now runs the pass only on functions whose control flow graph
is irreducible, and WebAssembly object emission leaves out the module
pass that collects external symbols for assembly declarations, so each
function's machine code is freed once it is printed. Optimized
partitions are compiled through the thin backend's pre-codegen hook to
use the same pipeline. Objects are unchanged.
check_discard ran trim_allocate again for its returned-regions case, which
writes the blocks into trim_blocks, the array check_trim had freed. Where
glibc maps an 8 MB block by itself (its adaptive mmap threshold, which the
allocator's heap policy leaves alone unless transparent huge pages are in
madvise mode), the free unmaps it and the worker thread's first write
faults. The case now allocates the array again and frees it.
The check that a worker takes the free blocks set aside compared the
highest block it carved with that of the worker before it, which took its
blocks from free lists below the slice's frontier, and it passed when a
worker never took them. Each run now counts the blocks it allocates past
the highest block of the class so far: at most the bump room the slice had
left, against all of them when a worker does not take the free blocks. The
residency bound after a discard allows for pre-fault requests still in
flight.
querystring.parse and querystring.decode build their result with a null
prototype, as Node does: util.inspect prints the [Object: null prototype]
base, Object.getPrototypeOf answers null, ToPrimitive throws a TypeError,
and Object.prototype methods are not reachable through the result.
An inline JavaScript callback receives a matchAll row as a dynamic
array. The groups projection now reads its captures through dynamic
index reads, and throws Node's TypeError for null and undefined rows.
Rows kept by filter, slice, toReversed and toSorted, or picked by find,
findLast and at, trace to the drain's regex; a reassigned callback
parameter does not. { groups } patterns serve dynamic rows and pattern
parameters. The groups record has a null prototype.
maybeNarrow takes the receiver's declared shape from its non-nullable
type, so a JavaScript read of a nonparticipating group keeps its
undefined arm instead of narrowing to string.
`"method" in instance` on a class instance held as `any` answered false
for the class's methods, getters and setters when the program also uses
instanceof or Object.getPrototypeOf on the class. Those uses attach the
class's prototype data to the instance's snapshot, and that object holds
only the methods the program reads through the prototype; the literal-key
`in` then searched it instead of the class.
When a literal key names a method or accessor of a boxed class with
prototype data, the class dynamic-dispatch pass now evaluates `in`
through the computed-key form, which answers class members from the class
itself.
renderDiagnostics printed every frame line whole and rebuilt the
file's line index for each diagnostic. On minified sources with
thousands of diagnostics the joined report exceeded V8's string length
and `scriptc coverage` crashed with RangeError: Invalid string length.
Frame lines longer than 400 characters now show a 400-character window
around the diagnostic's column, with "…" where text is cut, and the line
index is built once per file. Every diagnostic is still rendered.
Closes#201
Co-authored-by: Max B <32987678+techfreaque@users.noreply.github.com>
On Linux, a worker thread that exits without having made any object it
allocated reachable from another thread gives back all of its memory: the
pages it carved, including ProgramLifetime instances and other objects it
never freed, and the system blocks it still holds.
A worker carves past each slice's frontier while the arena's free lists and
returned regions are set aside, takes from those free lists only once a
slice has no bump room left, and records the system blocks it allocates.
Messages and intern tables that share published graphs by pointer, and the
process-wide key arrays of typed records, mark the thread as sharing; so
does a remote free of one of its blocks. When a worker that did not share
parks, the trim helper returns its pages, frees its system blocks, and
restores the arena to its state at the claim, with the free blocks the
worker took free again. A worker that shared keeps its memory as before.
SCR_SA_DISCARD=0 keeps every worker's memory; SCR_SA_DISCARD=poison makes
the discarded pages inaccessible instead, for tests.
A Hash or Hmac that flows into an unknown or any slot, or into untyped
JavaScript code, is now a native handle (Hash or Hmac) instead of a
compile error. The handle keeps the value's identity, so a cast back to
Hash or Hmac answers the same value. update(), digest() and Hash's
copy() dispatch through it, called directly or read as values: update
is one function for Hash and Hmac and digest is one per class, as in
Node 24.22, and update() answers the receiver. The stream and event
members throw a coded SC2020 error there, as do the methods called with
another receiver; other names read as undefined.
The to-dyn conversion boxes a Hash or Hmac through
scr_crypto_hash_to_dyn, which installs the handle ops on first use, so
programs that never box one link none of the handle code.
A native handle read through `as any` now dispatches its method calls
through the handle. Calling copy() on an Hmac throws Node's TypeError
("mac.copy is not a function") after the arguments are evaluated,
instead of the method-call fence.
Corpus 5768 and 5769 cover the TypeScript and JavaScript forms against
Node 24.22, and errors.test.ts covers the SC2020 cases. corpus-costs.json
records their plain and sanitized costs.
Inside a monomorphized generic body the checker keeps mapped types over
the function's own type parameters symbolic. The instance binds those
parameters, so { [K in keyof S]: T } now maps each property of the bound
type through the template evaluated at that key, covering indexed
templates (S[K], S[K]["_output"]) and conditional ones with infer
(S[K] extends Schema<infer T> ? T : never). Conditional types over bound
parameters evaluate the same way elsewhere in the body.
Closes#886
Co-authored-by: Malek Mohamed Noureldean Elkssas <87043730+malekelkssas@users.noreply.github.com>
d.toJSON() now answers the toISOString() string for a valid date and
null for an invalid one, as a string | null value although the lib
types say string. Unannotated bindings, object and array literal
entries initialized by it keep the null, reads of such bindings stay
checked, and JSON.stringify serializes the null instead of narrowing
it to string.
Closes#935
Co-authored-by: phall <25888173+phall1@users.noreply.github.com>
A class instance that a type assertion widens to a union, such as
(concrete as A | B).value, still lowers as that class's instance. The
shared-property lowering now reads the field or calls the getter on the
known class instead of refusing the receiver for not being a tagged
union.
Closes#49
Co-authored-by: Patrick Wozniak <4481570+patlux@users.noreply.github.com>
Library exports and callbacks passed text only as a pointer and length.
profile_format 2 adds the cstring class, a NUL-terminated `const char *`
(an i32 pointer in Wasm reactors), for export parameters, export results
and callback parameters. Parameters are copied in and decoded as UTF-8,
with U+FFFD for malformed bytes; a NULL pointer is the SC4012
host-contract trap. Results live in the result arena like string
results. A result or callback argument containing U+0000 traps instead
of being truncated.
Closes#615
Co-authored-by: ailuoku6 <23209876+ailuoku6@users.noreply.github.com>
An untyped JavaScript `let` initialized with an object literal took the
initializer's record shape. A later assignment of an object literal with
more properties (`state = { _tag: "PullLeft", right }`, as in Effect's
Stream.zip) stored the object, but reading the added property failed with
SC1090. Such a binding now uses checked-dynamic storage, as it already does
when the program adds a property through the binding, so the added
properties read back and missing ones read as undefined, as in Node.
Closes#937
Co-authored-by: phall <25888173+phall1@users.noreply.github.com>