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