Stream: git-wasmtime

Topic: wasmtime / issue #6848 Get instance data in host defined ...


view this post on Zulip Wasmtime GitHub notifications bot (Aug 15 2023 at 08:30):

bobogei81123 opened issue #6848:

Feature

Provide instance (Instance struct) or instance data to host defined functions in component model.

Benefit

In #2491, it is suggested to bind the instance data to the closure passed to Func::wrap to store per-instance data. However, this will not work for instances in component model because to bind a function (let host export a function to be called by guests), one need to configure LinkerInstance (e.g., use LinkerInstance::func_wrap or similar methods). Yet, there is only a single linker set up for instantiating all the instances in a store, so there is no way to configure per-instance data.

Providing host function instance and instance data will let host function able to get data tied to the instance that calls the function, or let host perform a nested call to a guest function, etc.

Implementation

I think a possible implementation is to let the function passed to LinkerInstance::func_wrap to be able to take Caller instead of StoreContextMut. The non-component model counterpart Func::wrap takes AsContextMut to achieve this, and I'm not sure why func_wrap takes StoreContextMut instead. Then, we can expose the instance stored in the Caller struct. Of course, this all rely on the assumption that Caller can be retrieve in calls to component host.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 18 2023 at 15:07):

alexcrichton commented on issue #6848:

You mention that a single linker is used for a store, but that's not quite accurate because you can use any number of linkers to instantiate within a Store. In that sense you can still provide per-function state within the Linker. Otherwise though I'll also note that the question there was in reference to the C API and the Rust API is a bit different. In Rust the closures in Linker are Fn meaning you don't get mutable access to closed-over-state. Instead that sort of information typically goes within the T of a Store<T> which you do get mutable access to.

So, if possible, the recommendation is to store per-instance information into a T in Store<T> and only if necessary store per-instance information within the closures passed to a Linker. Does that work for you?

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2023 at 08:27):

bobogei81123 commented on issue #6848:

I'll also note that the question there was in reference to the C API and the Rust API is a bit different.

Sorry for not stating the question clearly. I'm using the rust API. Otherwise

So, if possible, the recommendation is to store per-instance information into a T in Store<T> and only if necessary store per-instance information within the closures passed to a Linker. Does that work for you?

I'm a little bit confused here because I thought there can be multiple instances inside a single store. My setup is as follows:
First I create a global Engine and Store:

fn init() {
  engine = Engine::new(config)?;
  store = Store::new(...);
  linker = Linker::new(&engine);
  MyWasmWorld::add_to_linker(&mut linker, ...)?;
  ...
}

Then, when a plugin (guest program) is loaded, I load the wasm file and instantiate the component

fn load_plugin_from_path(file_path: &str) {
  Component::from_file(engine, file_path)?;
  let (_, instance) = MyWasmWorld::instantiate(&mut store, &component, &linker)?;
  ...
}

My understanding is that load_plugin_from_path can be called multiple time to instantiate multiple plugins in the same store, so I'll need a way to identify which instance is calling the host function.

Or should I use multiple stores for different plugins? But even then, I still need to get the Instance handle to get its exports so I cn call guest functions or inspect its memory, is that correct?

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2023 at 08:32):

bobogei81123 commented on issue #6848:

Oh, I think I get what you are suggesting, I can create one linker each time I instantiate a plugin. Let me try if that works.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2023 at 15:09):

alexcrichton commented on issue #6848:

Ah yes it's possible to put lots of instances in the same store. The downside of that approach is that you can't incrementally delete instances within the store, it's an all-or-nothing operation (e.g. you can't unload just one plugin, you'd have to unload all of them).

If possible I'd recommend having a Store-per-plugin. With the component abstraction it's not actually necessary to have everything in one store as that's primarily there for core wasm instance linking and shared memory, which the component model doesn't support.

Storing state per-linker would still work, however, if that works for you!


Last updated: Oct 23 2024 at 20:03 UTC