Commit graph

34 commits

Author SHA1 Message Date
Pavel Shliak
a125bc97c4 LibWasm: Fix memory.fill ignoring memory index and unsafe bounds check
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
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
5f4ad17f89 LibWasm: Fix Negate::name() to return "neg"
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
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
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
ayeteadoe
78a08bac82 LibWasm: Fix Windows build
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
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
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
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
Ali Mohammad Pur
bfc1ebb2d4 LibWasm: Disable spammy 'memory access oob' debug prints 2025-05-22 07:35:58 +01:00
Ali Mohammad Pur
d79d5b70a5 LibWasm: Validate indirect calls at runtime
This is required by the spec, and also unbreaks all of the call-indirect
wpt tests.
2025-05-22 07:35:58 +01:00
Ali Mohammad Pur
39b637a446 LibWasm+LibWeb: Throw a js stack-overflow error if wasm stack overflows
Follows the spec.
2025-05-22 07:35:58 +01:00
Tim Ledbetter
58ffc56c38 LibWas: Unbreak compilation with WASM_TRACE_DEBUG enabled
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
2025-05-19 10:20:40 +01:00
Timothy Flynn
7280ed6312 Meta: Enforce newlines around namespaces
This has come up several times during code review, so let's just enforce
it using a new clang-format 20 option.
2025-05-14 02:01:59 -06:00
Ali Mohammad Pur
292688e249 LibWasm: Validate tables, memories, globals, elements and data correctly
These sections are supposed to be validated with only the imported
globals.
2025-05-08 03:35:11 -06:00
Ali Mohammad Pur
51bab5b186 LibWasm: Make traps hold on to externally-managed data
...instead of specially handling JS::Completion.
This makes it possible for LibWeb/LibJS to have full control over how
these things are made, stored, and visited (whenever).

Fixes an issue where we couldn't roundtrip a JS exception through Wasm.
2025-04-22 08:43:46 -06:00
Andrew Kaster
16e764ddb6 LibWasm: Store function references' source module in RefPtr to const 2025-04-16 10:41:44 -06:00
Andreas Kling
de424d6879 LibJS: Make Completion.[[Value]] non-optional
Instead, just use js_undefined() whenever the [[Value]] field is unused.
This avoids a whole bunch of presence checks.
2025-04-05 11:20:26 +02:00
stasoid
44ddc4fc28 LibWasm: Port to Windows 2025-02-11 23:11:13 -07:00
Pavel Shliak
e08f6a69b2 LibWasm: Respect instance.types() bounds 2024-12-09 12:30:41 +01:00
Pavel Shliak
35764db0b7 LibWasm: Clean up #include directives
This change aims to improve the speed of incremental builds.
2024-11-21 14:08:33 +01:00
Timothy Flynn
93712b24bf Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00