Produce JS-visible string results as UTF-16 at their source, including
numeric formatting, BigInt and BigFraction formatting, URI encoding,
console formatting, parser errors, regular expression errors, Intl and
Temporal records, LibUnicode locale boundaries, and LibWeb bindings.
Handle fractional radix formatting through the UTF-16 builder view.
Keep primitive string storage in Utf16String and remove the UTF-8
storage path from PrimitiveString. ASCII strings still use compact
Utf16String ASCII storage, while UTF-16 becomes the only owned
representation.
Short string concatenations are a common allocation churn pattern in JS
execution. Many of these results are immediately observed as flat
strings, so the intended win is to avoid spending GC and flattening work
on an intermediate representation that does not carry its weight.
Microbenchmark:
const n = 10_000_000;
function bench(a, b) {
let total = 0;
for (let i = 0; i < n; ++i)
total += (a + b).length;
if (total !== n * 2)
throw new Error(String(total));
}
bench("a", "b");
Measured with hyperfine against the same build with the fast path
disabled:
baseline: 822.7 ms +/- 25.7 ms
optimized: 385.5 ms +/- 21.5 ms
speedup: 2.13 +/- 0.14 times faster
Teach the PrimitiveString substring creation path to return the
VM's preallocated single-character ASCII strings instead of always
allocating a deferred Substring.
This keeps one-code-unit ASCII substrings on the same fast path as
direct string creation, including callers like charAt and indexed
string property access.
Return JS::Substring objects from the builtin regexp exec and split
paths instead of eagerly copying UTF-16 slices into new strings.
Matches, captures, and split pieces can now point back at the original
input until someone asks for the string contents.
Add focused runtime coverage for UTF-16 captures and regex split
captures so these lazy slices stay exercised.
Introduce JS::Substring as a lazily materialized PrimitiveString
variant that stores an originating string plus a UTF-16 offset and
length. This makes substring creation cheap while still reifying to
a normal string when character data is requested.
Track which short strings actually live in the VM caches so lazily
resolved ropes and substrings do not evict unrelated cached strings
when they are finalized. Add focused unit tests for nested ranges,
rope-backed substrings, surrogate boundaries, and cache behavior.