Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Merge with main#244

Merged
alexcrichton merged 40 commits intobytecodealliance:mainfrom
alexcrichton:merge
Aug 12, 2025
Merged

Merge with main#244
alexcrichton merged 40 commits intobytecodealliance:mainfrom
alexcrichton:merge

Conversation

@alexcrichton
Copy link
Copy Markdown
Member

For real this time

alexcrichton and others added 30 commits August 1, 2025 01:24
* Simplify WASI internal implementations

This commit migrates the WASIp2 implementation to be closer to the
upcoming WASIp3 implementation in terms of how things are implemented
internally. Previously the way things worked with WASIp2 is:

* Embedders call `add_to_linker` with `T: WasiView`
* Internally `add_to_linker` is called which creates `WasiImpl<&mut T>`
* All internal implementations were `impl<T> Host for WasiImpl<T> where T: WasiView`
* A forwarding impl of `impl<T: WasiView> WasiView for &mut T` was
  required

While this all worked it's a bit complicated for a few reasons:

1. Dealing with generically named structures like `WasiImpl` (or
   `IoImpl` or `WasiHttpImpl`) is a bit baroque and not always obvious
   as to what's going on.
2. The extra layer of generics in `impl<T> Host for WasiImpl<T>` adds a
   layer of conceptual indirection which is non-obvious.
3. Other WASI proposal implementations do not use this strategy and
   instead use "view" types or `impl Host for TheType` for example.
4. Internal incantations of `add_to_linker` had to deal with mixtures of
   `IoImpl` and `WasiImpl` and aligning everything just right.
5. An extra layer of generics on all impls meant that everything was
   generic meaning that `wasmtime-wasi`-the-crate didn't generate much
   code, causing longer codegen times for consumers.

The goal of this commit is to migrate towards the style of what WASIp3
is prototyping for how impls are modeled. This is done to increase the
amount of code that can be shared between WASIp2 and WASIp3. This has a
number of benefits such as being easier to understand and also being
more modular where `wasi:clocks` implementations of traits don't require
filesystem context to be present (as is the case today). This in theory
helps a more mix-and-match paradigm of blending together various bits
and pieces of `wasmtime-wasi` implementations.

Concretely the changes made here are:

* `WasiView` no longer inherits from `IoView`, they're unrelated traits
  now.
* `WasiView` now returns `WasiViewCtx<'a>` which has `ctx: &'a mut WasiCtx`
  and `table: &'a mut ResourceTable`. That means it basically does the
  same thing before but in a slightly different fashion.
* Implementations of `Host` traits are now directly for
  `WasiCtxView<'_>` and don't involve any generics at all. These are
  hopefully easier to understand and also better from a
  codegen/compile-time perspective.
* Embedders no longer need to implement `IoView` directly and instead
  fold that functionality into `WasiView`.
* `WasiHttpView` no longer inherits from `IoView` and instead has a
  direct `fn table` method. Additionally `WasiHttpImpl` no longer embeds
  `IoImpl` inside of it.
* Host traits for `wasi:io` are now implemented directly for
  `ResourceTable` instead of `IoImpl<T>`.

The immediate goal of this refactoring is to enable more sharing along
the lines of #11362. This was not possible prior because WASIp3 requires
a simultaneous borrow on the table/ctx while the trait hierarchy
previously gave you one-or-the-other. With this new organization it will
be possible to get both at the same time meaning more
structure/contexts/etc can be shared between implementations.

prtest:full

* CI fixes

* More CI fixes

* More CI fixes
* Share stdio implementations in WASIp{2,3}

This commit is a refactoring of the
`wasmtime_wasi::{cli,p2::stdio,p3::cli}` modules to share more code. The
generic trait object that represents stdio now has the ability to
acquire either a p2 stream or an async-based stream. The acquisition of
p2 has a default implementation so in the future this can be primarily
`Async{Read,Write}`-based.

