Skip to content

Commit d8360be

Browse files
authored
wasmtime-environ: add initial table support (#10497)
* wasmtime-environ: add initial table support In order to lower the [`thread.spawn_indirect`] canonical builtin from the component model, we need to be able to refer to the tables exported from instance. This change adds the initial plumbing to access such tables. [`thread.spawn_indirect`]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#-canon-threadspawn_indirect * review: add missing doc comment * review: add missing field calculation * review: fix a return type * fix: gate `pub use` behind component-model feature
1 parent 8385bea commit d8360be

File tree

9 files changed

+119
-11
lines changed

9 files changed

+119
-11
lines changed

crates/environ/src/component/dfg.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ macro_rules! id {
175175
id! {
176176
pub struct InstanceId(u32);
177177
pub struct MemoryId(u32);
178+
pub struct TableId(u32);
178179
pub struct ReallocId(u32);
179180
pub struct CallbackId(u32);
180181
pub struct AdapterId(u32);
@@ -497,6 +498,7 @@ impl ComponentDfg {
497498
dfg: &self,
498499
initializers: Vec::new(),
499500
runtime_memories: Default::default(),
501+
runtime_tables: Default::default(),
500502
runtime_post_return: Default::default(),
501503
runtime_reallocs: Default::default(),
502504
runtime_callbacks: Default::default(),
@@ -538,6 +540,7 @@ impl ComponentDfg {
538540
num_lowerings: linearize.num_lowerings,
539541

540542
num_runtime_memories: linearize.runtime_memories.len() as u32,
543+
num_runtime_tables: linearize.runtime_tables.len() as u32,
541544
num_runtime_post_returns: linearize.runtime_post_return.len() as u32,
542545
num_runtime_reallocs: linearize.runtime_reallocs.len() as u32,
543546
num_runtime_callbacks: linearize.runtime_callbacks.len() as u32,
@@ -574,6 +577,7 @@ struct LinearizeDfg<'a> {
574577
trampoline_defs: PrimaryMap<TrampolineIndex, info::Trampoline>,
575578
trampoline_map: HashMap<TrampolineIndex, TrampolineIndex>,
576579
runtime_memories: HashMap<MemoryId, RuntimeMemoryIndex>,
580+
runtime_tables: HashMap<TableId, RuntimeTableIndex>,
577581
runtime_reallocs: HashMap<ReallocId, RuntimeReallocIndex>,
578582
runtime_callbacks: HashMap<CallbackId, RuntimeCallbackIndex>,
579583
runtime_post_return: HashMap<PostReturnId, RuntimePostReturnIndex>,

crates/environ/src/component/info.rs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ pub struct Component {
141141
/// stored in two different locations).
142142
pub num_runtime_memories: u32,
143143

144+
/// The number of runtime tables (maximum `RuntimeTableIndex`) needed to
145+
/// instantiate this component. See notes on `num_runtime_memories`.
146+
pub num_runtime_tables: u32,
147+
144148
/// The number of runtime reallocs (maximum `RuntimeReallocIndex`) needed to
145149
/// instantiate this component.
146150
///
@@ -215,10 +219,11 @@ impl Component {
215219
}
216220
}
217221

218-
/// GlobalInitializer instructions to get processed when instantiating a component
222+
/// GlobalInitializer instructions to get processed when instantiating a
223+
/// component.
219224
///
220-
/// The variants of this enum are processed during the instantiation phase of
221-
/// a component in-order from front-to-back. These are otherwise emitted as a
225+
/// The variants of this enum are processed during the instantiation phase of a
226+
/// component in-order from front-to-back. These are otherwise emitted as a
222227
/// component is parsed and read and translated.
223228
//
224229
// FIXME(#2639) if processing this list is ever a bottleneck we could
@@ -257,11 +262,10 @@ pub enum GlobalInitializer {
257262
/// A core wasm linear memory is going to be saved into the
258263
/// `VMComponentContext`.
259264
///
260-
/// This instruction indicates that the `index`th core wasm linear memory
261-
/// needs to be extracted from the `export` specified, a pointer to a
262-
/// previously created module instance, and stored into the
263-
/// `VMComponentContext` at the `index` specified. This lowering is then
264-
/// used in the future by pointers from `CanonicalOptions`.
265+
/// This instruction indicates that a core wasm linear memory needs to be
266+
/// extracted from the `export` and stored into the `VMComponentContext` at
267+
/// the `index` specified. This lowering is then used in the future by
268+
/// pointers from `CanonicalOptions`.
265269
ExtractMemory(ExtractMemory),
266270

267271
/// Same as `ExtractMemory`, except it's extracting a function pointer to be
@@ -276,14 +280,24 @@ pub enum GlobalInitializer {
276280
/// used as a `post-return` function.
277281
ExtractPostReturn(ExtractPostReturn),
278282

283+
/// A core wasm table is going to be saved into the `VMComponentContext`.
284+
///
285+
/// This instruction indicates that s core wasm table needs to be extracted
286+
/// from its `export` and stored into the `VMComponentContext` at the
287+
/// `index` specified. During this extraction, we will also capture the
288+
/// table's containing instance pointer to access the table at runtime. This
289+
/// extraction is useful for `thread.spawn_indirect`.
290+
ExtractTable(ExtractTable),
291+
279292
/// Declares a new defined resource within this component.
280293
///
281294
/// Contains information about the destructor, for example.
282295
Resource(Resource),
283296
}
284297

285-
/// Metadata for extraction of a memory of what's being extracted and where it's
286-
/// going.
298+
/// Metadata for extraction of a memory; contains what's being extracted (the
299+
/// memory at `export`) and where it's going (the `index` within a
300+
/// `VMComponentContext`).
287301
#[derive(Debug, Serialize, Deserialize)]
288302
pub struct ExtractMemory {
289303
/// The index of the memory being defined.
@@ -319,6 +333,15 @@ pub struct ExtractPostReturn {
319333
pub def: CoreDef,
320334
}
321335

336+
/// Metadata for extraction of a table.
337+
#[derive(Debug, Serialize, Deserialize)]
338+
pub struct ExtractTable {
339+
/// The index of the table being defined in a `VMComponentContext`.
340+
pub index: RuntimeTableIndex,
341+
/// Where this table is being extracted from.
342+
pub export: CoreExport<TableIndex>,
343+
}
344+
322345
/// Different methods of instantiating a core wasm module.
323346
#[derive(Debug, Serialize, Deserialize)]
324347
pub enum InstantiateModule {

crates/environ/src/component/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ indices! {
222222
/// Same as `RuntimeMemoryIndex` except for the `post-return` function.
223223
pub struct RuntimePostReturnIndex(u32);
224224

225+
/// Index representing a table extracted from a wasm instance which is
226+
/// stored in a `VMComponentContext`. This is used to deduplicate references
227+
/// to the same table when it's only stored once in a `VMComponentContext`.
228+
///
229+
/// This does not correspond to anything in the binary format for the
230+
/// component model.
231+
pub struct RuntimeTableIndex(u32);
232+
225233
/// Index for all trampolines that are compiled in Cranelift for a
226234
/// component.
227235
///

crates/environ/src/component/vmcomponent_offsets.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// trampoline_func_refs: [VMFuncRef; component.num_trampolines],
99
// lowerings: [VMLowering; component.num_lowerings],
1010
// memories: [*mut VMMemoryDefinition; component.num_runtime_memories],
11+
// tables: [*mut VMTableDefinition; component.num_runtime_tables],
1112
// reallocs: [*mut VMFuncRef; component.num_runtime_reallocs],
1213
// post_returns: [*mut VMFuncRef; component.num_runtime_post_returns],
1314
// resource_destructors: [*mut VMFuncRef; component.num_resources],
@@ -44,6 +45,8 @@ pub struct VMComponentOffsets<P> {
4445
pub num_lowerings: u32,
4546
/// The number of memories which are recorded in this component for options.
4647
pub num_runtime_memories: u32,
48+
/// The number of tables which are recorded in this component for options.
49+
pub num_runtime_tables: u32,
4750
/// The number of reallocs which are recorded in this component for options.
4851
pub num_runtime_reallocs: u32,
4952
/// The number of callbacks which are recorded in this component for options.
@@ -66,6 +69,7 @@ pub struct VMComponentOffsets<P> {
6669
trampoline_func_refs: u32,
6770
lowerings: u32,
6871
memories: u32,
72+
tables: u32,
6973
reallocs: u32,
7074
callbacks: u32,
7175
post_returns: u32,
@@ -87,6 +91,7 @@ impl<P: PtrSize> VMComponentOffsets<P> {
8791
ptr,
8892
num_lowerings: component.num_lowerings,
8993
num_runtime_memories: component.num_runtime_memories.try_into().unwrap(),
94+
num_runtime_tables: component.num_runtime_tables.try_into().unwrap(),
9095
num_runtime_reallocs: component.num_runtime_reallocs.try_into().unwrap(),
9196
num_runtime_callbacks: component.num_runtime_callbacks.try_into().unwrap(),
9297
num_runtime_post_returns: component.num_runtime_post_returns.try_into().unwrap(),
@@ -103,6 +108,7 @@ impl<P: PtrSize> VMComponentOffsets<P> {
103108
trampoline_func_refs: 0,
104109
lowerings: 0,
105110
memories: 0,
111+
tables: 0,
106112
reallocs: 0,
107113
callbacks: 0,
108114
post_returns: 0,
@@ -145,6 +151,7 @@ impl<P: PtrSize> VMComponentOffsets<P> {
145151
size(trampoline_func_refs) = cmul(ret.num_trampolines, ret.ptr.size_of_vm_func_ref()),
146152
size(lowerings) = cmul(ret.num_lowerings, ret.ptr.size() * 2),
147153
size(memories) = cmul(ret.num_runtime_memories, ret.ptr.size()),
154+
size(tables) = cmul(ret.num_runtime_tables, ret.ptr.size()),
148155
size(reallocs) = cmul(ret.num_runtime_reallocs, ret.ptr.size()),
149156
size(callbacks) = cmul(ret.num_runtime_callbacks, ret.ptr.size()),
150157
size(post_returns) = cmul(ret.num_runtime_post_returns, ret.ptr.size()),
@@ -262,6 +269,20 @@ impl<P: PtrSize> VMComponentOffsets<P> {
262269
self.runtime_memories() + index.as_u32() * u32::from(self.ptr.size())
263270
}
264271

272+
/// The offset of the base of the `runtime_tables` field
273+
#[inline]
274+
pub fn runtime_tables(&self) -> u32 {
275+
self.tables
276+
}
277+
278+
/// The offset of the `*mut VMTableDefinition` for the runtime index
279+
/// provided.
280+
#[inline]
281+
pub fn runtime_table(&self, index: RuntimeTableIndex) -> u32 {
282+
assert!(index.as_u32() < self.num_runtime_tables);
283+
self.runtime_tables() + index.as_u32() * u32::from(self.ptr.size())
284+
}
285+
265286
/// The offset of the base of the `runtime_reallocs` field
266287
#[inline]
267288
pub fn runtime_reallocs(&self) -> u32 {

crates/wasmtime/src/runtime/component/component.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ impl Component {
623623
},
624624
GlobalInitializer::LowerImport { .. }
625625
| GlobalInitializer::ExtractMemory(_)
626+
| GlobalInitializer::ExtractTable(_)
626627
| GlobalInitializer::ExtractRealloc(_)
627628
| GlobalInitializer::ExtractCallback(_)
628629
| GlobalInitializer::ExtractPostReturn(_)

crates/wasmtime/src/runtime/component/instance.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ impl<'a> Instantiator<'a> {
601601
self.data.state.set_lowering(*index, func.lowering());
602602
}
603603

604+
GlobalInitializer::ExtractTable(table) => self.extract_table(store.0, table),
605+
604606
GlobalInitializer::ExtractMemory(mem) => self.extract_memory(store.0, mem),
605607

606608
GlobalInitializer::ExtractRealloc(realloc) => {
@@ -678,6 +680,16 @@ impl<'a> Instantiator<'a> {
678680
.set_runtime_post_return(post_return.index, func_ref);
679681
}
680682

683+
fn extract_table(&mut self, store: &mut StoreOpaque, table: &ExtractTable) {
684+
let export = match self.data.lookup_export(store, &table.export) {
685+
crate::runtime::vm::Export::Table(t) => t,
686+
_ => unreachable!(),
687+
};
688+
self.data
689+
.state
690+
.set_runtime_table(table.index, export.definition);
691+
}
692+
681693
fn build_imports<'b>(
682694
&mut self,
683695
store: &mut StoreOpaque,

crates/wasmtime/src/runtime/vm.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ pub use crate::runtime::vm::sys::unwind::UnwindRegistration;
9090
pub use crate::runtime::vm::table::{Table, TableElement};
9191
pub use crate::runtime::vm::traphandlers::*;
9292
pub use crate::runtime::vm::unwind::*;
93+
#[cfg(feature = "component-model")]
94+
pub use crate::runtime::vm::vmcontext::VMTableDefinition;
9395
pub use crate::runtime::vm::vmcontext::{
9496
VMArrayCallFunction, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMFunctionBody,
9597
VMFunctionImport, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport,

crates/wasmtime/src/runtime/vm/component.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
use crate::prelude::*;
1010
use crate::runtime::vm::{
1111
SendSyncPtr, VMArrayCallFunction, VMFuncRef, VMGlobalDefinition, VMMemoryDefinition,
12-
VMOpaqueContext, VMStore, VMStoreRawPtr, VMWasmCallFunction, ValRaw, VmPtr, VmSafe,
12+
VMOpaqueContext, VMStore, VMStoreRawPtr, VMTableDefinition, VMWasmCallFunction, ValRaw, VmPtr,
13+
VmSafe,
1314
};
1415
use alloc::alloc::Layout;
1516
use alloc::sync::Arc;
@@ -289,6 +290,19 @@ impl ComponentInstance {
289290
}
290291
}
291292

293+
/// Returns the runtime table definition corresponding to the index of the
294+
/// table provided.
295+
///
296+
/// This can only be called after `idx` has been initialized at runtime
297+
/// during the instantiation process of a component.
298+
pub fn runtime_table(&self, idx: RuntimeTableIndex) -> *mut VMTableDefinition {
299+
unsafe {
300+
let ret = *self.vmctx_plus_offset::<VmPtr<_>>(self.offsets.runtime_table(idx));
301+
debug_assert!(ret.as_ptr() as usize != INVALID_PTR);
302+
ret.as_ptr()
303+
}
304+
}
305+
292306
/// Returns the realloc pointer corresponding to the index provided.
293307
///
294308
/// This can only be called after `idx` has been initialized at runtime
@@ -404,6 +418,23 @@ impl ComponentInstance {
404418
}
405419
}
406420

421+
/// Stores the runtime memory pointer at the index specified.
422+
///
423+
/// This is intended to be called during the instantiation process of a
424+
/// component once a memory is available, which may not be until part-way
425+
/// through component instantiation.
426+
///
427+
/// Note that it should be a property of the component model that the `ptr`
428+
/// here is never needed prior to it being configured here in the instance.
429+
pub fn set_runtime_table(&mut self, idx: RuntimeTableIndex, ptr: NonNull<VMTableDefinition>) {
430+
unsafe {
431+
let storage = self
432+
.vmctx_plus_offset_mut::<VmPtr<VMTableDefinition>>(self.offsets.runtime_table(idx));
433+
debug_assert!((*storage).as_ptr() as usize == INVALID_PTR);
434+
*storage = ptr.into();
435+
}
436+
}
437+
407438
/// Configures host runtime lowering information associated with imported f
408439
/// functions for the `idx` specified.
409440
pub fn set_lowering(&mut self, idx: LoweredIndex, lowering: VMLowering) {
@@ -801,6 +832,11 @@ impl OwnedComponentInstance {
801832
unsafe { self.instance_mut().set_runtime_post_return(idx, ptr) }
802833
}
803834

835+
/// See `ComponentInstance::set_runtime_table`
836+
pub fn set_runtime_table(&mut self, idx: RuntimeTableIndex, ptr: NonNull<VMTableDefinition>) {
837+
unsafe { self.instance_mut().set_runtime_table(idx, ptr) }
838+
}
839+
804840
/// See `ComponentInstance::set_lowering`
805841
pub fn set_lowering(&mut self, idx: LoweredIndex, lowering: VMLowering) {
806842
unsafe { self.instance_mut().set_lowering(idx, lowering) }

crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ unsafe impl InstanceAllocatorImpl for PoolingInstanceAllocator {
527527
}
528528
LowerImport { .. }
529529
| ExtractMemory(_)
530+
| ExtractTable(_)
530531
| ExtractRealloc(_)
531532
| ExtractCallback(_)
532533
| ExtractPostReturn(_)

0 commit comments

Comments
 (0)