wasmtime/runtime/vm/instance/allocator/
on_demand.rs1use super::{
2 InstanceAllocationRequest, InstanceAllocator, MemoryAllocationIndex, TableAllocationIndex,
3};
4use crate::prelude::*;
5use crate::runtime::vm::CompiledModuleId;
6use crate::runtime::vm::instance::RuntimeMemoryCreator;
7use crate::runtime::vm::memory::{DefaultMemoryCreator, Memory};
8use crate::runtime::vm::mpk::ProtectionKey;
9use crate::runtime::vm::table::Table;
10use alloc::sync::Arc;
11use wasmtime_environ::{DefinedMemoryIndex, DefinedTableIndex, HostPtr, Module, VMOffsets};
12
13#[cfg(feature = "gc")]
14use crate::runtime::vm::{GcHeap, GcHeapAllocationIndex, GcRuntime};
15
16#[cfg(feature = "async")]
17use wasmtime_fiber::RuntimeFiberStackCreator;
18
19#[cfg(feature = "component-model")]
20use wasmtime_environ::{
21 StaticModuleIndex,
22 component::{Component, VMComponentOffsets},
23};
24
25#[derive(Clone)]
27pub struct OnDemandInstanceAllocator {
28 mem_creator: Option<Arc<dyn RuntimeMemoryCreator>>,
29 #[cfg(feature = "async")]
30 stack_creator: Option<Arc<dyn RuntimeFiberStackCreator>>,
31 #[cfg(feature = "async")]
32 stack_size: usize,
33 #[cfg(feature = "async")]
34 stack_zeroing: bool,
35}
36
37impl OnDemandInstanceAllocator {
38 pub fn new(
40 mem_creator: Option<Arc<dyn RuntimeMemoryCreator>>,
41 stack_size: usize,
42 stack_zeroing: bool,
43 ) -> Self {
44 let _ = (stack_size, stack_zeroing); Self {
46 mem_creator,
47 #[cfg(feature = "async")]
48 stack_creator: None,
49 #[cfg(feature = "async")]
50 stack_size,
51 #[cfg(feature = "async")]
52 stack_zeroing,
53 }
54 }
55
56 #[cfg(feature = "async")]
58 pub fn set_stack_creator(&mut self, stack_creator: Arc<dyn RuntimeFiberStackCreator>) {
59 self.stack_creator = Some(stack_creator);
60 }
61}
62
63impl Default for OnDemandInstanceAllocator {
64 fn default() -> Self {
65 Self {
66 mem_creator: None,
67 #[cfg(feature = "async")]
68 stack_creator: None,
69 #[cfg(feature = "async")]
70 stack_size: 0,
71 #[cfg(feature = "async")]
72 stack_zeroing: false,
73 }
74 }
75}
76
77#[async_trait::async_trait]
78unsafe impl InstanceAllocator for OnDemandInstanceAllocator {
79 #[cfg(feature = "component-model")]
80 fn validate_component<'a>(
81 &self,
82 _component: &Component,
83 _offsets: &VMComponentOffsets<HostPtr>,
84 _get_module: &'a dyn Fn(StaticModuleIndex) -> &'a Module,
85 ) -> Result<()> {
86 Ok(())
87 }
88
89 fn validate_module(&self, _module: &Module, _offsets: &VMOffsets<HostPtr>) -> Result<()> {
90 Ok(())
91 }
92
93 #[cfg(feature = "gc")]
94 fn validate_memory(&self, _memory: &wasmtime_environ::Memory) -> Result<()> {
95 Ok(())
96 }
97
98 #[cfg(feature = "component-model")]
99 fn increment_component_instance_count(&self) -> Result<()> {
100 Ok(())
101 }
102
103 #[cfg(feature = "component-model")]
104 fn decrement_component_instance_count(&self) {}
105
106 fn increment_core_instance_count(&self) -> Result<()> {
107 Ok(())
108 }
109
110 fn decrement_core_instance_count(&self) {}
111
112 async fn allocate_memory(
113 &self,
114 request: &mut InstanceAllocationRequest<'_, '_>,
115 ty: &wasmtime_environ::Memory,
116 memory_index: Option<DefinedMemoryIndex>,
117 ) -> Result<(MemoryAllocationIndex, Memory)> {
118 let creator = self
119 .mem_creator
120 .as_deref()
121 .unwrap_or_else(|| &DefaultMemoryCreator);
122
123 let image = if let Some(memory_index) = memory_index {
124 request.runtime_info.memory_image(memory_index)?
125 } else {
126 None
127 };
128
129 let allocation_index = MemoryAllocationIndex::default();
130 let memory = Memory::new_dynamic(
131 ty,
132 request.store.engine().tunables(),
133 creator,
134 image,
135 request.limiter.as_deref_mut(),
136 )
137 .await?;
138 Ok((allocation_index, memory))
139 }
140
141 unsafe fn deallocate_memory(
142 &self,
143 _memory_index: Option<DefinedMemoryIndex>,
144 allocation_index: MemoryAllocationIndex,
145 _memory: Memory,
146 ) {
147 debug_assert_eq!(allocation_index, MemoryAllocationIndex::default());
148 }
150
151 async fn allocate_table(
152 &self,
153 request: &mut InstanceAllocationRequest<'_, '_>,
154 ty: &wasmtime_environ::Table,
155 _table_index: DefinedTableIndex,
156 ) -> Result<(TableAllocationIndex, Table)> {
157 let allocation_index = TableAllocationIndex::default();
158 let table = Table::new_dynamic(
159 ty,
160 request.store.engine().tunables(),
161 request.limiter.as_deref_mut(),
162 )
163 .await?;
164 Ok((allocation_index, table))
165 }
166
167 unsafe fn deallocate_table(
168 &self,
169 _table_index: DefinedTableIndex,
170 allocation_index: TableAllocationIndex,
171 _table: Table,
172 ) {
173 debug_assert_eq!(allocation_index, TableAllocationIndex::default());
174 }
176
177 #[cfg(feature = "async")]
178 fn allocate_fiber_stack(&self) -> Result<wasmtime_fiber::FiberStack> {
179 if self.stack_size == 0 {
180 anyhow::bail!("fiber stacks are not supported by the allocator")
181 }
182 let stack = match &self.stack_creator {
183 Some(stack_creator) => {
184 let stack = stack_creator.new_stack(self.stack_size, self.stack_zeroing)?;
185 wasmtime_fiber::FiberStack::from_custom(stack)
186 }
187 None => wasmtime_fiber::FiberStack::new(self.stack_size, self.stack_zeroing),
188 }?;
189 Ok(stack)
190 }
191
192 #[cfg(feature = "async")]
193 unsafe fn deallocate_fiber_stack(&self, stack: wasmtime_fiber::FiberStack) {
194 let _ = stack;
197 }
198
199 fn purge_module(&self, _: CompiledModuleId) {}
200
201 fn next_available_pkey(&self) -> Option<ProtectionKey> {
202 None
206 }
207
208 fn restrict_to_pkey(&self, _: ProtectionKey) {
209 unreachable!()
213 }
214
215 fn allow_all_pkeys(&self) {
216 unreachable!()
220 }
221
222 #[cfg(feature = "gc")]
223 fn allocate_gc_heap(
224 &self,
225 engine: &crate::Engine,
226 gc_runtime: &dyn GcRuntime,
227 memory_alloc_index: MemoryAllocationIndex,
228 memory: Memory,
229 ) -> Result<(GcHeapAllocationIndex, Box<dyn GcHeap>)> {
230 debug_assert_eq!(memory_alloc_index, MemoryAllocationIndex::default());
231 let mut heap = gc_runtime.new_gc_heap(engine)?;
232 heap.attach(memory);
233 Ok((GcHeapAllocationIndex::default(), heap))
234 }
235
236 #[cfg(feature = "gc")]
237 fn deallocate_gc_heap(
238 &self,
239 allocation_index: GcHeapAllocationIndex,
240 mut gc_heap: Box<dyn crate::runtime::vm::GcHeap>,
241 ) -> (MemoryAllocationIndex, Memory) {
242 debug_assert_eq!(allocation_index, GcHeapAllocationIndex::default());
243 (MemoryAllocationIndex::default(), gc_heap.detach())
244 }
245}