* Add a component type accessor for `Component`
All the bits are already in place so all that's needed is to touch up
some docs and fixup a minor case uncovered through testing. Otherwise
this enables runtime reflection over the imports and exports of an
uninstantiated component.
* Run test through miri
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.
This commit clears out the dynamic tracking of borrows within a
`ResourceAny` when it's converted to a `Resource<T>`. The `Resource<T>`
type doesn't participate in this borrow tracking in the same way as
`ResourceAny` because it's assumed that hosts are well-behaved in this
regard. This means that the conversion here should respect these
guarantees of `Resource<T>` and auto-clear the borrow tracking.
* Remove type information from dynamic component funcs
This commit removes the `&Component` argument from the
`component::Linker::func_new` API. This is inspired by #8062 where `Val`
holds less type information as well in addition to the realization that
type-checking happens at runtime rather than instantiation time.
This argument was originally added to mirror
`wasmtime::Linker::func_new` which takes a type argument of the core
wasm function that's being defined. Unlike core wasm, though, component
functions already have to carry along their type information as part of
function calls to handle resources correctly. This means that when a
host function is invoked the type is already known of all the parameters
and results. Additionally values are already required to be type-checked
going back into wasm, so there's less of a need to perform an additional
type-check up front.
The main consequence of this commit is that it's a bit more difficult
for embeddings to know what the expected types of results are. No type
information is provided when a host function is defined, not even
function arity. This means that when the host function is invoked it may
not know how many results are expected to be produced and of what type.
Typically though a bindings generator is used somewhere along the way so
that's expected to alleviate this issue.
Finally my hope is to enhance this "dynamic" API in the future with a
bit more information so the type information is more readily accessible
at runtime. For now though hosts will have to "simply know what to do".
* Update crates/wasmtime/src/runtime/component/linker.rs
Co-authored-by: Joel Dice <joel.dice@fermyon.com>
* Fix doc links
* Fix component call benchmarks
---------
Co-authored-by: Joel Dice <joel.dice@fermyon.com>
* Add a winch calling convention to cranelift
* Add some tests to exercise the winch calling convention
* Enable fuzzing for the winch calling convention
* Share the list of clobbers with the tail calling convention
* Fix the doc build
* Move dtor information from `ResourceAny` into a `Store`
This commit moves the internals of the `ResourceAny` type related to
destructors into the auxiliary data within a `Store`. This avoids the
need to carry around pointers with `ResourceAny` and additionally makes
it easier to work with.
As part of this commit this also updates the behavior of
`ResourceAny::try_from_resource` to no longer need an `InstancePre` and
type information. This was required originally to get
`ResourceAny::resource_drop` working to drop the host resource. In
retrospect I'm not sure if this was the best goal to achieve because
`Resource<T>` already has no destructor support and one of the more
common use cases for the conversion is to simply turn around and give it
back to a component where a component already has enough destructor
information.
In the end this should make both `ResourceAny` and `Resource<T>` pretty
close to "just an index" which is easier to reason about when working
with resources than carrying additional pointers.
* Remove now-unneeded ResourceImportIndex machinery
* Migrate mach to mach2
* Add audit for mach2 0.4.1 -> 0.4.2
* Use mach2 things instead of custom addons
* Fix build on aarch64-apple-darwin.
* Cast the u32 flags to i32.
* Add back custom definition that doesn't match `mach2`
prtest:full
* Fix x64 unused import
---------
Co-authored-by: Junji Takakura <j.takakura@gmail.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
Co-authored-by: Alex Crichton <alex@alexcrichton.com>
This commit is a large refactor of the `Val` type as used with
components to remove inherent type information present currently. The
`Val` type is now only an AST of what a component model value looks like
and cannot fully describe the type that it is without further context.
For example enums only store the case that's being used, not the full
set of cases.
The motivation for this commit is to make it simpler to use and
construct `Val`, especially in the face of resources. Some problems
solved here are:
* With resources in play managing type information is not trivial and
can often be surprising. For example if you learn the type of a
function from a component and the instantiate the component twice the
type information is not suitable to use with either function due to
exported resources acquiring unique types on all instantiations.
* Functionally it's much easier to construct values when type
information is not required as it no longer requires probing various
pieces for type information here and there.
* API-wise there's far less for us to maintain as there's no need for a
type-per-variant of component model types. Pieces now fit much more
naturally into a `Val` shape without extra types.
* Functionally when working with `Val` there's now only one typecheck
instead of two. Previously a typecheck was performed first when a
`Val` was created and then again later when it was passed to wasm. Now
the typecheck only happens when passed to wasm.
It's worth pointing out that `Val` as-is is a pretty inefficient
representation of component model values, for example flags are stored
as a list of strings. While semantically correct this is quite
inefficient for most purposes other than "get something working". To
that extent my goal is to, in the future, add traits that enable
building a custom user-defined `Val` (of sorts), but still dynamically.
This should enable embedders to opt-in to a more efficient
representation that relies on contextual knowledge.
* egraph: Ensure eclass members are all available in the same block
During elaboration, we want the property that it's safe to pick any
member of an eclass to implement that eclass. To establish that
property, this commit defines a notion of the "available block" for
every value, and enforces that all values in an eclass have the same
available block.
Closes#7891 where we devised this plan.
Co-authored-by: L Pereira <l.pereira@fastly.com>
* Review comments
- add documentation comments
- push orig_value onto optimized_values before calling simplify so it
can't cause a heap reallocation
* Delay pushing orig_value so filetests don't change
* Don't set available-block for instructions removed by GVN
Because the duplicate instruction is never used, it never matters what
block it might be available in. For the same reason it also doesn't need
to be in the union-find.
* Add tests
---------
Co-authored-by: L Pereira <l.pereira@fastly.com>
* Fix `wasmtime settings` command.
Currently the `settings` command panics because the tunables are not set in the
compiler builder.
This commit creates a default tunables based on either the target triple passed
on the command line or uses the default for the host.
Fixes#8058.
* Additional clean up.
This commit fixes the bounds check comparison for dynamic heaps. The previous implementation wasn't using the right value: for the general case of dynamic heaps, we want to compare if
index + offset + access_size > bounds
But it was only comparing
index > bounds
This commit addresses the issue by adding a new temporary register into the equation which will be used for the bounds check comparison and for overflow checks. This approach is preferred over using the scratch register because it's harder to know when the scratch register might get clobbered (in the case of spectre checks, it could for example)
* Define garbage collection rooting APIs
Rooting prevents GC objects from being collected while they are actively being
used.
We have a few sometimes-conflicting goals with our GC rooting APIs:
1. Safety: It should never be possible to get a use-after-free bug because the
user misused the rooting APIs, the collector "mistakenly" determined an
object was unreachable and collected it, and then the user tried to access
the object. This is our highest priority.
2. Moving GC: Our rooting APIs should moving collectors (such as generational
and compacting collectors) where an object might get relocated after a
collection and we need to update the GC root's pointer to the moved
object. This means we either need cooperation and internal mutability from
individual GC roots as well as the ability to enumerate all GC roots on the
native Rust stack, or we need a level of indirection.
3. Performance: Our rooting APIs should generally be as low-overhead as
possible. They definitely shouldn't require synchronization and locking to
create, access, and drop GC roots.
4. Ergonomics: Our rooting APIs should be, if not a pleasure, then at least not
a burden for users. Additionally, the API's types should be `Sync` and `Send`
so that they work well with async Rust.
For example, goals (3) and (4) are in conflict when we think about how to
support (2). Ideally, for ergonomics, a root would automatically unroot itself
when dropped. But in the general case that requires holding a reference to the
store's root set, and that root set needs to be held simultaneously by all GC
roots, and they each need to mutate the set to unroot themselves. That implies
`Rc<RefCell<...>>` or `Arc<Mutex<...>>`! The former makes the store and GC root
types not `Send` and not `Sync`. The latter imposes synchronization and locking
overhead. So we instead make GC roots indirect and require passing in a store
context explicitly to unroot in the general case. This trades worse ergonomics
for better performance and support for moving GC and async Rust.
Okay, with that out of the way, this module provides two flavors of rooting
API. One for the common, scoped lifetime case, and another for the rare case
where we really need a GC root with an arbitrary, non-LIFO/non-scoped lifetime:
1. `RootScope` and `Rooted<T>`: These are used for temporarily rooting GC
objects for the duration of a scope. Upon exiting the scope, they are
automatically unrooted. The internal implementation takes advantage of the
LIFO property inherent in scopes, making creating and dropping `Rooted<T>`s
and `RootScope`s super fast and roughly equivalent to bump allocation.
This type is vaguely similar to V8's [`HandleScope`].
[`HandleScope`]: https://v8.github.io/api/head/classv8_1_1HandleScope.html
Note that `Rooted<T>` can't be statically tied to its context scope via a
lifetime parameter, unfortunately, as that would allow the creation and use
of only one `Rooted<T>` at a time, since the `Rooted<T>` would take a borrow
of the whole context.
This supports the common use case for rooting and provides good ergonomics.
2. `ManuallyRooted<T>`: This is the fully general rooting API used for holding
onto non-LIFO GC roots with arbitrary lifetimes. However, users must manually
unroot them. Failure to manually unroot a `ManuallyRooted<T>` before it is
dropped will result in the GC object (and everything it transitively
references) leaking for the duration of the `Store`'s lifetime.
This type is roughly similar to SpiderMonkey's [`PersistentRooted<T>`],
although they avoid the manual-unrooting with internal mutation and shared
references. (Our constraints mean we can't do those things, as mentioned
explained above.)
[`PersistentRooted<T>`]: http://devdoc.net/web/developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::PersistentRooted.html
At the end of the day, both `Rooted<T>` and `ManuallyRooted<T>` are just tagged
indices into the store's `RootSet`. This indirection allows working with Rust's
borrowing discipline (we use `&mut Store` to represent mutable access to the GC
heap) while still allowing rooted references to be moved around without tying up
the whole store in borrows. Additionally, and crucially, this indirection allows
us to update the *actual* GC pointers in the `RootSet` and support moving GCs
(again, as mentioned above).
* Reorganize GC-related submodules in `wasmtime-runtime`
* Reorganize GC-related submodules in `wasmtime`
* Use `Into<StoreContext[Mut]<'a, T>` for `Externref::data[_mut]` methods
* Run rooting tests under MIRI
* Make `into_abi` take an `AutoAssertNoGc`
* Don't use atomics to update externref ref counts anymore
* Try to make lifetimes/safety more-obviously correct
Remove some transmute methods, assert that `VMExternRef`s are the only valid
`VMGcRef`, etc.
* Update extenref constructor examples
* Make `GcRefImpl::transmute_ref` a non-default trait method
* Make inline fast paths for GC LIFO scopes
* Make `RootSet::unroot_gc_ref` an `unsafe` function
* Move Hash and Eq for Rooted, move to impl methods
* Remove type parameter from `AutoAssertNoGc`
Just wrap a `&mut StoreOpaque` directly.
* Make a bunch of internal `ExternRef` methods that deal with raw `VMGcRef`s take `AutoAssertNoGc` instead of `StoreOpaque`
* Fix compile after rebase
* rustfmt
* revert unrelated egraph changes
* Fix non-gc build
* Mark `AutoAssertNoGc` methods inline
* review feedback
* Temporarily remove externref support from the C API
Until we can add proper GC rooting.
* Remove doxygen reference to temp deleted function
* Remove need to `allow(private_interfaces)`
* Fix call benchmark compilation
This commit defers the usage of `format!` until it's actually needed when retrieving addresses for locals. This helps improve performance in modules that incur in a considerable number of local lookups.
This commit fixes a bug where when an out-of-bounds access is detected at compile time, `emit_wasm_store` was failing to free the source register. By the time the address is computed, the register is already allocated, independently if it's used or not, it must be freed.
* Add commentary on advantages/disadvantages of the pooling allocator
Inspired by discussion on #8034
* Add `memory_init_cow` commentary on disadvantages
* Fix doc link
* Show true error reason in `wasmtime serve`
The `wasmtime serve` command prints failed HTTP handling to `stderr`
but, when the reason was due to failure inside the HTTP handler itself,
the printed error message is not descriptive enough. After looking at
long dumps of `guest never invoked `response-outparam::set` method`, I
realized that errors inside the Tokio `task` are never propagated
outwards. This change captures those errors and appends them to the
printed error message.
* review: remove TODO comment
* review: improve doc comment
Co-authored-by: Trevor Elliott <telliott@fastly.com>
* review: add comment about immediate resolution
---------
Co-authored-by: Trevor Elliott <telliott@fastly.com>
* Add CLI flags for instance limits
While experimenting with `wasmtime serve`, I found it helpful to be able
to configure some of the maximum limits of the various objects stored in
the pooling allocator. This change surfaces some new `-O total-*` flags
for controlling these limits from the command line.
* review: prepend flags with `pooling_*`
* 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 WinML backend for wasi-nn.
* Log execution time.
* WinML backend supports execution target selection.
ExecutionTarget::Gpu is mapped to LearningModelDeviceKind::DirectX.
* Limit WinML backend on Windows only.
* Move wasi-nn WinML example to new test infra.
* Scale tensor data in test app.
App knows input and target data range, so it's better to let app to
handle scaling.
* Remove old example for wasi-nn WinML backend.
* Update image2tensor link.
* Format code.
* Upgrade image2tensor to 0.3.1.
* Upgrade windows to 0.52.0
* Use tensor data as input for wasi-nn WinML backend test.
To avoid involving too many external dependencies, input image is
converted to tensor data offline.
* Restore trailing new line for Cargo.toml.
* Remove unnecessary features for windows crate.
* Check input tensor types.
Only FP32 is supported right now. Reject other tensor types.
* Rename default model name to model.onnx.
It aligns with openvino backend.
prtest:full
* Run nn_image_classification_winml only when winml is enabled.
* vet: add trusted `windows` crate to lockfile
* Fix wasi-nn tests when both openvino and winml are enabled.
* Add check for WinML availability.
* vet: reapply vet lock
---------
Co-authored-by: Andrew Brown <andrew.brown@intel.com>
This commit fixes an issue when inspecting the types of a component
where if a resource type wasn't substituted through an import it would
end up panicking. The fix here is to add a third kind of resource type
which represents an uninstantiated component as opposed to an
instantiated component or host type.
Closes#8003
When native unwinding information is enabled Wasmtime will use the
`__register_frame` API on Unix platforms to inform the runtime of the
unwinding information generated for wasm modules. This function,
however, has a different interface in libgcc vs libunwind. This means
that we need to detect which is being used and adapt our calls to it
appropriately.
Previously this decision was static. FreeBSD and Linux glibc would
assume libgcc and everything else was assumed to be libunwind. It's
possible to use libgcc on other platforms, however, such as with musl.
The goal of this PR is to make the detection here more robust.
Specifically this PR now probes for a symbol at runtime rather than
relying on a compile-time decision. That way we can see what we got at
runtime and make the decision then.
Closes#7997
* 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
This commit is an attempt to make the mistake fixed in #8016 harder to
happen again. This removes the `set_raw` helper entirely from tables and
instead forces all callers to view the table as either a table of
funcrefs or a table of externefs. By forcing that choice outwards
instead of handling it inwards it enables dealing with a typed table in
more contexts which should help naturally do the right thing.
While debugging #7999, we learned of a possible, extremely subtle,
interaction between the design of our ISLE mid-end prelude and matching
rules with a certain structure. Because a `Value` represents an entire
eclass, separate left-hand sides (as in helper rules or if-let clauses)
that match on the value may match against different enodes returned by
the multi-match extractor's iterator. We then may infer some property of
one enode, another property of another enode, and perform a rewrite that
is only valid if both of those matches are on the same enode.
The precise distinction is whether it is a property of the *value* -- e.g.,
nonzero, or even, or within a range -- or a property of the *operation*
and matched subpieces. The former is fine, the latter runs into
trouble. We found that #7719 added a helper that determined whether a
value "was a certain operator" -- actually, had any enode of a certain
operator -- and separately, matched "the operator" and extracted its
opcode and parameters (actually, *any* binary operator). The first half
can match an opcode we support simplifying, and the second half can get
the arguments and `op` and blindly use them in the rewrite.
This PR adds new guidance to avoid complex helpers and be aware of
multi-matching behavior, preferring to write patterns directly (as the
fix in #8005 does) instead. Longer-term, we also have other ideas, e.g.
@jameysharp's suggestion to disallow at-patterns on multi-extractors in
left hand sides to reduce the chance of hitting this footgun.
This logs the resulting values of a call into ISLE's `simplify` constructor, not
just the input value, so we can better debug in the future by tracing how a value
was produced and which value it is a rewrite of.
New output:
Calling into ISLE with original value v2
-> returned from ISLE: v2 -> [v3, v4, v5]
Old output:
Calling into ISLE with original value v2
-> returned from ISLE, generated 3 optimized values
We had two optimization rules which started off like this:
(rule (simplify (ireduce smallty val@(binary_op _ op x y)))
(if-let _ (reducible_modular_op val))
...)
This was intended to check that `x` and `y` came from an instruction
which not only was a binary op but also matched `reducible_modular_op`.
Unfortunately, both `binary_op` and `reducible_modular_op` were
multi-terms.
- So `binary_op` would search the eclass rooted at `val` to find each
instruction that uses a binary operator.
- Then `reducible_modular_op` would search the entire eclass again to
find an instruction which matched its criteria.
Nothing ensured that both searches would find the same instruction.
The reason these rules were written this way was because they had
additional guards (`will_simplify_with_ireduce`) which made them fairly
complex, and it seemed desirable to not have to copy those guards for
every operator where we wanted to apply this optimization.
However, we've decided that checking whether the rule is actually an
improvement is not desirable. In general, that should be the job of the
cost function. Blindly adding equivalent expressions gives us more
opportunities for other rules to fire, and we have global recursion and
growth limits to keep the process from going too wild.
As a result, we can just delete those guards. That allows us to write
the rules in a more straightforward way.
Fixes#7999.
Co-authored-by: Trevor Elliott <telliott@fastly.com>
Co-authored-by: L Pereira <l.pereira@fastly.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
This commit is an implementation of #7860 for Wasmtime where
`wasmtime::component::Linker` is now "semver aware". This means that it
assumes that hosts are always managing WIT interfaces in a
semver-aare fashion meaning that semver-compatible upgrade exclusively
adds functionality. This neatly fits into the idea of subtyping at the
instance-level where if a binary built against 0.2.0 only requests a
subset of functionality from a runtime that provides 0.2.1, that should
work just fine.
Specifically what this change does is:
* For all names inserted into a `Linker` there might also be a "semver
compatible name" which is registered as well. For example `..@1.0.0`
is also registered as `..@1`.
* Semver-compatible names are only provided for versions without a
prerelease and with either a nonzero major or minor version number.
* When looking up an item in the linker if no exact match is found then
if a semver-compatible-name is available for the lookup key then
that's consulted as well.
This semantically means that if a components imports WASI 0.2.0 then a
runtime which only provides WASI 0.2.1 will be able to instantiate the
component. Furthermore if a component imports WASI 0.2.1 but only
imports the subset of WASI that was available in 0.2.0 then it will be
instantiable in a runtime that only supports 0.2.0.
This implementation is intended to be a crucial part of the evolution to
WASI to make it more seamless to upgrade WASI from both a host and guest
perspective. This no longer requires everyone to upgrade to the same
version all at the same time but instead decouples the upgrade
schedules.
Closes#7860
* winch: Fix bounds checks for dynamic heaps
This commit fixes a fuzz bug in which the current implementation was incorrectly cloberring the index register of a memory access (for addition overflow check) and then using that same clobbered register to perform the memory access. The clobbered register contained the value: `index + offset + access_size`, which resulting in an incorrect access and consequently in an incorrect `HeapOutOfBounds` trap.
This bug is only reproducible when modifying Wasmtime's memory settings, forcing the heap to be treated as `Dynamic`.
Currently in Winch there's no easy way to have specific Wasmtime configurations, so having a filetests for this case is not straightforward. I've opted to add an integration test, in which it's easier to configure Wasmtime.
Note that the `tests/all/winch.rs` file is temporary, and the plan is to execute all the other integration tests with Winch at some point. In the case of `memory.rs`, that will be once Winch supports `memory64` hoping to reduce the amount of code needed in order to integrate Winch.
* Remove unused variable in integration tests