Commit graph

129 commits

Author SHA1 Message Date
Ali Mohammad Pur
b3f3d68291 LibWeb+LibWasm: Keep WebAssembly cache storage stable
These need to stay in place across rehashes so we can avoid querying
their address on every collection cycle.
2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
530c95fde5 LibWasm: Remove all gc, function-refs and EH test exceptions 2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
8a74f52571 LibWasm: Partially implement the (new) exception handling proposal
This implements try_table and throw_ref execution in the interpreter.
2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
16d1486cc9 LibWasm: Implement the wasm-gc instruction set in the BC interpreter 2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
87961e3c92 LibWasm: Back wasm-gc aggregate instances with the LibGC heap 2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
62cb073ada LibWasm: Validate the wasm-gc and function-references instructions
Actual implementations are still trap-on-exec.
2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
42c0a430f5 LibWasm: Implement the spec's type matching relations 2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
3ca552b37b LibWasm: Parse wasm-gc types
No more unsupported heap refs.
2026-06-19 17:01:47 +02:00
Ali Mohammad Pur
340d87efd6 LibWasm: Catch SIGFPE on jitted code too
SIGFPE can happen if we emit a bare idiv.
2026-06-15 16:09:51 +02:00
Andreas Kling
8a8625b399 LibWasm: Require virtual storage for wasm32 memory
Reserve the wasm32 virtual address space when creating an i32 memory.
Crash if the reservation fails instead of using ByteBuffer storage.

This keeps wasm32 memory on the virtual path used for fault recovery.
2026-06-10 17:34:16 +02:00
Ali Mohammad Pur
34fd6d87f4 LibWasm: Delete Frame's move operator=
This is not used and is a footgun anyway.
2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
c414f31ecf LibWasm: Correctly handle memory64's addr types in the interpreter 2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
f81717d4c8 LibWasm: Allow allocating max-size wasm32 memories
We used to disallow allocating 65536 pages, but that's fine as per spec.
2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
08221aebab LibWasm: Start execution immediately after validation
This adds a tier-up mechanism at loop edges, making it so we can
seamlessly (ish) transition between interpreted and native code so we
can start running wasm code immediately after validation while
compilation happens in the background, and switching to native code
eventually once we hit a big enough function that would benefit from
being compiled to begin with.
2026-06-05 00:08:11 +02:00
Ali Mohammad Pur
3c89c36158 LibWasm+LibWeb: Restore disk cache for compiled wasm modules
Also untangle the confusing validation layering on async compilation.
2026-06-05 00:08:11 +02:00
Andreas Kling
164ed80244 Meta: Enable exit-time destructor warnings for libraries
Enable -Wexit-time-destructors for all in-tree library targets and
update process-lifetime library statics so they no longer register
exit-time destructors. Long-lived caches, lookup tables, singleton
registries, and generated constants now use NeverDestroyed or leaked
references where the data is intended to live until process exit.

Update LibWeb, LibLine, and the binding generators so regenerated
sources follow the same rule instead of reintroducing destructed
statics.
2026-06-04 19:20:49 +02:00
François Guerraz
be4173af81 LibWasm: Validate a tag's type index before dereferencing it
The throw and try_table validators looked up the tag referenced by the
instruction, then indexed m_context.types with the tag's type index
without checking it was in range. validate(TagIndex) only validates the
tag index itself, and the tag section is validated after the code
section, so a module whose tag carries an out-of-range type index
reached the unchecked m_context.types[...] access and tripped a Vector
bounds assertion during validation.

Any WebAssembly.compile() of such a module aborts the WebContent
process.

