Commit graph

13 commits

Author SHA1 Message Date
Andreas Kling
01df2663af LibJS: Test mapped bytecode cache installation
Cover installing bytecode cache blobs into live scripts and modules,
including stable shared-function-data identity, lazy function cleanup,
template object cache preservation, and top-level-await module
executable replacement.
2026-05-22 10:54:44 +02:00
Andreas Kling
a6e69d9518 LibJS: Lazily map UTF-8 source offsets
Avoid repeatedly decoding an entire byte-backed UTF-8 source when a
cached function asks for its source text and the script contains a
non-ASCII code point before the requested range.

Build a small map from UTF-16 code unit offsets to byte offsets on
demand for valid UTF-8 sources, then slice the source bytes directly for
subsequent extractions. Invalid or non-UTF-8 sources keep using the
existing decoder fallback.

Add coverage for lazy range extraction after non-ASCII UTF-8 and for
bytecode-cache materialization of function source text from such a
script.
2026-05-19 17:58:08 +02:00
Andreas Kling
7c19719946 LibJS: Avoid repeated lazy source decoding
Function.prototype.toString() can ask for the same cached function
source text repeatedly after a script was materialized from the
bytecode cache. In that path SourceCode still owns only the encoded
source bytes, so every request decoded the requested source range
again. Large ASCII bundles made that path expensive enough to stall
Speedometer 2.1's Ember debug test.

Keep the byte-backed SourceCode representation lazy, but let ASCII
UTF-8 source ranges slice the source bytes directly. For other ASCII
byte-backed encodings, first ask the decoder to prove that the source
bytes map to the same UTF-16 code units at the same positions.

Cache extracted function source text on shared function data after the
first request so repeated toString() calls do not keep going back to
SourceCode.

Add bytecode cache coverage for toString() on lazy UTF-8 source bytes,
keep malformed UTF-8 and UTF-16 edge cases on the decoder path, and
cover PDFDocEncoding bytes that are not identity-mapped.
2026-05-19 17:58:08 +02:00
Andreas Kling
948afeb7ee LibJS: Reuse cached constant buffers when materializing
Validate cached constant buffers without decoding them into Rust
ConstantValue objects, then pass the bytes to the C++ executable
factory. Align string constants in the FFI encoding so fresh and cached
buffers use the same layout.
2026-05-19 11:32:50 +02:00
Andreas Kling
ef74c1ca55 LibJS: Keep cached bytecode file-backed
Teach Bytecode::Executable to store its instruction stream as either
an owned Vector or a retained Core::ImmutableBytes range. Cached
bytecode materialization now clones the immutable blob owner and lets
the executable point directly into the file-backed cache blob instead
of copying instruction bytes back onto the heap.

Keep a cached instruction data pointer inside the stream wrapper so the
asm interpreter still has a direct hot-path load. Align executable
bytecode payloads in the cache format so mmap-backed instruction
streams satisfy validator and interpreter alignment requirements.
2026-05-18 20:35:14 +02:00
Andreas Kling
45da0e4a0e LibTextCodec: Preserve malformed decoder replacements
Reject UTF-8 second bytes outside the Encoding Standard's per-lead-byte
bounds before consuming the rest of each sequence. This keeps surrogate
and out-of-range sequences from collapsing multiple malformed bytes into
one replacement character.

Also report an odd trailing UTF-16 byte as U+FFFD through the streaming
code point path and route UTF-16 to_utf8() through the same logic. This
keeps lazy and eager script decoding aligned for bytecode cache source
hashes.

Cover the malformed UTF-8 and UTF-16 cases in LibTextCodec, TextDecoder,
and bytecode-cache source decoding tests.
2026-05-18 14:08:22 +02:00
Andreas Kling
5627e89956 LibTextCodec: Preserve UTF-8 replacement decoding
Decode malformed UTF-8 consistently in UTF8Decoder::process() and
UTF8Decoder::to_utf8(). This keeps lazy SourceCode decoding and bytecode
cache source hashing in step with eager source text decoding when cached
script source bytes contain invalid UTF-8.

