Commit graph

66 commits

Author SHA1 Message Date
Undefine
7bccd65b4a LibWasm: Make sure try_table creates a new frame while validating
The spec says that while validating this opcode a new label should
be pushed.

Fixes a crash in instance.wast on WPT.
2025-10-19 17:28:11 +02:00
Undefine
07c86542b6 LibWasm: Properly read and validate limits for I64 memories and tables
Since memory64 got merged into the spec the minimum value for limits
is now actualy 64-bit and the maximum sizes for memories and tables
for I64 address types were increased.

Fixes 5 tests in memory64.wast nad 8 tests in table64.wast on WPT.
2025-10-19 17:28:11 +02:00
Undefine
692195ae88 LibWasm: Cast to long double before checking if trunactions is in range
I found that this fixes some precision issues while comparing to values
on the edge of the limits.

Fixes 6 tests in conversions.wast on WPT.
2025-10-19 17:28:11 +02:00
Ali Mohammad Pur
92c0cbc453 LibWasm+LibWeb: Stub wasm-gc's heap reference types
WPT inserts these into all modules regardless of whether they're used,
so let's just parse and ignore them.
2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
d99f663b1a LibWasm: Implement parsing/validation for proposal exception-handling
Actual execution traps for now.
2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
8138c2f48b LibWasm: Follow the updated spec on instantiation
The spec now permits access to all globals for all segment initializers,
as well as previously-defined globals for the global initializers.
2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
ddb35dcb5f LibWasm: Accept proposal 'memory64' (but don't actually run it)
This is a WIP implementation.
2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
d6f3f5fd51 LibWasm: Implement proposal 'relaxed-simd' 2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
77237af33f LibWasm: Add support for proposal 'extended-const' 2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
6a6f747701 LibWasm: Add support for proposal 'tail-call' 2025-10-15 01:26:29 +02:00
Ali Mohammad Pur
9ceb8052c8 LibWasm: Avoid revalidating memory/address for every element in memory.*
This also "fixes" the "address leak" detected by GCC (which is not
actually leaked to the tailcalled function).
2025-10-06 16:00:02 +02:00
Ali Mohammad Pur
31da9ab4e8 LibWasm: Take memory_fill arguments in the right order
This makes ruffle.rs work again :^)
2025-10-04 11:17:08 +02:00
Ali Mohammad Pur
353febfab6 LibWasm: Remove confusing newline after a few TAILCALLs 2025-10-04 11:17:08 +02:00
Ali Mohammad Pur
2397ae4af5 LibWasm: Use [[gnu::musttail]] on new-enough GCC versions
This is supported starting GCC 15.
The warning -Wmaybe-musttail-local-addr complained about &value possibly
escaping (it cannot, but gcc is being pessimistic about
store_to_memory), so a little rearrangement of that function was
necessary.
2025-10-01 23:47:29 +02:00
Ali Mohammad Pur
02b3c4f8a9 LibWasm: Utilise direct threading if/when possible
~50% performance improvement on coremark.
2025-10-01 23:47:29 +02:00
Ali Mohammad Pur
cf30d61d8b LibWasm: Use a faster way to detect live registers
Instead of doing a naive O(n^2) liveness detection loop, use a bitmap
for values allocated to registers.
This cuts down validating time from 20% to 1.4% of runtime on the same
game as last commit.
2025-10-01 23:47:29 +02:00
Ali Mohammad Pur
c0223befe1 LibWasm: Avoid frequent re/deallocations while validating expressions
Freeing and reallocating these vectors was ~6% of runtime when
validating some web-based game.
2025-10-01 23:47:29 +02:00
Jelle Raaijmakers
c31eff6a47 Everywhere: Use Optional<T>::ensure() where useful
No functional changes.
2025-09-17 12:01:18 -04:00
Rocco Corsi
55d4adc614 LibWasm: Missing argument formatter (Wasm::Value) for WASI_DEBUG
Formatting code was removed in PR #960 for performance improvements.
Adding Wasi::Value back as u128 to allow WASI_DEBUG MACRO compilation
2025-09-16 22:13:23 +02:00
Nico Weber
9272df7a86 Everywhere: Fix a few unreachable-return / unreachable-break warnings
I was playing with clang's -Wunreachable-code-aggressive a bit.
This fixes a handful uncontroversial things it flags.