Validate the tag's type index before using it, the same check
validate(TagType) already performs.
2026-06-04 13:54:58 +02:00
Ali Mohammad Pur
841572f358 LibWeb+LibWasm: Don't wait for JIT-compilation of wasm modules
Return from the jsapi calls when we have a module that satisfies the
state required by the spec, and let jit compilation (if it's happening)
continue in the background.
This also means we no longer do the full compilation pipeline for
validate().
2026-06-03 11:51:43 +02:00
Ali Mohammad Pur
5c1d2004b7 LibWasm: Handle traps emitted from cranelift 2026-06-03 11:51:43 +02:00
Ali Mohammad Pur
68f6c03a67 LibWasm: Correctly handle failed validation 2026-06-03 11:51:43 +02:00
Ali Mohammad Pur
01db906039 LibWasm: Disable direct threading on ASAN builds
ASAN changes tailcall semantics that break the code.
2026-05-31 20:26:22 +02:00
Ali Mohammad Pur
402e151b62 LibWasm: Move the "rest" of br_if.nostack into a separate function
...instead of a lambda, so gcc doesn't have to deal with annotations on
lambdas.
2026-05-28 10:34:26 +02:00
Ali Mohammad Pur
f54ad4ca25 LibWasm: Only build the compiled function table once per module 2026-05-27 09:52:34 +02:00
Ali Mohammad Pur
842e8a6796 LibWasm+LibWeb: Add per-module wasm compile stats 2026-05-27 09:52:34 +02:00
Ali Mohammad Pur
2419cce8d8 LibWasm+LibWeb: Serialize and save compiled wasm as a cache blob 2026-05-27 09:52:34 +02:00
Ali Mohammad Pur
f31519c393 LibWasm: Add runtime checks to nostack br/br_if
synthetic_br_nostack and synthetic_br_if_nostack assumed the runtime
value stack already matches the target label's expected size. The
register allocator can leave more values on the stack than the
validator's abstract count predicted, so the bare nostack variants get
us out of sync and we crash later. This makes it so they drop to regular
br/br_if behaviour if they notice that the size is not as expected.
2026-05-27 09:52:34 +02:00
Ali Mohammad Pur
8e8a8f9270 LibWasm: Tighten the cranelift direct-call lookup paths
Switches the compiled function table from HashMap<u32, ...> to a Vector
indexed by function index. The keys are densely packed up to
functions.size() so the hash probe wasn't buying us anything.

Also drops the bounds check from MemoryInstance::unsafe_get to match
FunctionInstance::unsafe_get; the caller has already proved the address
is in range by the time we get here.
2026-05-27 09:52:34 +02:00
sideshowbarker
59eb221d7c LibWasm: Fix “return” leaking intermediate value-stack entries to caller
Problem: Loading WebAssembly modules that use “return” mid-function can
corrupt the heap and crash the browser.

Cause: HANDLE_INSTRUCTION(return_) shrank the label stack but left any
working values pushed before the “return” instruction on the shared
value stack. Those residuals leaked into the caller’s frame and
accumulated across calls — until they overflowed the value stack’s
inline storage and corrupted adjacent allocator metadata.

Fix: After shrinking the label stack down to the function-level label,
also remove value-stack entries between that label’s recorded
stack_height and the top .arity() result values — mirroring the cleanup
that branch_to_label<true> already performs for br/br_if.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9614
2026-05-25 09:00:44 +02:00
Andreas Kling
f374e72c54 LibWasm: Store try_table catches out of line
TryTableArgs only needs catches for try_table instructions. Reuse the
structured-instruction layout with catch storage in place of the else
target, and keep the catch elements in a FixedArray.

This avoids storing a full Vector inline in every Instruction variant
alternative and keeps the catch storage copyable for the variant.
2026-05-14 12:19:38 +02:00
Andreas Kling
571bbba042 LibWasm: Use chunked synthetic instruction storage
Keep synthetic instruction pointers stable by storing them in fixed
chunks instead of one large Vector. This removes the old oversized
reserve. Expressions without synthetic instructions now avoid extra
instruction storage entirely.
2026-05-14 12:19:38 +02:00
Andreas Kling
8775f48436 LibWasm: Store structured metadata directly
Validation always fills structured instruction metadata before compiled
expressions are executed. Store the metadata directly instead of using
Optional, and update execution and printing paths accordingly.
2026-05-14 12:19:38 +02:00
Andreas Kling
f22dec54ef LibWasm: Store opcodes in 32 bits
Wasm opcodes only need one byte plus a 24-bit selector for
prefixed instructions. Store them in u32 instead of u64 and reject
selectors that would not fit. Update the Rust opcode generator to
accept the new integer suffixes used by Opcode.h.
2026-05-14 12:19:38 +02:00
Ali Mohammad Pur
9bda97a11b LibWasm: Avoid huge switches in all handlers' log functions
This explodes the debug info size, making the CI runner OOM when
building this file :)
2026-05-10 16:41:42 +02:00
Ali Mohammad Pur
a36f6abedb LibWasm+LibWeb: Properly track module lifetime with function refs 2026-05-10 16:41:42 +02:00
Ali Mohammad Pur
a33e148339 LibWasm+Meta: Add Cranelift AOT compilation backend
Add an optional Cranelift-based AOT compiler for WebAssembly functions,
enabled via -DENABLE_CRANELIFT_JIT=ON.
2026-05-10 16:41:42 +02:00
Ali Mohammad Pur
5ab2eaed8c LibWasm: Fix some signedness bugs
- memory.grow page count
- memory.copy offsets and underflow in copy op
- table_{set,get} index exec
2026-05-10 16:41:42 +02:00
Ali Mohammad Pur
f181d24dc0 LibWasm: Prepare for VM and direct function calls
Introduce MemoryBuffer, a memory backing store that uses mmap to reserve
the full wasm32 address space (4 GiB + guard pages) upfront, growing
without a copy and falling back to a ByteBuffer when mmap fails.
Also let Frame know how to handle non-owned locals (to e.g. allow
allocating them on the native stack.)
2026-05-10 16:41:42 +02:00
Andreas Kling
eb789e790e Everywhere: Use AK::SaturatingMath and remove Checked saturating APIs
Port all callers of Checked<T>::saturating_add/sub/mul to the new
standalone functions in AK/SaturatingMath.h, and remove the old
APIs from Checked.
2026-03-21 18:20:09 -05:00
Jelle Raaijmakers
bd9bc10eb2 LibWasm: Remove Vector size checks in (return_)call_indirect
These are followed by `Vector::operator==` which immediately compares
sizes as well.
2026-03-07 16:05:20 +01:00
Jelle Raaijmakers
fa1417114e LibWasm: Implement call_ref and return_call_ref instructions
These are part of the typed function references proposal, which is now
widely used by toolchains like wasm-bindgen. This makes sites like
wordsalad.online load in Ladybird.
2026-03-07 16:05:20 +01:00
Jelle Raaijmakers
f764b881bc LibWasm: Add reference type subtyping to the validator
The typed function references proposal requires subtype checking: e.g.
(ref $t) is a subtype of (ref func), and a non-nullable reference is a
subtype of its nullable counterpart. This is needed for correct
validation of `call_ref` and `return_call_ref`.
2026-03-07 16:05:20 +01:00
Jelle Raaijmakers
f78fa73a48 LibWasm: Remove unused current_module field 2026-03-07 16:05:20 +01:00
Ali Mohammad Pur
0e7fb1386e LibWasm: Use the right indices for i64 constlocal fused ops
Also aligns the i32 ones to use the same detection logic as the i64
cases.
2026-02-23 00:22:47 +01:00
Marcus Nilsson
21c827e8af LibWasm: Parse and validate array types
This patch makes this parse
```wat
(module
  (type $a (array i32))
)
```
2026-02-10 13:00:16 +01:00
Marcus Nilsson
27a66c33c5 LibWasm: Validate struct types and type section
Spec tests struct.{3,4} are enabled again as they are now correctly
validated.
2026-02-10 13:00:16 +01:00
Marcus Nilsson
5fa9747105 LibWasm: Parse and validate typeuse references
This adds parsing of `(ref typeidx)` and validates that `typeidx` is a
valid index. Currently, nullability of the reference is lost.