Cover UTF-8 encoded surrogate code points and overlong byte sequences in
LibTextCodec, and add lazy SourceCode coverage for both cases.
2026-05-18 09:18:35 +02:00
Andreas Kling
30314e8ad0 LibJS: Lazily decode cached function bytecode
Store nested function executables in the bytecode cache as
length-prefixed payloads, and keep those payloads mapped instead of
decoding every function when materializing the outer script or module.
Decode and validate a cached function executable only when that
function is installed for lazy materialization.

Validate cached executable bytecode before storing it on shared data,
and recurse source range validation through the lazy executable
payload. This keeps corrupt cache entries on the recoverable
materialization path instead of crashing when a function is first used.

This avoids turning the warm disk cache into retained dirty heap for
all uncalled nested functions on large sites.
2026-05-17 08:58:45 +02:00
Andreas Kling
1ad3039001 LibJS: Align bytecode cache UTF-16 payloads
Bump the bytecode cache format and pad serialized UTF-16 strings to u16
alignment. This lets mapped cache blobs expose decoded UTF-16 payloads
as FFI slices directly instead of re-decoding them into temporary
aligned buffers during materialization.

Update the bytecode cache corruption helpers to skip the new string
padding when walking serialized blobs.
2026-05-16 08:13:35 +02:00
Andreas Kling
a646f9d0bf LibJS: Borrow mapped bytecode cache executable bytes
Keep executable bytecode payloads decoded from owner-backed bytecode
cache blobs as ranges into the original blob instead of copying them
into Rust Vec allocations. The mapped blob owner is held by decoded
executable records, including lazy nested function executables, so the
borrowed bytecode remains alive until materialization copies it into the
final C++ Executable.

Use the owner-backed decoder for HTTP bytecode cache hits and keep the
plain byte decoder for tests and in-memory callers. Add coverage for
materializing bytecode cache data from an ImmutableBytes mapped file.
2026-05-16 08:13:35 +02:00
Andreas Kling
e926e86f8d LibJS: Materialize compiled function bytecode lazily
Keep fully compiled function bytecode in its Rust-side form until the
function is called for the first time. This covers decoded disk cache
records and freshly precompiled bytecode, so startup avoids eagerly
allocating every nested function executable.

Validate cached function bytecode before accepting a cache entry. This
keeps the existing failure behavior for corrupt on-disk cache data. Add
coverage for bytecode-cache and freshly precompiled functions to assert
that nested executables stay absent after script materialization, then
appear after the function is called.
2026-05-14 08:15:01 +02:00
Andreas Kling
4ef3c076f9 LibJS: Preserve imported names in module bytecode cache
Store the original imported binding name when serializing a re-export of
an imported binding as an indirect export. The cache previously kept the
local alias, so materialized modules could fail to resolve valid exports
such as `export { renamed as default }`.

Bump the bytecode cache format version so existing blobs with the stale
metadata are ignored. Add coverage for both normal module loading and
materializing this pattern from bytecode cache.
2026-05-13 20:54:10 +02:00
Andreas Kling
afa1f77252 LibJS: Materialize decoded bytecode cache blobs
Create parser-free script and module materializers for decoded cache
blobs. Cached functions create SFDs without Rust compile inputs and
attach their precompiled executable immediately, while declaration
metadata is populated from decoded records.

Treat cache blobs as external input from the HTTP disk cache. Run
bytecode validation unconditionally before fixing up cache pointers, and
reject decoded source ranges or metadata indices that would be
out-of-bounds during C++ materialization.

Report executable validation failures as parser errors so callers can
reject corrupt sidecars and fall back to source compilation. LibJS tests
cover corrupt top-level bytecode, declaration bytecode, and declaration
source spans.
2026-05-06 08:20:06 +02:00