No behavior change.
2025-09-12 14:33:14 +01:00
Pavel Shliak
a125bc97c4 LibWasm: Fix memory.fill ignoring memory index and unsafe bounds check
Previously, the memory.fill instruction always wrote to memory 0,
ignoring the selected memory index. This caused incorrect behavior
in multi-memory modules (e.g. filling mem0 instead of mem1).
Additionally, the bounds check used `destination_offset + count`
without overflow checking, which could wrap and bypass validation.

This patch:
- Passes `args.memory_index` into store_to_memory, so the correct
  memory is filled.
- Uses Checked<u32> for destination_offset + count, consistent
  with memory.copy and memory.init, to prevent overflow.

Minimal repro:

    (module
      (memory $m0 1)
      (memory $m1 1)

      (func (export "go") (result i32)
        ;; Fill mem1[0] with 0xAA
        i32.const 0
        i32.const 170
        i32.const 1
        memory.fill (memory 1)

        ;; Return (mem1[0] << 8) | mem0[0]
        i32.const 0
        i32.load8_u (memory 1)
        i32.const 8
        i32.shl
        i32.const 0
        i32.load8_u (memory 0)
        i32.or
      )
    )

Before fix: returns 170 (0x00AA).
After fix:  returns 43520 (0xAA00).
2025-09-06 08:51:11 +02:00
Pavel Shliak
9e11fa0ac6 LibWasm: Close byte list for active data segments in WAT output
LibWasm/Printer no longer leaves
the byte list in active data segments unclosed
2025-09-06 06:21:03 +02:00
Pavel Shliak
c53d9d7122 LibWasm: Use 0x40 flag for SIMD memory memidx like scalar ops
SIMD loads/stores checked bit 0x20 of the align immediate to detect a
following memory index, unlike scalar mem ops which use 0x40 per the
multi-memory encoding. This caused the memidx byte to be misparsed as
the next immediate (e.g. offset).

Update both SIMD sites (v128 load/store and lane variants) to check and
clear 0x40, then read LEB128<u32> memidx.

Repro:
  (module (memory $m0 1) (memory $m1 1)
    (func (export "go")
      i32.const 0
      v128.load (memory 1)
      drop))
Before: printed memidx 0 with offset 1.
After:  prints memidx 1 with offset 0.
2025-09-06 06:19:40 +02:00
Pavel Shliak
cdab6b0a2f LibWasm: Fix pushes for i16x8.replace_lane in Opcode table
The opcode entry declared i16x8_replace_lane with pushes = -1, but
replace_lane pops 2 (vector, lane value) and pushes 1 result vector.
Set pushes to 1 to match the other replace_lane opcodes.
2025-09-06 06:06:44 +02:00
Pavel Shliak
5f4ad17f89 LibWasm: Fix Negate::name() to return "neg"
Negate was incorrectly returning "== 0", a copy/paste from EqualsZero.
This patch corrects it to return "neg", matching the operator's actual
semantics and WebAssembly mnemonics (f32.neg, f64.neg).
2025-09-06 01:06:58 +02:00
Ali Mohammad Pur
4462348916 Everywhere: Slap some [[clang::lifetimebound]] where appropriate
This first pass only applies to the following two cases:
- Public functions returning a view type into an object they own
- Public ctors storing a view type

This catches a grand total of one (1) issue, which is fixed in
the previous commit.
2025-09-01 11:11:38 +02:00
Ali Mohammad Pur
22448b0c35 LibWasm: Move the interpreter IP out of the configuration object
This, along with moving the sources and destination out of the config
object, makes it so we don't have to double-deref to get to them on each
instruction, leading to a ~15% perf improvement on dispatch.
2025-08-26 15:20:33 +02:00
Ali Mohammad Pur
d8ea9e67f8 LibWasm: Access registers directly without bounds checks
The register array is guaranteed to be large enough for all registers
used in the program, so get rid of the bounds checks.
2025-08-26 15:20:33 +02:00
Ali Mohammad Pur
f7bdc596b4 LibWasm: Avoid allocations for the label stack as much as possible
Namely, find an upper bound at validation time so we can allocate the
space when entering the frame.

