Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement calling a "dynamically typed" API in the component model #4310

Closed
Tracked by #4185
alexcrichton opened this issue Jun 23, 2022 · 4 comments
Closed
Tracked by #4185
Labels
wasm-proposal:component-model Issues related to the WebAssembly Component Model proposal

Comments

@alexcrichton
Copy link
Member

For core wasm Wasmtime offers the Func and TypedFunc APIs for calling into WebAssembly. The current intention is to provide the same for the component model. Currently the TypedFunc API exists, but the Func API doesn't actually support calls.

The intended use case for this feature is for something like the wasmtime CLI where it wants to be able to call any component it loads so we can't statically enumerate the signatures ahead of time. It's expected that this version of calling a component is slower (perhaps significantly so) than calling a typed function.

Currently I don't have many ideas about how the implementation will be done. The rough idea is that there'd be some sort of wasmtime::Val equivalent but for the component model. Like with Val the actual value iteslf is "tagged" with the type information. The actual implementation of this is going to be much trickier than core wasm because Val only deals with primitives and a component model value can recursively contain other component model values. This will likely imply a significant overhead in terms of allocations, indirection, and management.

I do not think that the wasmtime::component::Val type will implement any of ComponentValue, Lift, or Lower. Those are intended only for types where the type in the component model is statically known at compile-time.

This work is also motivated by unlocking half of the fuzzing possiblities in #4307

@alexcrichton alexcrichton added the wasm-proposal:component-model Issues related to the WebAssembly Component Model proposal label Jun 23, 2022
@alexcrichton
Copy link
Member Author

One other thing worth mentioning here is that the support here not only applies to wasmtime::component::Func but also the wasmtime::component::Linker type. Ideally a host function can be defined generically with a runtime-defined signature which allows other interesting forms of fuzzing and such. My hope would be that if untyped values work in Func it would be relatively easy to add support to Linker to do the same thing.

@dicej
Copy link
Contributor

dicej commented Jul 8, 2022

I'm going to start experimenting with this today.

@dicej
Copy link
Contributor

dicej commented Jul 13, 2022

Quick update: I've mostly finished with this -- just fleshing out the test suite. Should have a PR up today.

dicej added a commit to dicej/wasmtime that referenced this issue Jul 13, 2022
This addresses bytecodealliance#4310, introducing a new `component::values::Val` type for
representing component values dynamically.  It also adds a `call` method to
`component::func::Func`, which takes a slice of `Val`s as parameters and returns
a `Result<Val>` representing the result.

As an implementation detail, I've also added a `component::values::Type` type,
which is an owned, despecialized version of
`wasmtime_environ::component::InterfaceType`.  That serves two purposes:

- It allows us to despecialize as the first step, which reduces the number of cases to consider when typechecking and lowering.
- It avoids needing to borrow the store both mutably and immutably when lowering, as we would if we used `InterfaceType`s.

Finally, I happened to notice that the `ComponentType::SIZE32` calculation in
`expand_record_for_component_type` needed a correction, so I did that.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit to dicej/wasmtime that referenced this issue Jul 13, 2022
This addresses bytecodealliance#4310, introducing a new `component::values::Val` type for
representing component values dynamically.  It also adds a `call` method to
`component::func::Func`, which takes a slice of `Val`s as parameters and returns
a `Result<Val>` representing the result.

As an implementation detail, I've also added a `component::values::Type` type,
which is an owned, despecialized version of
`wasmtime_environ::component::InterfaceType`.  That serves two purposes:

- It allows us to despecialize as the first step, which reduces the number of cases to consider when typechecking and lowering.
- It avoids needing to borrow the store both mutably and immutably when lowering, as we would if we used `InterfaceType`s.

Finally, I happened to notice that the `ComponentType::SIZE32` calculation in
`expand_record_for_component_type` needed a correction, so I did that.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
dicej added a commit to dicej/wasmtime that referenced this issue Jul 21, 2022
This addresses bytecodealliance#4310, introducing a new `component::values::Val` type for
representing component values dynamically, as well as `component::types::Type`
for representing the corresponding interface types. It also adds a `call` method
to `component::func::Func`, which takes a slice of `Val`s as parameters and
returns a `Result<Val>` representing the result.

Note that I've moved `post_return` and `call_raw` from `TypedFunc` to `Func`
since there was nothing specific to `TypedFunc` about them, and I wanted to
reuse them.  The code in both is unchanged beyond the trivial tweaks to make
them fit in their new home.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
alexcrichton pushed a commit that referenced this issue Jul 25, 2022
* support dynamic function calls in component model

This addresses #4310, introducing a new `component::values::Val` type for
representing component values dynamically, as well as `component::types::Type`
for representing the corresponding interface types. It also adds a `call` method
to `component::func::Func`, which takes a slice of `Val`s as parameters and
returns a `Result<Val>` representing the result.

Note that I've moved `post_return` and `call_raw` from `TypedFunc` to `Func`
since there was nothing specific to `TypedFunc` about them, and I wanted to
reuse them.  The code in both is unchanged beyond the trivial tweaks to make
them fit in their new home.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* order variants and match cases more consistently

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* implement lift for String, Box<str>, etc.

This also removes the redundant `store` parameter from `Type::load`.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* implement code review feedback

This fixes a few issues:

- Bad offset calculation when lowering
- Missing variant padding
- Style issues regarding `types::Handle`
- Missed opportunities to reuse `Lift` and `Lower` impls

It also adds forwarding `Lift` impls for `Box<[T]>`, `Vec<T>`, etc.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* move `new_*` methods to specific `types` structs

Per review feedback, I've moved `Type::new_record` to `Record::new_val` and
added a `Type::unwrap_record` method; likewise for the other kinds of types.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* make tuple, option, and expected type comparisons recursive

These types should compare as equal across component boundaries as long as their
type parameters are equal.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* improve error diagnostic in `Type::check`

We now distinguish between more failure cases to provide an informative error
message.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* address review feedback

- Remove `WasmStr::to_str_from_memory` and `WasmList::get_from_memory`
- add `try_new` methods to various `values` types
- avoid using `ExactSizeIterator::len` where we can't trust it
- fix over-constrained bounds on forwarded `ComponentType` impls

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* rearrange code per review feedback

- Move functions from `types` to `values` module so we can make certain struct fields private
- Rename `try_new` to just `new`

Signed-off-by: Joel Dice <joel.dice@fermyon.com>

* remove special-case equality test for tuples, options, and expecteds

Instead, I've added a FIXME comment and will open an issue to do recursive
structural equality testing.

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
@alexcrichton
Copy link
Member Author

Implemented in #4442

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasm-proposal:component-model Issues related to the WebAssembly Component Model proposal
Projects
None yet
Development

No branches or pull requests

2 participants