A bug causing the code below to fail parsing has been fixed.
```wat
(module
  (type $T (struct (field i32) (field f32)))
  (type $T1 (struct (field i32) (field f32)))
  (; many more types... ;)
  (type $T64 (struct (field i32) (field f32)))
  (type $f (func (result (ref null $T64))))
)
```

The spec tests type-equivalence.{0,1,3,13} have been disabled as they
were previously false positives.
2026-02-10 13:00:16 +01:00
Rocco Corsi
d2ddf5d91d LibWasm: Disable direct threading on debug+gcc15
In preperation for Ubuntu 26.04 LTS, which will most likely come default
with GNU GCC 15.2.0 (but should have versions 14 and 16 available),
found that musttail/tail-call optimization fails for non-release builds.

Testing done on Ubuntu 25.10 which has GNU GCC 15.2.0 as default,
checking: Release, Debug, All_Debug, Sanitizer, and Distribution.

Fixes: #6745
2026-02-10 01:58:40 +01:00
Marcus Nilsson
bfa51c2555 LibWasm: Parse struct types and support multiple types in type section
This patch adds support for parsing structs in the type section.

It also removes the assumption that all types in the type section are
function types, adding appropriate validation.

Spec tests struct.3 and struct.4 have been disable as this would
require expanding `ValueType` to include more heap-types.
2026-02-04 14:29:22 +01:00
Ali Mohammad Pur
0dc39e9bfd LibWasm: Use the source_value() mechanism in binary_numeric_operation
This avoids a bunch of extra stack ops and some unnecessary loads for
registers.
2026-02-02 14:11:49 +01:00
Ali Mohammad Pur
9964c64446 LibWasm: Implement the i32 const/local fusions for i64 too 2026-02-02 14:11:49 +01:00