Many trait implementations and types and such were all consolidated
together into the `wasmtime_wasi::cli` module. One-off implementations
in p2/p3 are now shared in one location and `WasiCtxBuilder` no longer
needs any generics for different stdio streams.

Functionally this necessitated the addition of `Async{Read,Write}`
implementations for some "base" implementations of stdio primitives.
Implementations were mostly trivial except for a few adapters which were
significantly more complicated, namely the `Async{Read,Write}Stream`
adapter which converts a single `Async{Read,Write}` into the stdio of a
component.

Finally the stdin implementation for p3 was refactored to avoid use of
`tokio::io::stdin()` which generally isn't safe to use. It's replaced
with a custom `AsyncRead` using the worker thread implementation we have
in the crate already.

Eventually I hope to remove the distinction between `p{2,3}::WasiCtx`
and have these be the same type. This will make it nicer to only have a
single `WasiView` trait and additionally make it easier to
simultaneously implement all of WASIp{1,2,3}.

* Fix build of C API

* Fix build of `wasmtime serve`
This commit updates to using the `trappable_error_type` in bindings
generated for WASIp3 to mirror what happens in WASIp2, removing an extra
`Result<Result<..>>` layer to only have one layer of results.
This removes `wasmtime_wasi::p{2,3}::{WasiCtx, WasiCtxBuilder,
WasiView}` in favor of only having `wasmtime_wasi::{WasiCtx,
WasiCtxBuilder, WasiView}` instead. Conceptually these revisions of WASI
all provide the same functionality just with a different veneer that the
component model offers, so having only one way to configure host-side
behavior will make it easier to both organize implementations internally
(e.g. more sharing of code) as well as for embedders to configure (only
one context to create/manage).
Co-authored-by: Wasmtime Publish <wasmtime-publish@users.noreply.github.com>
* Mirror WASIp{2,3} cli implementations

This is an implementation of #11362 but for the `wasi:cli`
implementation of WASIp2.

* Fix unused field without p3
This is an implementation of #11362 but for the `wasi:clocks`
implementation of WASIp2. The goal here is to have the impls be
implemented and look roughly the same across WASIp2 and WASIp3, namely
the target of the implementation of now `WasiClocksCtxView` instead of
`WasiCtxView`. This makes the trait implementations a bit more flexible
as it means embedders aren't required to, for example, provide a full
WASI context for clocks but just clock-related context.
This is an implementation of #11362 but for the `wasi:sockets`
implementation of WASIp2. This additionally internalizes much of the
WASIp3 implementation with `pub(crate)` to avoid unnecessarily exposing
implementation details of the crate.
* Rename "preview{0,1}" in `wasmtime-wasi` to "p{0,1}"

This commit renames the `preview1` module and features to `p1` and does
the same for `preview0`. This additionally cleans up the test suite a
bit to share more code amongst all the implementaitons and to also move
the p1 tests out of the p2 folder.

This additionally adds a `p2` feature to the `wasmtime-wasi` crate but
it does not currently gate the `p2` module because that'll require some
more refactoring an annotations to get that working.

* Fix build of the CLI

* Fix build of the C API

* Fix bench-api build

* Fix build of examples

* More renamings
* Use the same `UdpSocket` in WASIp{2,3}

This commit refactors the implementation of `wasi:sockets` for WASIp2
and WASIp3 to use the same underlying host data structure for the
`UdpSocket` resource in WIT. Previously each version of WASI had its own
socket which resulted in duplicated code. There's some minor differences
between WASIp2 and WASIp3 but it's easy enough to paper over with the
same socket type. This is intended to help with the maintainability of
this going forward to only have one type to operate on rather than two
(which also ensures that bugfixes for one should affect the other).

One other change made in this commit is that sprinkled checks for
whether or not UDP is allowed are all removed and canonicalized during
UDP socket creation. This means that UDP socket creation is the only
location that checks for whether UDP is allowed. Once a UDP socket is
created it can be used freely regardless of whether the UDP setting is
enabled or disabled. This is not intended to have a large practical
effect but it does mean the behavior of hosts that deny UDP but manually
give access to a UDP socket resource to a component may behave subtly
differently.

