Commit graph

15 commits

Author SHA1 Message Date
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
a31c2c388b LibJS: Stop persisting basic_block_start_offsets on Executable
Keep basic block offsets as construction-only metadata rather than
storing them on every Executable. The validator now receives the offsets
through a transient Rust FFI span, and the bytecode dump rebuilds block
starts by scanning labels, terminators, and exception handler metadata.

Drop the table from the bytecode cache format and bump the format
version so old caches are rebuilt. This removes a field that was only
used by validation and bytecode dump paths.
2026-05-14 12:08:12 +02:00
Andreas Kling
21cbfb3cb1 LibJS: Drop source ranges from bytecode source maps
Store source map locations as bytecode offset, line, and column.
Runtime consumers only emit the start line and column, so source end
positions and source text offsets do not need to be carried through
Executable source maps, bytecode cache serialization, or the Rust FFI.

Keep SourceCode's internal position cache able to track source text
offsets so callers can still translate source offsets to line and
column pairs when needed. Hash dump-bytecode IDs from the name, first
source position, and bytecode size instead of source slices that need
end offsets.

Bump the bytecode cache format version for the slimmer serialized
source map entry shape.
2026-05-14 09:41:03 +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
Andreas Kling
b265694f0d LibJS: Match bytecode cache blobs to their source
Store a SHA-256 fingerprint of the decoded source text in each bytecode
cache blob, and require callers to provide the expected fingerprint when
validating or decoding a blob.

This rejects sidecars for stale HTTP cache entries whose URL and request
headers still match but whose source body has been replaced. Bytecode
cache tests cover the mismatched-source rejection path.
2026-05-06 08:20:06 +02:00
Andreas Kling
de9f2b8343 LibJS: Decode bytecode cache blobs over FFI
Expose an owned decoded bytecode cache handle through RustIntegration.
This lets C++ callers keep validated metadata and executable records in
Rust-owned cache structures without invoking the parser.

Extend the js bytecode cache validation mode to create and free the FFI
handle so blob generation exercises the ownership path.
2026-05-06 08:20:06 +02:00
Andreas Kling
fb11f81305 LibJS: Cache declaration function bytecode
Precompile top-level function declarations used during script and
module instantiation while producing a full bytecode cache entry. Keep
normal off-thread execution artifacts on the existing eager path, and
store declaration records separately from executable nested functions.

Place those records after declaration metadata in the cache blob, and
bump the blob version so older sidecars are rejected.
2026-05-06 08:20:06 +02:00
Andreas Kling
9b33cd1c21 LibJS: Return decoded bytecode cache blobs
Make bytecode cache validation return a decoded blob containing the
validated program record, declaration metadata, and executable records.

This keeps a single Rust-owned object alive for consumers that need to
materialize cached bytecode after validation succeeds.
2026-05-06 08:20:06 +02:00
Andreas Kling
16f4775a99 LibJS: Decode bytecode cache executable records
Decode bytecode cache executable records into owned Rust data instead
of only skipping over their serialized fields during validation.

Keep cached bytecode, constants, nested functions, and class blueprints
available for later materialization without rebuilding ASTs.
2026-05-06 08:20:06 +02:00
Andreas Kling
4f1bf52eb3 LibJS: Persist bytecode cache declaration metadata
Store and decode script declaration-instantiation metadata and module
import, export, request, and declaration metadata in bytecode cache
blobs.

Return decoded metadata as owned Rust records so warm-cache script and
module construction can recover parser-derived facts from the sidecar.
2026-05-06 08:20:06 +02:00
Andreas Kling
c5b6739c47 LibJS: Tag bytecode cache blobs with program type
Record whether each bytecode cache blob contains a classic script or a
module, and pass that type through the serializer call sites.

Require validation callers to provide the expected program type so
script and module sidecars cannot be reused for the wrong loader.
2026-05-06 08:20:06 +02:00
Andreas Kling
b327f61ab3 LibJS: Validate bytecode cache blob records
Add structural validation for bytecode cache blobs using the serialized
record layout. The decoder shares primitive helpers across cache
sections instead of duplicating flat parsing logic.

Reject bad magic values, unsupported versions, invalid enum tags, and
truncated sections before materialization. Bound sequence reads against
the remaining blob so malformed sidecars cannot force large allocations.
2026-05-06 08:20:06 +02:00
Andreas Kling
96a6782800 LibJS: Serialize compiled bytecode cache blobs
Add a versioned Rust bytecode cache writer for fully compiled programs.
The blob records executable bytecode, metadata tables, source maps,
exception handlers, nested function bytecode, and class blueprints
without materializing GC objects.

Expose the serialized blob through RustIntegration as an owned
ByteBuffer so Web-facing callers can store it as HTTP cache data.
2026-05-06 08:20:06 +02:00