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