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

Merge with main#243

Closed
alexcrichton wants to merge 32 commits intobytecodealliance:mainfrom
alexcrichton:merge
Closed

Merge with main#243
alexcrichton wants to merge 32 commits intobytecodealliance:mainfrom
alexcrichton:merge

Conversation

@alexcrichton
Copy link
Copy Markdown
Member

No description provided.

tschneidereit and others added 30 commits July 30, 2025 08:29
* 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.
* 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)
Basically forward to the Linux kernel source itself.
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
@alexcrichton
Copy link
Copy Markdown
Member Author

I forgot to merge this...

@alexcrichton alexcrichton deleted the merge branch August 12, 2025 17:28
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.

5 participants