* Review comments

* Fix p3-less warnings

* Update UDP denial test

* Fix some clippy issues

* Fix no-udp test warnings
* asm: generate boolean terms of CPU features

As discussed [here], we will soon need the ability to express more
complex combinations of CPU features. These are best expressed as
boolean terms: e.g., `(32-bit OR 64-bit) AND ...`, `(32-bit OR 64-bit)
AND ((AVX512VL AND AVX512F) OR AVX10.1)`. This change modifies the
generated code to have a `Inst::is_available` method which contains a
Rust-ified version of the instruction's boolean term. To do this, we now
pass in a `Features` trait, which the instruction can query to see if
its desired feature set is available.

[here]: https://bytecodealliance.zulipchat.com/#narrow/channel/217117-cranelift/topic/boolean.20terms.20for.20x64.20features

* x64: wire up `Inst::is_available` in Cranelift

This change makes us of the assembler's new generated
`Inst::is_available` methods to check an instruction's feature set in a
more succinct (and likely quicker) way. Unfortunately, this does not
allow us to print the missing ISA requirements on failure--something to
address later.

* Rename `Features` to `AvailableFeatures`

* Remove unused `InstructionSet`

* asm: fix all feature definitions

This is a mechanical transformation converting all instruction
definitions. Now, instructions should have a correct boolean term
describe the features required: e.g., `(_64b | compat) & avx`.

* x64: replace `use_*` with `has_*` when checking ISA features

In Cranelift, the `has_*` flags of `isa::x64::settings::Flags` indicate
that the CPU _has_ some capability; the `use_*` flags indicate that
Cranelift _should emit_ instructions using those capabilities. Further,
the `use_*` flags may turned on by the presence of more than one `has_*`
flags; e.g., when `has_avx` and `has_avx2` are available, `use_avx2` is
enabled.

Now that Cranelift's new x64 assembler understands boolean terms, we no
longer need the `use_*` flags for checking if an instruction can be
emitted: instead, we should use the `has_*` flags and rely on the logic
encoded in `Inst::is_available`.

* asm: materialize `Features` via `Inst::features`

For better error messages (and just for general use of CPU features, see
discussion [here]), this change adds `Inst::features`--a way to
explicitly examine the boolean term for an instruction. This function
returns a `&'static Features` that contains the `AND` and `OR` branches
defining when an instruction is available. This is all generated into
something that looks like:

```rust
pub fn features(&self) -> &'static Features {
    const F1: &'static Features = &Features::Feature(Feature::_64b);
    const F2: &'static Features = &Features::Feature(Feature::compat);
    const F0: &'static Features = &Features::Or(F1, F2);
    F0
}
```

This change makes use of `for_each_feature` more: we build up the
`AvailableFeatures` trait and the `Feature` enum from it. This should be
a bit more direct than searching through the generated code (?).

[here]: bytecodealliance/wasmtime#11272 (comment)
In #11344 it was found that if Wasmtime had a frame on the stack then an
application's previous unwinding was broken. This was due to the fact
that Wasmtime's C API artifacts do not have unwind information built-in
due to being build with `-Cpanic=abort`. This change updates to building
the C API artifacts with `-Cforce-unwind-tables` even though Rust itself
won't use them to assist with embedders that want to unwind. These
should in theory be easily strippable if desired and additionally
embedders always have the option to build their own version of the C API
too.

