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