Also drop labels at once instead of popping them off one at a time now
that we're using a Vector.
2025-08-26 15:20:33 +02:00
Ali Mohammad Pur
6732e1cdc3 LibWasm: Don't clobber registers on (most) calls
This still passes the values on the stack, but registers are now allowed
to cross a call boundary.
This is a very significant (>50%) improvement on the small call
microbenchmarks on my machine.
2025-08-26 15:20:33 +02:00
ayeteadoe
a95e0d2777 Utilities/wasm: Enable on Windows 2025-08-24 12:58:27 -06:00
ayeteadoe
070392307a LibWasm: Enable EXPLICIT_SYMBOL_EXPORT 2025-08-24 12:58:27 -06:00
Luke Wilde
12dc771186 CI: Create wasm artifact and use it in the js-benchmarks workflow 2025-08-14 10:02:35 +02:00
ayeteadoe
78a08bac82 LibWasm: Fix Windows build 2025-08-09 16:41:37 -06:00
Ali Mohammad Pur
8af095f797 LibWasm: Make Wasm::Validator::Stack hold a Vector instead of inheriting 2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
b97ad99014 LibWasm: Remove unnecessary C-style casts
Or replace them with static-cast when necessary.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
33cd5ae08c LibWasm: Fuse some very common instruction combos into specialised ops
Largely combinations of i32.const and local.get.
This shaves off at most single-digit% number of instructions from
dispatch, which translates to at most ~10% reduced dispatch time.

Across most benchmarks, this gains around ~5% perf increase.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
0e5ecef848 LibWasm: Try really hard to avoid touching the value stack
This commit adds a register allocator, with 8 available "register"
slots.
In testing with various random blobs, this moves anywhere from 30% to
74% of value accesses into predefined slots, and is about a ~20% perf
increase end-to-end.

To actually make this usable, a few structural changes were also made:
- we no longer do one instruction per interpret call
- trapping is an (unlikely) exit condition
- the label and frame stacks are replaced with linked lists with a huge
  node cache size, as we only need to touch the last element and
  push/pop is very frequent.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
998454028c LibWasm+wasm: Remove the debug interpreter
This is largely unused (only in wasm.cpp)
A future reimplementation can bring it back as a separate interpreter
class that embeds the current bytecode interpreter.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
931b554f68 LibWasm: Give some inline capacity to the frame and label stacks
The average wasm function rarely goes over these bounds for the labels
(32 nested control structures), and 8 frames is just enough to clear
most initialization code/start section without allocating anything.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
dc67f0ad4e LibWasm: Hold on to the stack depth for expressions in the validator
This allows preallocating the value stack when pushing frames, avoiding
repeated reallocs and copies.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
3f77aa8521 LibWasm: Try to avoid vcalls on very busy stream read functions
This was a bottleneck when parsing, in general.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
bd7c188b86 LibWasm: Avoid memory copy in read_value<T>() if possible
If the address is already aligned properly, just read a T from it;
otherwise copy it to a local aligned array. This was a bottleneck on
memory-heavy benchmarks.
2025-08-08 12:54:06 +02:00
Ali Mohammad Pur
5c6f223f48 LibWasm: Avoid repeated shrinkage of value stack 2025-08-08 12:54:06 +02:00
Jelle Raaijmakers
ed94381209 LibWasm: Return canonical NaN for min/max/floor/ceil/truncate operations
Instead of returning whichever argument was NaN, return the canonical
NaN instead. The spec allows the old behavior:

  "Following the recommendation that operators propagate NaN payloads
   from their operands is permitted but not required."

But Chrome, Firefox and Safari do not propagate the operand payloads.

Fixes 448 WPT subtests in `wasm/core`.

Co-authored-by: Ali Mohammad Pur <ali.mpfard@gmail.com>
2025-07-27 15:35:28 +02:00
Jelle Raaijmakers
58c3a391a3 LibWeb+LibWasm: Reject module instantiation with correct error type
The spec tells us to reject the promise with a RuntimeError instead of a
LinkError whenever the module's start function fails during module
instantiation. Fixes 1 WPT subtest in `wasm/core`.
2025-07-25 15:13:28 +02:00
ayeteadoe
25f5936dee CMake: Rename serenity_* helper functions/macros to ladybird_* 2025-07-03 23:19:41 +02:00
Timothy Flynn
9fc3e72db2 AK+Everywhere: Allow lonely UTF-16 surrogates by default
By definition, the web allows lonely surrogates by default. Let's have
our string APIs reflect this, so we don't have to pass an allow option
all over the place.
2025-07-03 09:51:56 -04:00
Viktor Szépe
19f88f96dc Everywhere: Fix typos - act III 2025-06-16 14:20:48 +01:00
Ali Mohammad Pur
83995ada1f LibWasm: Quit early in memory_fill if store_to_memory traps
We shouldn't try to run the next 'instruction' if we trap.
Unbreaks the memory-fill test in wpt.
2025-05-22 07:35:58 +01:00