wasmtime/runtime/component/
store.rs

1#[cfg(feature = "component-model-async")]
2use crate::runtime::vm::VMStore;
3use crate::runtime::vm::component::{ComponentInstance, OwnedComponentInstance};
4use crate::store::{StoreData, StoreId, StoreOpaque};
5#[cfg(feature = "component-model-async")]
6use alloc::vec::Vec;
7use core::pin::Pin;
8use wasmtime_environ::PrimaryMap;
9
10#[derive(Default)]
11pub struct ComponentStoreData {
12    instances: PrimaryMap<ComponentInstanceId, Option<OwnedComponentInstance>>,
13}
14
15#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16pub struct ComponentInstanceId(u32);
17wasmtime_environ::entity_impl!(ComponentInstanceId);
18
19impl StoreData {
20    pub(crate) fn push_component_instance(
21        &mut self,
22        data: OwnedComponentInstance,
23    ) -> ComponentInstanceId {
24        let expected = data.get().id();
25        let ret = self.components.instances.push(Some(data));
26        assert_eq!(expected, ret);
27        ret
28    }
29}
30
31impl ComponentStoreData {
32    pub fn next_component_instance_id(&self) -> ComponentInstanceId {
33        self.instances.next_key()
34    }
35
36    #[cfg(feature = "component-model-async")]
37    pub(crate) fn drop_fibers_and_futures(store: &mut dyn VMStore) {
38        let mut fibers = Vec::new();
39        let mut futures = Vec::new();
40        store
41            .concurrent_state_mut()
42            .take_fibers_and_futures(&mut fibers, &mut futures);
43
44        for mut fiber in fibers {
45            fiber.dispose(store);
46        }
47
48        crate::component::concurrent::tls::set(store, move || drop(futures));
49    }
50
51    #[cfg(feature = "component-model-async")]
52    pub(crate) fn assert_instance_states_empty(&mut self) {
53        for (_, instance) in self.instances.iter_mut() {
54            let Some(instance) = instance.as_mut() else {
55                continue;
56            };
57
58            assert!(
59                instance
60                    .get_mut()
61                    .instance_states()
62                    .0
63                    .iter_mut()
64                    .all(|(_, state)| state.handle_table().is_empty()
65                        && state.concurrent_state().pending_is_empty())
66            );
67        }
68    }
69}
70
71impl StoreData {
72    pub(crate) fn component_instance(&self, id: ComponentInstanceId) -> &ComponentInstance {
73        self.components.instances[id].as_ref().unwrap().get()
74    }
75
76    pub(crate) fn component_instance_mut(
77        &mut self,
78        id: ComponentInstanceId,
79    ) -> Pin<&mut ComponentInstance> {
80        self.components.instances[id].as_mut().unwrap().get_mut()
81    }
82}
83
84impl StoreOpaque {
85    pub(crate) fn component_instance(&self, id: ComponentInstanceId) -> &ComponentInstance {
86        self.store_data().component_instance(id)
87    }
88}
89
90/// A type used to represent an allocated `ComponentInstance` located within a
91/// store.
92///
93/// This type is held in various locations as a "safe index" into a store. This
94/// encapsulates a `StoreId` which owns the instance as well as the index within
95/// the store's list of which instance it's pointing to.
96///
97/// This type can notably be used to index into a `StoreOpaque` to project out
98/// the `ComponentInstance` that is associated with this id.
99#[repr(C)] // used by reference in the C API
100#[derive(Copy, Clone, Debug, PartialEq, Eq)]
101pub struct StoreComponentInstanceId {
102    store_id: StoreId,
103    instance: ComponentInstanceId,
104}
105
106impl StoreComponentInstanceId {
107    pub(crate) fn new(
108        store_id: StoreId,
109        instance: ComponentInstanceId,
110    ) -> StoreComponentInstanceId {
111        StoreComponentInstanceId { store_id, instance }
112    }
113
114    #[inline]
115    pub fn assert_belongs_to(&self, store: StoreId) {
116        self.store_id.assert_belongs_to(store)
117    }
118
119    #[inline]
120    pub(crate) fn store_id(&self) -> StoreId {
121        self.store_id
122    }
123
124    #[inline]
125    pub(crate) fn instance(&self) -> ComponentInstanceId {
126        self.instance
127    }
128
129    /// Looks up the `vm::ComponentInstance` within `store` that this id points
130    /// to.
131    ///
132    /// # Panics
133    ///
134    /// Panics if `self` does not belong to `store`.
135    pub(crate) fn get<'a>(&self, store: &'a StoreOpaque) -> &'a ComponentInstance {
136        self.assert_belongs_to(store.id());
137        store.component_instance(self.instance)
138    }
139
140    /// Mutable version of `get` above.
141    ///
142    /// # Panics
143    ///
144    /// Panics if `self` does not belong to `store`.
145    pub(crate) fn get_mut<'a>(&self, store: &'a mut StoreOpaque) -> Pin<&'a mut ComponentInstance> {
146        self.from_data_get_mut(store.store_data_mut())
147    }
148
149    /// Return a mutable `ComponentInstance` and a `ModuleRegistry`
150    /// from the store.
151    ///
152    /// # Panics
153    ///
154    /// Panics if `self` does not belong to `store`.
155    #[cfg(feature = "component-model-async")]
156    pub(crate) fn get_mut_and_registry<'a>(
157        &self,
158        store: &'a mut StoreOpaque,
159    ) -> (
160        Pin<&'a mut ComponentInstance>,
161        &'a crate::module::ModuleRegistry,
162    ) {
163        let (store_data, registry) = store.store_data_mut_and_registry();
164        let instance = self.from_data_get_mut(store_data);
165        (instance, registry)
166    }
167
168    /// Same as `get_mut`, but borrows less of a store.
169    pub(crate) fn from_data_get_mut<'a>(
170        &self,
171        store: &'a mut StoreData,
172    ) -> Pin<&'a mut ComponentInstance> {
173        self.assert_belongs_to(store.id());
174        store.component_instance_mut(self.instance)
175    }
176}