* Migrate the wasmtime-types crate to no_std
This commit is where no_std for Wasmtime starts to get a bit
interesting. Specifically the `wasmtime-types` crate is the first crate
that depends on some nontrivial crates that also need to be migrated to
`no_std`. This PR disables the default feature of `wasmparser` by
default and additionally does the same for `serde`. This enables them to
compile in `no_std` contexts by default and default features will be
enabled elsewhere in this repository as necessary.
This also opts to drop the `thiserror` dependency entirely in favor of a
manual `Display` implementation with a cfg'd implementation of `Error`.
As before CI checks are added for `wasmtime-types` with a `no_std`
target itself to ensure the crate and all dependencies all avoid `std`.
* Fix adapter build
* Expose `wasmtime-runtime` as `crate::runtime::vm` internally for the `wasmtime` crate
* Rewrite uses of `wasmtime_runtime` to `crate::runtime::vm`
* Remove dep on `wasmtime-runtime` from `wasmtime-cli`
* Move the `wasmtime-runtime` crate into the `wasmtime::runtime::vm` module
* Update labeler for merged crates
* Fix `publish verify`
prtest:full
* move fx hash to workspace level dep
* change internal fxhash to use fxhash crate
* remove unneeded HashSet import
* change fxhash crate to rustc hash
* undo migration to rustc hash
* manually implement hash function from fxhash
* change to rustc hash
This removes about a million lines from our estimated audit backlog
according to `cargo vet suggest`.
If I understand the Criterion documentation correctly, I believe this
means that generating HTML reports from Criterion benchmarks now
requires having gnuplot installed, because it can't fall back to using
the pure-Rust "plotters" crate.
* Start migrating some Wasmtime crates to no_std
This commit is the first in what will be multiple PRs to migrate
Wasmtime to being compatible with `#![no_std]`. This work is outlined
in #8341 and the rough plan I have in mind is to go on a crate-by-crate
basis and use CI as a "ratchet" to ensure that `no_std` compat is
preserved. In that sense this PR is a bit of a template for future PRs.
This PR migrates a few small crates to `no_std`, basically those that
need no changes beyond simply adding the attribute. The nontrivial parts
introduced in this PR are:
* CI is introduced to verify that a subset of crates can indeed be
built on a `no_std` target. The target selected is
`x86_64-unknown-none` which is known to not have `std` and will result
in a build error if it's attempted to be used.
* The `anyhow` crate, which `wasmtime-jit-icache-coherence` now depends
on, has its `std` feature disabled by default in Wasmtime's workspace.
This means that some crates which require `std` now need to explicitly
enable the feature, but it means that by-default its usage is
appropriate for `no_std`.
The first point should provide CI checks that compatibility with
`no_std` indeed works, at least from an "it compiles" perspective. Note
that it's not sufficient to test with a target like
`x86_64-unknown-linux-gnu` because `extern crate std` will work on that
target, even when `#![no_std]` is active.
The second point however is likely to increase maintenance burden
in Wasmtime unfortunately. Namely we'll inevitably, either here or in
the future, forget to turn on some feature for some crate that's not
covered in CI checks. While I've tried to do my best here in covering it
there's no guarantee that everything will work and the combinatorial
explosion of what could be checked in CI can't all be added to CI.
Instead we'll have to rely on bug fixes, users, and perhaps point
releases to add more use cases to CI over time as we see fit.
* Add another std feature
* Another std feature
* Enable anyhow/std for another crate
* Activate `std` in more crates
* Fix miri build
* Fix compile on riscv64
prtest:full
* Fix min-platform example build
* Fix icache-coherence again
Wasmtime and Cranelift have a few miscellaenous use cases for "just take
this Rust type and make it bytes", for example Wasmtime's serialization
of internal metadata into a compiled module. Previously Wasmtime used
the `bincode` crate for performing these tasks as the format was
generally optimized to be small and fast, not general purpose (e.g.
JSON). The `bincode` crate on crates.io doesn't work on `no_std`,
however, and with the work in #8341 that's an issue now for Wasmtime.
This crate switches instead to the `postcard` crate. This crate is
listed in Serde's documentation as:
> Postcard, a no_std and embedded-systems friendly compact binary
> format.
While I've not personally used it before it checks all the boxes we
relied on `bincode` for and additionally works with `no_std`. After
auditing the crate this commit then switches out Wasmtime's usage of
`bincode` for `postcard` throughout the repository.
\### The `GcRuntime` and `GcCompiler` Traits
This commit factors out the details of the garbage collector away from the rest
of the runtime and the compiler. It does this by introducing two new traits,
very similar to a subset of [those proposed in the Wasm GC RFC], although not
all equivalent functionality has been added yet because Wasmtime doesn't
support, for example, GC structs yet:
[those proposed in the Wasm GC RFC]: https://github.com/bytecodealliance/rfcs/blob/main/accepted/wasm-gc.md#defining-the-pluggable-gc-interface
1. The `GcRuntime` trait: This trait defines how to create new GC heaps, run
collections within them, and execute the various GC barriers the collector
requires.
Rather than monomorphize all of Wasmtime on this trait, we use it
as a dynamic trait object. This does imply some virtual call overhead and
missing some inlining (and resulting post-inlining) optimization
opportunities. However, it is *much* less disruptive to the existing embedder
API, results in a cleaner embedder API anyways, and we don't believe that VM
runtime/embedder code is on the hot path for working with the GC at this time
anyways (that would be the actual Wasm code, which has inlined GC barriers
and direct calls and all of that). In the future, once we have optimized
enough of the GC that such code is ever hot, we have options we can
investigate at that time to avoid these dynamic virtual calls, like only
enabling one single collector at build time and then creating a static type
alias like `type TheOneGcImpl = ...;` based on the compile time
configuration, and using this type alias in the runtime rather than a dynamic
trait object.
The `GcRuntime` trait additionally defines a method to reset a GC heap, for
use by the pooling allocator. This allows reuse of GC heaps across different
stores. This integration is very rudimentary at the moment, and is missing
all kinds of configuration knobs that we should have before deploying Wasm GC
in production. This commit is large enough as it is already! Ideally, in the
future, I'd like to make it so that GC heaps receive their memory region,
rather than allocate/reserve it themselves, and let each slot in the pooling
allocator's memory pool be *either* a linear memory or a GC heap. This would
unask various capacity planning questions such as "what percent of memory
capacity should we dedicate to linear memories vs GC heaps?". It also seems
like basically all the same configuration knobs we have for linear memories
apply equally to GC heaps (see also the "Indexed Heaps" section below).
2. The `GcCompiler` trait: This trait defines how to emit CLIF that implements
GC barriers for various operations on GC-managed references. The Rust code
calls into this trait dynamically via a trait object, but since it is
customizing the CLIF that is generated for Wasm code, the Wasm code itself is
not making dynamic, indirect calls for GC barriers. The `GcCompiler`
implementation can inline the parts of GC barrier that it believes should be
inline, and leave out-of-line calls to rare slow paths.
All that said, there is still only a single implementation of each of these
traits: the existing deferred reference-counting (DRC) collector. So there is a
bunch of code motion in this commit as the DRC collector was further isolated
from the rest of the runtime and moved to its own submodule. That said, this was
not *purely* code motion (see "Indexed Heaps" below) so it is worth not simply
skipping over the DRC collector's code in review.
\### Indexed Heaps
This commit does bake in a couple assumptions that must be shared across all
collector implementations, such as a shared `VMGcHeader` that all objects
allocated within a GC heap must begin with, but the most notable and
far-reaching of these assumptions is that all collectors will use "indexed
heaps".
What we are calling indexed heaps are basically the three following invariants:
1. All GC heaps will be a single contiguous region of memory, and all GC objects
will be allocated within this region of memory. The collector may ask the
system allocator for additional memory, e.g. to maintain its free lists, but
GC objects themselves will never be allocated via `malloc`.
2. A pointer to a GC-managed object (i.e. a `VMGcRef`) is a 32-bit offset into
the GC heap's contiguous region of memory. We never hold raw pointers to GC
objects (although, of course, we have to compute them and use them
temporarily when actually accessing objects). This means that deref'ing GC
pointers is equivalent to deref'ing linear memory pointers: we need to add a
base and we also check that the GC pointer/index is within the bounds of the
GC heap. Furthermore, compressing 64-bit pointers into 32 bits is a fairly
common technique among high-performance GC
implementations[^compressed-oops][^v8-ptr-compression] so we are in good
company.
3. Anything stored inside the GC heap is untrusted. Even each GC reference that
is an element of an `(array (ref any))` is untrusted, and bounds checked on
access. This means that, for example, we do not store the raw pointer to an
`externref`'s host object inside the GC heap. Instead an `externref` now
stores an ID that can be used to index into a side table in the store that
holds the actual `Box<dyn Any>` host object, and accessing that side table is
always checked.
[^compressed-oops]: See ["Compressed OOPs" in
OpenJDK.](https://wiki.openjdk.org/display/HotSpot/CompressedOops)
[^v8-ptr-compression]: See [V8's pointer
compression](https://v8.dev/blog/pointer-compression).
The good news with regards to all the bounds checking that this scheme implies
is that we can use all the same virtual memory tricks that linear memories use
to omit explicit bounds checks. Additionally, (2) means that the sizes of GC
objects is that much smaller (and therefore that much more cache friendly)
because they are only holding onto 32-bit, rather than 64-bit, references to
other GC objects. (We can, in the future, support GC heaps up to 16GiB in size
without losing 32-bit GC pointers by taking advantage of `VMGcHeader` alignment
and storing aligned indices rather than byte indices, while still leaving the
bottom bit available for tagging as an `i31ref` discriminant. Should we ever
need to support even larger GC heap capacities, we could go to full 64-bit
references, but we would need explicit bounds checks.)
The biggest benefit of indexed heaps is that, because we are (explicitly or
implicitly) bounds checking GC heap accesses, and because we are not otherwise
trusting any data from inside the GC heap, we greatly reduce how badly things
can go wrong in the face of collector bugs and GC heap corruption. We are
essentially sandboxing the GC heap region, the same way that linear memory is a
sandbox. GC bugs could lead to the guest program accessing the wrong GC object,
or getting garbage data from within the GC heap. But only garbage data from
within the GC heap, never outside it. The worse that could happen would be if we
decided not to zero out GC heaps between reuse across stores (which is a valid
trade off to make, since zeroing a GC heap is a defense-in-depth technique
similar to zeroing a Wasm stack and not semantically visible in the absence of
GC bugs) and then a GC bug would allow the current Wasm guest to read old GC
data from the old Wasm guest that previously used this GC heap. But again, it
could never access host data.
Taken altogether, this allows for collector implementations that are nearly free
from `unsafe` code, and unsafety can otherwise be targeted and limited in scope,
such as interactions with JIT code. Most importantly, we do not have to maintain
critical invariants across the whole system -- invariants which can't be nicely
encapsulated or abstracted -- to preserve memory safety. Such holistic
invariants that refuse encapsulation are otherwise generally a huge safety
problem with GC implementations.
\### `VMGcRef` is *NOT* `Clone` or `Copy` Anymore
`VMGcRef` used to be `Clone` and `Copy`. It is not anymore. The motivation here
was to be sure that I was actually calling GC barriers at all the correct
places. I couldn't be sure before. Now, you can still explicitly copy a raw GC
reference without running GC barriers if you need to and understand why that's
okay (aka you are implementing the collector), but that is something you have to
opt into explicitly by calling `unchecked_copy`. The default now is that you
can't just copy the reference, and instead call an explicit `clone` method (not
*the* `Clone` trait, because we need to pass in the GC heap context to run the
GC barriers) and it is hard to forget to do that accidentally. This resulted in
a pretty big amount of churn, but I am wayyyyyy more confident that the correct
GC barriers are called at the correct times now than I was before.
\### `i31ref`
I started this commit by trying to add `i31ref` support. And it grew into the
whole traits interface because I found that I needed to abstract GC barriers
into helpers anyways to avoid running them for `i31ref`s, so I figured that I
might as well add the whole traits interface. In comparison, `i31ref` support is
much easier and smaller than that other part! But it was also difficult to pull
apart from this commit, sorry about that!
---------------------
Overall, I know this is a very large commit. I am super happy to have some
synchronous meetings to walk through this all, give an overview of the
architecture, answer questions directly, etc... to make review easier!
prtest:full
* Lift all serde deps to the workspace level
Deduplicate some versions mentioned throughout crates in the workspace.
* Lift `bincode` deps to the workspace configuration level
Deduplicate some mentioned versions throughout.
* Lift libc deps up to the workspace root
As with prior commits, deduplicate some versions mentioned.
* Gate support for the wasm `threads` proposal behind a Cargo feature
This commit moves support for the `threads` proposal behind a new
on-by-default Cargo feature: `threads`. This is intended to support
building Wasmtime with fewer runtime dependencies such as those required
for the atomic operations on memories.
This additionally adds the `gc` feature in a few missing places too.
* Fix compile of C API without threads
With all Winch tests moved to `tests/disas` in #8243 plus the support of
`wasmtime compile -C compiler=winch` this tool should in theory be
supplanted nowadays with other alternatives. This commit removes the
executable and the `winch-filetests` support.
* Disassemble `*.cwasm` for `compile` disas tests
This commit changes how the `compile` mode of the `disas` test suite
works. Previously this would use `--emit-clif` and run the Cranelift
pipeline for each individual function and use the custom VCode-based
disassembly for instruction output. This commit instead uses the raw
binary coming out of Wasmtime. The ELF file itself is parsed and is
disassembled in a manner similar to Winch tests.
The goal of this commit is somewhat twofold:
* Lay the groundwork to migrate all Winch-based filetests to
`tests/disas`.
* Test the raw output from Cranelift/Wasmtime which includes
optimizations like branch chomping in the `MachBuffer`.
This commit doesn't itself move the Winch tests yet, that's left for a
future commit.
* Update all test expectations for new output
* Fix PR-based CI when too many files are changed
This provides a bit of a nicer experience than the default "build your
own test harness" experience by providing things like filters and
parallel execution by default. This helps speed up the `disas` test
suite, for example, which previously had no parallelism.
The wasmtime-cranelift-shared crate is not as useful as it once was, as
it's no longer possible to build wasmtime with only winch; winch uses
the trampolines generated by cranelift now.
* Bump MSRV to 1.75.0
Coupled with today's release of 1.77.0. Today's release actually has
some nice functions and such I think we'll want to use in Wasmtime but
we'll need to wait 3 months to be able to use them.
* Fix dead code warning in onnx
* Delete now-dead code from the wasm runner in cranelift-filetest
No longer needed with tests having moved out to `tests/disas`
* Move wasm<->clif testing to `tests/disas.rs`
No need for `test_wasm.rs` to stick around in cranelift-filetest, so
move the bits up a layer.
* Remove wasm crate dependencies
* Change bless env var name
* Force link to `libm`
* Add an `asm` test suite for Wasmtime
This commit adds a suite of tests at `tests/asm/*.wat` which is intended
to replace the tests in `cranelift/filetests/filetests/wasm`. Tests are
configured differently than before using Wasmtime CLI flags rather than
a custom TOML-based configuration scheme. Otherwise though the same
shape of tests is supported.
This commit migrates a small handful of tests as a showcase and bulk
migration is left for a follow-up.
* Organize the asm.rs test with methods/functions
* Switch back to TOML for config parsing
* Disable disassembly tests on miri
Takes a bit too long in cranelift
This commit updates the minimum Rust version supported by Wasmtime to
1.74.0 which is two behind the current stable 1.76. At the same time
this additionally updates nightly in CI to stay up-to-date there.
* update capstone dependency to 0.12.0
this is only used for benchmarking, so the cargo vet is just an exemption which I updated to the latest version.
* winch filetests: fix capstone changes
* Add a "custom" platform configuration for Wasmtime
This commit leverages adds a new "platform" to Wasmtime to be supported
in the `crates/runtime/src/sys` folder. This joins preexisting platforms
such as Unix and Windows. The goal of this platform is to be an opt-in
way to build Wasmtime for targets that don't have a predefined way to
run.
The new "custom" platform requires `--cfg wasmtime_custom_platform` to
be passed to the Rust compiler, for example by using `RUSTFLAGS`. This
new platform bottoms out in a C API that is intended to be small and
Linux-like. The C API is effectively the interface to virtual memory
that Wasmtime requires. This C API is also available as a header file at
`examples/min-platform/embedding/wasmtime-platform.h` (generated by
`cbindgen`).
The main purpose of this is to make it easier to experiment with porting
Wasmtime to new platforms. By decoupling a platform implementation from
Wasmtime itself it should be possible to run these experiments
out-of-tree. An example of this I've been working on is getting
Wasmtime running on bare-metal with a custom kernel. This support
enables defining the platform interface of the custom kernel's syscalls
outside of Wasmtime.
* Exclude wasmtime-platform.h from formatting
* Include build-wasmtime-target-wasm32 in final job
* Don't force any single toolchain
* Add notes to no_std docs
* Add rust-src to CI
* Review comments
* Change APIs to be fallible
* Only compile the min-platform example on Linux
* Fix compile of min-platform example
* Fix another compile error in the example
First of all, it is just a nice separation of concerns.
Second of all, as I design the GC rooting APIs for Wasmtime's upcoming Wasm GC
support, I want this same thing and I'd rather not open code it multiple times.
* Enable compiling the Wasmtime CLI to Wasm
While not the most useful thing to do in the world it's kind of neat to
play around with. This builds on the previous work to exclude the
runtime from the `wasmtime` crate so it's now possible to compile the
Wasmtime CLI's `compile` command, and only the `compile` command, to
wasm itself. This means you can run Wasmtime in Wasmtime!
* Fix warning on wasm
* Fix some feature combos
* Remove the `WASI` submodule
Historically the `WASI` submodule in this repository was used to pull
the sources of the `*.witx` files for preview1. This has never been used
by the `wasmtime-wasi` crate (which has its own copy in the
`crates/wasi/witx` folder) and was only ever used by `wasi-common`. This
submodule also served as a location for the `witx` crate itself.
Neither of these are really needed any more as the `*.witx` files are
unlikely to ever really change again. This commit removes the submodule
entirely, as well as the `path` dependency on `witx`, and copies the
`*.witx` files in the same manner as the `wasmtime-wasi` crate.
* Updated vet entries for witx
* Remove witx special cases in publish script
* Change how the wasi-common package is built
* better top matter
* eliminate wasi-common deprecations from wasmtime-wasi
* wasmtime-wasi: preview2 feature always enabled, so just eliminate it
* rename preview1-on-preview2 feature to just preview1
* wasi-http fix
* dep fixes. change some log::debug! to tracing::debug!
* mv preview2 up to root
and `sed -i 's/crate::preview2/crate/g' **/*.rs`
* fix tests too
* fixes throughout wasmtime-wasi-http
* cli: s/wasmtime_wasi::preview2/wasmtime_wasi
* rustfmt
* fix wasi-async example
* fix docs build (needs wasi-common built to compile examples)
* c-api: use wasi-common directly
i guess we didnt build the c-api in CI with deprecation warnings denied
prtest:full
* fix example required-features
* fix examples CMakeLists build
* WIP: try to make wasi-common self contained.
* rebase: cargo.lock
* remove all dependencies between wasi-common and wasmtime-wasi
* use wasi-common directly throughout tests, benches, examples, cli run
* wasi-threads: use wasi-common's maybe_exit_on_error in spawned thread
not a very modular design, but at this point wasi-common and
wasi-threads are forever wed
* fix wasmtime's docs
* re-introduce wasmtime-wasi's exports of wasi-common definitions behind deprecated
* factor out determining i32 process exit code
and remove libc dep because rustix provides the same constant
* commands/run: inline the logic about aborting on trap
since this is the sole place in the codebase its used
* Add high-level summary to wasi-common's top-level doc comment.
* c-api: fix use of wasi_cap_std_sync => wasi_common::sync, wasmtime_wasi => wasi_common
* fix tokio example
* think better of combining downcast and masking into one method
* fix references to wasmtime_wasi in docs
prtest:full
* benches: use wasi-common
* cfg-if around use of rustix::process because that doesnt exist on windows
* wasi-common: include tests, caught by verify-publish
* fix another bench
* exit requires wasmtime dep. caught by verify-publish.
* Update the wasm-tools family of crates
Pulling in some updates to improve how WIT is managed in this
repository. No changes just yet, however, just pulling in the updates
first.
* Fix tests
* Fix fuzzer build
* Add wasmtime-c-api-impl to the list of crates to publish
* Enable rustdoc and publishing for c-api crate
* Provide paths to c-api headers as cargo links metadata
* Add a README section about using wasm-c-api in a rust crate
* In C API doc comment, mention use case for crates w/ C bindings
* Enable publishing for wasmtime-c-api-macros (prtest:full)
* Move c-api crates later in the publishing sequence (prtest:full)
This commit updates the `wasmtime` crate itself to have the
`component-model` feature enabled by default. This was also done for the
CLI but only for clarity because the `component-model` feature was
already eanbled by default transitively through the `serve` feature.
Don't force-enable the `wasmtime-wast` crate if the `component-model`
feature is active, only activate component model support if
`wasmtime-wast` is otherwise activated.
* Move `jit` crate to `environ`
Move the platform agnostic parts of the crate `wasmtime-jit` to
`wasmtime-environ`. This is the first part of the refactoring discussed
here: https://github.com/bytecodealliance/wasmtime/issues/7652 and a
follow up will move the remaining parts of `wasmtime-jit` so that the
crate can be deleted.
* Move `jit` crate to `wasmtime`
Move the remaining parts of `wasmtime-jit` to the `wasmtime` crate and
remove `wasmtime-jit`. This is part of the refactoring discussed in
https://github.com/bytecodealliance/wasmtime/issues/7652.
* undo toml formatting
* Trigger pipeline: prtest:full
* Remove `jit` directory
* move `ProfilingAgent` out of `profiling` feature
* add links to ELF_NAME_DATA
* Update the wasm-tools family of crates
Brings in support for validating gc instructions, but they're all left
disabled for now.
* Update fuzz test case generation
* More test fixes, remove stray files
* More test fixes
* Rebase