Skip to content

Commit 238ec90

Browse files
authored
Improve table support for components (#10499)
* Fix documentation, add debug check This change cleans up some missing items from #10497: a copy-paste typo and some missing debug assertions about the initial state of the table list in the `VMComponentContext`. * Add missing `VMContext` field for component table use When components access tables, these may lazily initialized. Eventually, we will need to call `Instance::get_defined_table_with_lazy_init` to set up the table immediately prior to use. To do so, this change stores an additional `*mut VMContext` (for a core instance, not a component) in the `VMComponentContext` along with each `*mut VMTableDefinition` so that we can recover the core instance needed for lazy initialization. * Use `VMTableImport` to record component tables To avoid extra structures, this change uses `VMTableImport` everywhere a component would need to keep track of a `VMTableDefinition` and `VMContext` (recall the `VMContext` is needed for lazy initialization). This is a bit awkward since this usage is not truly an import, but perhaps we can change the name later.
1 parent d8360be commit 238ec90

File tree

4 files changed

+71
-24
lines changed

4 files changed

+71
-24
lines changed

crates/environ/src/component/vmcomponent_offsets.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +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],
11+
// tables: [VMTableImport; component.num_runtime_tables],
1212
// reallocs: [*mut VMFuncRef; component.num_runtime_reallocs],
1313
// post_returns: [*mut VMFuncRef; component.num_runtime_post_returns],
1414
// resource_destructors: [*mut VMFuncRef; component.num_resources],
@@ -151,7 +151,7 @@ impl<P: PtrSize> VMComponentOffsets<P> {
151151
size(trampoline_func_refs) = cmul(ret.num_trampolines, ret.ptr.size_of_vm_func_ref()),
152152
size(lowerings) = cmul(ret.num_lowerings, ret.ptr.size() * 2),
153153
size(memories) = cmul(ret.num_runtime_memories, ret.ptr.size()),
154-
size(tables) = cmul(ret.num_runtime_tables, ret.ptr.size()),
154+
size(tables) = cmul(ret.num_runtime_tables, ret.size_of_vmtable_import()),
155155
size(reallocs) = cmul(ret.num_runtime_reallocs, ret.ptr.size()),
156156
size(callbacks) = cmul(ret.num_runtime_callbacks, ret.ptr.size()),
157157
size(post_returns) = cmul(ret.num_runtime_post_returns, ret.ptr.size()),
@@ -275,12 +275,18 @@ impl<P: PtrSize> VMComponentOffsets<P> {
275275
self.tables
276276
}
277277

278-
/// The offset of the `*mut VMTableDefinition` for the runtime index
279-
/// provided.
278+
/// The offset of the table for the runtime index provided.
280279
#[inline]
281280
pub fn runtime_table(&self, index: RuntimeTableIndex) -> u32 {
282281
assert!(index.as_u32() < self.num_runtime_tables);
283-
self.runtime_tables() + index.as_u32() * u32::from(self.ptr.size())
282+
self.runtime_tables() + index.as_u32() * u32::from(self.size_of_vmtable_import())
283+
}
284+
285+
/// Return the size of `VMTableImport`, used here to hold the pointers to
286+
/// the `VMTableDefinition` and `VMContext` (not because this is an import).
287+
#[inline]
288+
pub fn size_of_vmtable_import(&self) -> u8 {
289+
2 * self.pointer_size()
284290
}
285291

286292
/// The offset of the base of the `runtime_reallocs` field

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ impl<'a> Instantiator<'a> {
687687
};
688688
self.data
689689
.state
690-
.set_runtime_table(table.index, export.definition);
690+
.set_runtime_table(table.index, export.definition, export.vmctx);
691691
}
692692

693693
fn build_imports<'b>(

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

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
99
use crate::prelude::*;
1010
use crate::runtime::vm::{
11-
SendSyncPtr, VMArrayCallFunction, VMFuncRef, VMGlobalDefinition, VMMemoryDefinition,
12-
VMOpaqueContext, VMStore, VMStoreRawPtr, VMTableDefinition, VMWasmCallFunction, ValRaw, VmPtr,
13-
VmSafe,
11+
SendSyncPtr, VMArrayCallFunction, VMContext, VMFuncRef, VMGlobalDefinition, VMMemoryDefinition,
12+
VMOpaqueContext, VMStore, VMStoreRawPtr, VMTableDefinition, VMTableImport, VMWasmCallFunction,
13+
ValRaw, VmPtr, VmSafe,
1414
};
1515
use alloc::alloc::Layout;
1616
use alloc::sync::Arc;
@@ -290,16 +290,20 @@ impl ComponentInstance {
290290
}
291291
}
292292