Closes #11344
…llation (#11329)

* Notify new terminal needs to be opened after wastime installation

* Notify on-screen instructions need to be followed after wastime installation
In addition to keeping things up-to-date this enables testing the
`tail_loop` interpreter mode of Pulley using the `become` keyword and
native Rust syntax. This still isn't ready for prime-time so it's just
as gated as before, but we can promote a `cargo check` to a `cargo test`
in CI.
* Use the same `TcpSocket` in WASIp{2,3}

This is the same as #11384 except for `TcpSocket` to share the
implementation of TCP across WASIp{2,3} and avoid duplicating code
between the two.

* Fix CI issues

* Review comments

* Trim "TCP allowed?" checks

Like UDP only perform the check on socket creation, not after it's
created.
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
…ining (#11389)

This was an entity that we forgot to translate from the callee into the
caller. Note that we do not use the `EntityMap` offset approach for these
entities because `ir::Function` hash-conses them.
* Bump MSRV to Rust 1.87.0

Coincides with today's release of Rust 1.89

* Fix some lint warnings

* Fix tests with Pulley

* Fix lldb tests

* Fix a doc test on 32-bit
* Further expand differential fuzzing documentation

Split out the list of non-deterministic behaviors to its own separate
section to both make it more easy to scan over and additionally have
more fuzzing-related discussion such as generating programs that bake-in
NaN canonicalization. I've also updated this to include WASIp1 APIs to
discourage differential fuzzing of WASIp1 as the proposal is effectively
not suitable for this. I've noted, though, that WASIp2-and-beyond should
be suitable for differential fuzzing.

* Be bold.
ASAN is the longest builder right now and many of the slow tests aren't
really buying much such as:

* `disas` - no `unsafe` code
* `wast` - no need to test all permutations of compilers/collectors and
  instead one should suffice
* `all` - various tests taking 1m+ were flagged to ignore under ASAN as
  it's not necessarily important to run 100% of tests under ASAN.
Use `*::cast_{un,}signed` in the Rust standard library stabilized in
1.87.
This was no longer needed, and was adding build time to testing wasmtime
(rebuilt every time wasmtime changes, because it depends on wasmtime)
for no reason

prtest:full
Checking for the tombstone address during the reachability calculation
allows more DWARF entries to be marked as unreachable, and there was
already code to handle this for addresses left as 0.
This opts-in to a new Clippy lint which is intended to help clean up
historical refactorings to ensure that bounds on type parameters are
either in the type parameter declaration or in a `where` clause, but not
both.
* WIP: use the pagemap_scan ioctl to selectively reset an instance's dirty pages

* Less hacky, and supporting tables, too

* Bugfixes

* WIP: memcpy instead of pread

* Refactor support for pagemap

* Don't hold a raw pointer to the original data, plumb through an `Arc`
  to have a safe reference instead.
* Update pagemap bindings to latest version of abstraction written.
* Include pagemap-specific tests.
* Use a `PageMap` structure created once-per-pool instead of a
  static-with-a-file.
* Refactor to use the "pagemap path" unconditionally which blends in the
  keep_resident bits.

* Improve safety documentation

prtest:full

* Fix some lints

* Skip ioctl tests when it's not supported

* Fix a memory leak by moving impls around

* Fix no vm build

* Review comments

* Add more pagemap-specific documentation

* Add more docs, refactor implementation slightly

* Improve `category_*` docs

Basically forward to the Linux kernel source itself.

* Fix compile

* Make pagemap integration resilient across forks

* Fix non-pooling-allocator-build

* Fix portability issues of new test

* Actually use config on macos

---------

Co-authored-by: Till Schneidereit <till@tillschneidereit.net>
We would previously always create Cranelift `ir::FuncRef`s for the callee of a
Wasm `call` instruction, even if that was a call to an imported function that
actually gets translated to an indirect call in CLIF. This commit makes it so
that we delay `ir::FuncRef` creation until we actually emit a direct call.

Also I found that we were not looking for already-created `ir::SigRef`s when
creating `ir::FuncRef`s, so I fixed that as well, which removes a couple
duplicate signature definitions in our disas tests.
alexcrichton and others added 7 commits August 8, 2025 21:28
* Remove a dead trait method

Made obsolete from previous refactorings, so no need to keep this any
more.

* Fix unused import

* Fix missing import
This cannot be an `unsafe` method as it's not possible to provide the
guarantee that the memory is placed back in the store (e.g. `forget`-ing
futures). Instead make the method more strict and say that panics will
happen if `replace_memory` isn't called. Existing implementations should
already adhere to this.
* Minimize lazy allocation of the GC store

This commit is an effort to minimize the number of entrypoints which
might lazily allocate a GC store. The is currently done through
`StoreOpaque::gc_store_mut` but this method is very commonly used
meaning that there are many many places to audit for lazily allocating a
GC store. The reason that this needs an audit is that lazy allocation
is an async operation right now that must be on a fiber and is something
I'm looking to fix as part of #11262.

This commit performs a few refactorings to achieve this:

* `gc_store_mut` is renamed to `ensure_gc_store`. This is intended to be
  an `async` function in the future and clearly demarcates where lazy
  allocation of a GC store is occurring.

* `require_gc_store{,_mut}` is now added which is a pure accessor of the
  GC store with no lazy allocation. Most locations previously using
  `gc_store_mut` are updated to use this instead.

Documentation is added to store methods to clearly indicate which ones
are allocating and which ones should only be called in a context where
allocation should already have happened.

* Fix configured build

* Relax GC store restrictions in more places

* Review comments on documentation

* Move `ensure_gc_store` calls during instantiation

Instead update `needs_gc_heap` with the tables that are added to a
module and rely on instantiation to create the GC heap.

* Shuffle around some code

* Fix CI and review comments

* Add in a few more i31 cases for externref
* Refactor `AbortHandle`, renamed to `JoinHandle`

This commit is inspired by recent discussions about providing more
guarantees around dropping WASI resources. This commit renames
`wasmtime::component::AbortHandle` to `wasmtime::component::JoinHandle`
and additionally implements `Future for JoinHandle` to know when the
associated task's future has been dropped. The renaming is intended to
more closely align with `tokio::task::JoinHandle` where
`tokio::task::AbortHandle` is notably different and doesn't have a
`Future` implementation. The `Future` implementation helps embedders
know exactly when a value has been dropped and synchronize on that.

* Clarify lack of abort-on-drop behavior
* refactor: move `File` and `Dir` to top-level

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: extract filesystem utilities to top-level

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore: update `wasi:filesystem@0.3` WIT

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore: port p2 filesystem test

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* feat(wasip3): add filesystem stubs

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore(wasip3): use trapping errors is fs

for consistency with refactors for sockets

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* feat(wasip3): implement `wasi:filesystem` without reads

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore: remove unused enums

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: remove `NewTimestamp` enum

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor(p2): check FD types before permissions

Previously, `wasi:filesystem` functions taking two directory FDs as arguments,
would check permissions on the source directory before ensuring that
target FD is also a directory. This order has now been changed and first
implementations ensure that both FDs are directories and only then check
permissions.

This should not have any functional differences in guest applications

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor(fs): remove `Advice` enum

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor(sockets): remove `ResultWriteTask`

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* feat(wasip3): implement `wasi:filesystem` reads

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* chore(p3): ignore FS test due to runtime panic

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* fix: make `filesystem` module public

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* feat(wasip3): abort filesystem tasks on descriptor drop

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* Revert "feat(wasip3): abort filesystem tasks on descriptor drop"

This reverts commit 40415b52f79a33c376a2a875ffecb1d0a01c7903.

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* fix: avoid double `Accessor` entry

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* fix(p3): correctly handle FS I/O

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* fix(fs-p3): expect unreachable enums on Windows

prtest:full

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* fix(p3): correctly handle Windows read_dir

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

* refactor: reorder read_dir conditional

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>

---------

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
@alexcrichton alexcrichton enabled auto-merge August 12, 2025 17:29
@alexcrichton alexcrichton added this pull request to the merge queue Aug 12, 2025
Merged via the queue into bytecodealliance:main with commit c513a45 Aug 12, 2025
163 checks passed
@alexcrichton alexcrichton deleted the merge branch August 12, 2025 18:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.