wasmer_wasix/state/linker/instance_group/
table.rs1use tracing::trace;
2use wasmer::{AsStoreMut, Function, RuntimeError, Value};
3
4use super::{InstanceGroupState, LinkError, LinkerState, ModuleHandle};
5
6impl InstanceGroupState {
7 pub(in crate::state::linker) fn allocate_function_table(
11 &mut self,
12 store: &mut impl AsStoreMut,
13 table_size: u32,
14 table_alignment: u32,
15 ) -> Result<u64, RuntimeError> {
16 trace!(table_size, "Allocating table indices");
17
18 let base_index = if table_size == 0 {
19 0
20 } else {
21 let current_size = self.indirect_function_table.size(store);
22 let alignment = 2_u32.pow(table_alignment);
23
24 let offset = if !current_size.is_multiple_of(alignment) {
25 alignment - (current_size % alignment)
26 } else {
27 0
28 };
29
30 let delta = table_size + offset;
31 trace!(?current_size, ?delta, "Growing indirect function table");
32 let start = self
33 .indirect_function_table
34 .grow(store, delta, Value::FuncRef(None))?;
35
36 (start + offset) as u64
37 };
38
39 trace!(
40 base_index,
41 new_table_size = ?self.indirect_function_table.size(store),
42 "Allocated table indices"
43 );
44
45 Ok(base_index)
46 }
47
48 pub(in crate::state::linker) fn append_to_function_table(
49 &self,
50 store: &mut impl AsStoreMut,
51 func: Function,
52 ) -> Result<u32, RuntimeError> {
53 let table = &self.indirect_function_table;
54
55 let ty = func.ty(store).to_string();
56 let index: u32 = table.size(store);
57 trace!(?index, ?ty, "Appending function in table");
58
59 table.grow(store, 1, func.into())
60 }
61
62 pub(super) fn place_in_function_table_at(
63 &self,
64 store: &mut impl AsStoreMut,
65 func: Function,
66 index: u32,
67 ) -> Result<(), RuntimeError> {
68 trace!(
69 ?index,
70 ?func,
71 "Placing function in table at pre-defined index"
72 );
73
74 let table = &self.indirect_function_table;
75 let size = table.size(store);
76
77 if size <= index {
78 let delta = index - size + 1;
79 trace!(
80 current_size = ?size,
81 ?delta,
82 "Growing indirect function table"
83 );
84 table.grow(store, delta, Value::FuncRef(None))?;
85 } else {
86 let existing = table.get(store, index).unwrap();
87 if let Value::FuncRef(Some(_)) = existing {
88 panic!("Internal error: function table index {index} already occupied");
89 }
90 }
91
92 let ty = func.ty(store).to_string();
93 trace!(?index, ?ty, "Placing function in table at index");
94 table.set(store, index, Value::FuncRef(Some(func)))
95 }
96
97 pub(super) fn allocate_function_table_for_existing_module(
98 &mut self,
99 linker_state: &LinkerState,
100 store: &mut impl AsStoreMut,
101 module_handle: ModuleHandle,
102 ) -> Result<(), LinkError> {
103 if self.side_instances.contains_key(&module_handle) {
104 panic!(
105 "Internal error: Module with handle {module_handle:?} \
106 was already instantiated in this group"
107 )
108 };
109
110 let dl_module = linker_state
111 .side_modules
112 .get(&module_handle)
113 .expect("Internal error: module not loaded into linker");
114
115 let table_base = self
116 .allocate_function_table(
117 store,
118 dl_module.dylink_info.mem_info.table_size,
119 dl_module.dylink_info.mem_info.table_alignment,
120 )
121 .map_err(LinkError::TableAllocationError)?;
122
123 if table_base != dl_module.table_base {
124 panic!("Internal error: table base out of sync with linker state");
125 }
126
127 trace!(table_base, "Allocated table indices for existing module");
128
129 Ok(())
130 }
131
132 pub(super) fn apply_resolved_function(
133 &self,
134 store: &mut impl AsStoreMut,
135 name: &str,
136 resolved_from: ModuleHandle,
137 function_table_index: u32,
138 ) -> Result<(), LinkError> {
139 trace!(
140 ?name,
141 ?resolved_from,
142 function_table_index,
143 "Applying resolved function"
144 );
145
146 let instance = &self.try_instance(resolved_from).unwrap_or_else(|| {
147 panic!("Internal error: module {resolved_from:?} not loaded by this group")
148 });
149
150 let func = instance.exports.get_function(name).unwrap_or_else(|e| {
151 panic!("Internal error: failed to resolve exported function {name}: {e:?}")
152 });
153
154 self.place_in_function_table_at(store, func.clone(), function_table_index)
155 .map_err(LinkError::TableAllocationError)?;
156
157 Ok(())
158 }
159
160 pub(super) fn apply_function_table_allocation(
161 &mut self,
162 store: &mut impl AsStoreMut,
163 index: u32,
164 size: u32,
165 ) -> Result<(), LinkError> {
166 trace!(index, "Applying function table allocation");
167 let allocated_index = self
168 .allocate_function_table(store, size, 0)
169 .map_err(LinkError::TableAllocationError)? as u32;
170 if allocated_index != index {
171 panic!(
172 "Internal error: allocated index {allocated_index} does not match expected index {index}"
173 );
174 }
175 Ok(())
176 }
177}