293-
/// Returns the runtime table definition corresponding to the index of the
294-
/// table provided.
293+
/// Returns the runtime table definition and associated instance `VMContext`
294+
/// corresponding to the index of the table provided.
295295
///
296296
/// This can only be called after `idx` has been initialized at runtime
297297
/// during the instantiation process of a component.
298-
pub fn runtime_table(&self, idx: RuntimeTableIndex) -> *mut VMTableDefinition {
298+
///
299+
/// Note that we use a `VMTableImport` here because of its structure, not
300+
/// because these tables are actually imports.
301+
pub fn runtime_table(&self, idx: RuntimeTableIndex) -> VMTableImport {
299302
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+
let ret = *self.vmctx_plus_offset::<VMTableImport>(self.offsets.runtime_table(idx));
304+
debug_assert!(ret.from.as_ptr() as usize != INVALID_PTR);
305+
debug_assert!(ret.vmctx.as_ptr() as usize != INVALID_PTR);
306+
ret
303307
}
304308
}
305309

@@ -418,20 +422,31 @@ impl ComponentInstance {
418422
}
419423
}
420424

421-
/// Stores the runtime memory pointer at the index specified.
425+
/// Stores the runtime table pointer at the index specified.
422426
///
423427
/// 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
428+
/// component once a table is available, which may not be until part-way
425429
/// through component instantiation.
426430
///
427431
/// Note that it should be a property of the component model that the `ptr`
428432
/// 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>) {
433+
pub fn set_runtime_table(
434+
&mut self,
435+
idx: RuntimeTableIndex,
436+
ptr: NonNull<VMTableDefinition>,
437+
vmctx: NonNull<VMContext>,
438+
) {
439+
// Note that we use a `VMTableImport` here because of its structure, not
440+
// because these tables are actually imports.
430441
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();
442+
let storage =
443+
self.vmctx_plus_offset_mut::<VMTableImport>(self.offsets.runtime_table(idx));
444+
debug_assert!((*storage).vmctx.as_ptr() as usize == INVALID_PTR);
445+
debug_assert!((*storage).from.as_ptr() as usize == INVALID_PTR);
446+
*storage = VMTableImport {
447+
vmctx: vmctx.into(),
448+
from: ptr.into(),
449+
};
435450
}
436451
}
437452

@@ -554,6 +569,11 @@ impl ComponentInstance {
554569
let offset = self.offsets.resource_destructor(i);
555570
*self.vmctx_plus_offset_mut(offset) = INVALID_PTR;
556571
}
572+
for i in 0..self.offsets.num_runtime_tables {
573+
let i = RuntimeTableIndex::from_u32(i);
574+
let offset = self.offsets.runtime_table(i);
575+
*self.vmctx_plus_offset_mut(offset) = INVALID_PTR;
576+
}
557577
}
558578
}
559579

@@ -833,8 +853,13 @@ impl OwnedComponentInstance {
833853
}
834854

835855
/// 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) }
856+
pub fn set_runtime_table(
857+
&mut self,
858+
idx: RuntimeTableIndex,
859+
ptr: NonNull<VMTableDefinition>,
860+
vmctx: NonNull<VMContext>,
861+
) {
862+
unsafe { self.instance_mut().set_runtime_table(idx, ptr, vmctx) }
838863
}
839864

840865
/// See `ComponentInstance::set_lowering`

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ mod test_vmtable_import {
160160
use super::VMTableImport;
161161
use core::mem::offset_of;
162162
use std::mem::size_of;
163+
use wasmtime_environ::component::{Component, VMComponentOffsets};
163164
use wasmtime_environ::{HostPtr, Module, VMOffsets};
164165

165166
#[test]
@@ -179,6 +180,21 @@ mod test_vmtable_import {
179180
usize::from(offsets.vmtable_import_vmctx())
180181
);
181182
}
183+
184+
#[test]
185+
fn ensure_sizes_match() {
186+
// Because we use `VMTableImport` for recording tables used by
187+
// components, we want to make sure that the size calculations between
188+
// `VMOffsets` and `VMComponentOffsets` stay the same.
189+
let module = Module::new();
190+
let vm_offsets = VMOffsets::new(HostPtr, &module);
191+
let component = Component::default();
192+
let vm_component_offsets = VMComponentOffsets::new(HostPtr, &component);
193+
assert_eq!(
194+
vm_offsets.size_of_vmtable_import(),
195+
vm_component_offsets.size_of_vmtable_import()
196+
);
197+
}
182198
}
183199

184200
/// The fields compiled code needs to access to utilize a WebAssembly linear

0 commit comments

Comments
 (0)