Skip to content

Commit 1b57186

Browse files
authored
Delete vm::Instance::table_grow (#11216)
This commit is a further inch towards #11179 by removing internal reliance on reading `VMContext` pointers and casting them to `Pin<&mut Instance>` in various contexts. Notably now only a defined table needs to be grown, which simplifies the internals of `vm::Instance` ever so slightly. This is a similar change as #11211 which transitions libcalls to using `DefinedTableIndex` instead of `TableIndex`.
1 parent da0eb2c commit 1b57186

7 files changed

Lines changed: 130 additions & 61 deletions

File tree

crates/cranelift/src/func_environ.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,14 +1814,14 @@ impl FuncEnvironment<'_> {
18141814
self.builtin_functions.table_grow_func_ref(&mut pos.func)
18151815
};
18161816

1817-
let vmctx = self.vmctx_val(&mut pos);
1817+
let (table_vmctx, defined_table_index) =
1818+
self.table_vmctx_and_defined_index(&mut pos, table_index);
18181819

18191820
let index_type = table.idx_type;
18201821
let delta = self.cast_index_to_i64(&mut pos, delta, index_type);
1821-
let table_index_arg = pos.ins().iconst(I32, table_index.as_u32() as i64);
18221822
let call_inst = pos
18231823
.ins()
1824-
.call(grow, &[vmctx, table_index_arg, delta, init_value]);
1824+
.call(grow, &[table_vmctx, defined_table_index, delta, init_value]);
18251825
let result = pos.func.dfg.first_result(call_inst);
18261826
Ok(self.convert_pointer_to_index_type(builder.cursor(), result, index_type, false))
18271827
}
@@ -2772,6 +2772,42 @@ impl FuncEnvironment<'_> {
27722772
}
27732773
}
27742774

2775+
/// Returns two `ir::Value`s, the first of which is the vmctx for the table
2776+
/// `index` and the second of which is the `DefinedTableIndex` for `index`.
2777+
///
2778+
/// Handles internally whether `index` is an imported table or not.
2779+
fn table_vmctx_and_defined_index(
2780+
&mut self,
2781+
pos: &mut FuncCursor,
2782+
index: TableIndex,
2783+
) -> (ir::Value, ir::Value) {
2784+
// NB: the body of this method is similar to
2785+
// `memory_vmctx_and_defined_index` above.
2786+
let cur_vmctx = self.vmctx_val(pos);
2787+
match self.module.defined_table_index(index) {
2788+
Some(index) => (cur_vmctx, pos.ins().iconst(I32, i64::from(index.as_u32()))),
2789+
None => {
2790+
let vmimport = self.offsets.vmctx_vmtable_import(index);
2791+
2792+
let vmctx = pos.ins().load(
2793+
self.isa.pointer_type(),
2794+
ir::MemFlags::trusted(),
2795+
cur_vmctx,
2796+
i32::try_from(vmimport + u32::from(self.offsets.vmtable_import_vmctx()))
2797+
.unwrap(),
2798+
);
2799+
let index = pos.ins().load(
2800+
ir::types::I32,
2801+
ir::MemFlags::trusted(),
2802+
cur_vmctx,
2803+
i32::try_from(vmimport + u32::from(self.offsets.vmtable_import_index()))
2804+
.unwrap(),
2805+
);
2806+
(vmctx, index)
2807+
}
2808+
}
2809+
}
2810+
27752811
pub fn translate_memory_grow(
27762812
&mut self,
27772813
builder: &mut FunctionBuilder<'_>,

crates/environ/src/vmoffsets.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,18 @@ impl<P: PtrSize> VMOffsets<P> {
706706
0 * self.pointer_size()
707707
}
708708

709+
/// The offset of the `vmctx` field.
710+
#[inline]
711+
pub fn vmtable_import_vmctx(&self) -> u8 {
712+
1 * self.pointer_size()
713+
}
714+
715+
/// The offset of the `index` field.
716+
#[inline]
717+
pub fn vmtable_import_index(&self) -> u8 {
718+
2 * self.pointer_size()
719+
}
720+
709721
/// Return the size of `VMTableImport`.
710722
#[inline]
711723
pub fn size_of_vmtable_import(&self) -> u8 {

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

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -719,19 +719,7 @@ impl Instance {
719719
///
720720
/// Returns `None` if table can't be grown by the specified amount of
721721
/// elements, or if `init_value` is the wrong type of table element.
722-
pub(crate) fn table_grow(
723-
self: Pin<&mut Self>,
724-
store: &mut dyn VMStore,
725-
table_index: TableIndex,
726-
delta: u64,
727-
init_value: TableElement,
728-
) -> Result<Option<usize>, Error> {
729-
self.with_defined_table_index_and_instance(table_index, |i, instance| {
730-
instance.defined_table_grow(store, i, delta, init_value)
731-
})
732-
}
733-
734-
fn defined_table_grow(
722+
pub(crate) fn defined_table_grow(
735723
mut self: Pin<&mut Self>,
736724
store: &mut dyn VMStore,
737725
table_index: DefinedTableIndex,

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

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ use core::ptr::NonNull;
7070
#[cfg(feature = "threads")]
7171
use core::time::Duration;
7272
use wasmtime_environ::{
73-
DataIndex, DefinedMemoryIndex, ElemIndex, FuncIndex, MemoryIndex, TableIndex, Trap,
73+
DataIndex, DefinedMemoryIndex, DefinedTableIndex, ElemIndex, FuncIndex, MemoryIndex,
74+
TableIndex, Trap,
7475
};
7576
#[cfg(feature = "wmemcheck")]
7677
use wasmtime_wmemcheck::AccessError::{
@@ -223,20 +224,19 @@ unsafe impl HostResultHasUnwindSentinel for Option<AllocationSize> {
223224
unsafe fn table_grow_func_ref(
224225
store: &mut dyn VMStore,
225226
mut instance: Pin<&mut Instance>,
226-
table_index: u32,
227+
defined_table_index: u32,
227228
delta: u64,
228229
init_value: *mut u8,
229230
) -> Result<Option<AllocationSize>> {
230-
let table_index = TableIndex::from_u32(table_index);
231-
232-
let element = match instance.as_mut().table_element_type(table_index) {
233-
TableElementType::Func => NonNull::new(init_value.cast::<VMFuncRef>()).into(),
234-
TableElementType::GcRef => unreachable!(),
235-
TableElementType::Cont => unreachable!(),
236-
};
237-
231+
let defined_table_index = DefinedTableIndex::from_u32(defined_table_index);
232+
let table_index = instance.env_module().table_index(defined_table_index);
233+
debug_assert!(matches!(
234+
instance.as_mut().table_element_type(table_index),
235+
TableElementType::Func,
236+
));
237+
let element = NonNull::new(init_value.cast::<VMFuncRef>()).into();
238238
let result = instance
239-
.table_grow(store, table_index, delta, element)?
239+
.defined_table_grow(store, defined_table_index, delta, element)?
240240
.map(AllocationSize);
241241
Ok(result)
242242
}
@@ -246,27 +246,28 @@ unsafe fn table_grow_func_ref(
246246
unsafe fn table_grow_gc_ref(
247247
store: &mut dyn VMStore,
248248
mut instance: Pin<&mut Instance>,
249-
table_index: u32,
249+
defined_table_index: u32,
250250
delta: u64,
251251
init_value: u32,
252252
) -> Result<Option<AllocationSize>> {
253-
let table_index = TableIndex::from_u32(table_index);
254-
255-
let element = match instance.as_mut().table_element_type(table_index) {
256-
TableElementType::Func => unreachable!(),
257-
TableElementType::GcRef => VMGcRef::from_raw_u32(init_value)
258-
.map(|r| {
259-
store
260-
.store_opaque_mut()
261-
.unwrap_gc_store_mut()
262-
.clone_gc_ref(&r)
263-
})
264-
.into(),
265-
TableElementType::Cont => unreachable!(),
266-
};
253+
let defined_table_index = DefinedTableIndex::from_u32(defined_table_index);
254+
let table_index = instance.env_module().table_index(defined_table_index);
255+
debug_assert!(matches!(
256+
instance.as_mut().table_element_type(table_index),
257+
TableElementType::GcRef,
258+
));
259+
260+
let element = VMGcRef::from_raw_u32(init_value)
261+
.map(|r| {
262+
store
263+
.store_opaque_mut()
264+
.unwrap_gc_store_mut()
265+
.clone_gc_ref(&r)
266+
})
267+
.into();
267268

268269
let result = instance
269-
.table_grow(store, table_index, delta, element)?
270+
.defined_table_grow(store, defined_table_index, delta, element)?
270271
.map(AllocationSize);
271272
Ok(result)
272273
}
@@ -275,24 +276,22 @@ unsafe fn table_grow_gc_ref(
275276
unsafe fn table_grow_cont_obj(
276277
store: &mut dyn VMStore,
277278
mut instance: Pin<&mut Instance>,
278-
table_index: u32,
279+
defined_table_index: u32,
279280
delta: u64,
280281
// The following two values together form the initial Option<VMContObj>.
281282
// A None value is indicated by the pointer being null.
282283
init_value_contref: *mut u8,
283284
init_value_revision: u64,
284285
) -> Result<Option<AllocationSize>> {
285-
let init_value = VMContObj::from_raw_parts(init_value_contref, init_value_revision);
286-
287-
let table_index = TableIndex::from_u32(table_index);
288-
289-
let element = match instance.as_mut().table_element_type(table_index) {
290-
TableElementType::Cont => init_value.into(),
291-
_ => panic!("Wrong table growing function"),
292-
};
293-
286+
let defined_table_index = DefinedTableIndex::from_u32(defined_table_index);
287+
let table_index = instance.env_module().table_index(defined_table_index);
288+
debug_assert!(matches!(
289+
instance.as_mut().table_element_type(table_index),
290+
TableElementType::Cont,
291+
));
292+
let element = VMContObj::from_raw_parts(init_value_contref, init_value_revision).into();
294293
let result = instance
295-
.table_grow(store, table_index, delta, element)?
294+
.defined_table_grow(store, defined_table_index, delta, element)?
296295
.map(AllocationSize);
297296
Ok(result)
298297
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ mod test_vmtable {
179179
offset_of!(VMTableImport, from),
180180
usize::from(offsets.vmtable_import_from())
181181
);
182+
assert_eq!(
183+
offset_of!(VMTableImport, vmctx),
184+
usize::from(offsets.vmtable_import_vmctx())
185+
);
186+
assert_eq!(
187+
offset_of!(VMTableImport, index),
188+
usize::from(offsets.vmtable_import_index())
189+
);
182190
}
183191

184192
#[test]

winch/codegen/src/codegen/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,6 +1590,36 @@ where
15901590
}
15911591
}
15921592
}
1593+
1594+
/// Same as `prepare_builtin_defined_memory_arg`, but for tables.
1595+
pub fn prepare_builtin_defined_table_arg(
1596+
&mut self,
1597+
table: TableIndex,
1598+
defined_index_at: usize,
1599+
builtin: BuiltinFunction,
1600+
) -> Result<Callee> {
1601+
match self.env.translation.module.defined_table_index(table) {
1602+
Some(defined) => {
1603+
self.context
1604+
.stack
1605+
.insert_many(defined_index_at, &[defined.as_u32().try_into()?]);
1606+
Ok(Callee::Builtin(builtin))
1607+
}
1608+
None => {
1609+
let vmimport = self.env.vmoffsets.vmctx_vmtable_import(table);
1610+
let vmctx_offset = vmimport + u32::from(self.env.vmoffsets.vmtable_import_vmctx());
1611+
let index_offset = vmimport + u32::from(self.env.vmoffsets.vmtable_import_index());
1612+
let index_addr = self.masm.address_at_vmctx(index_offset)?;
1613+
let index_dst = self.context.reg_for_class(RegClass::Int, self.masm)?;
1614+
self.masm
1615+
.load(index_addr, writable!(index_dst), OperandSize::S32)?;
1616+
self.context
1617+
.stack
1618+
.insert_many(defined_index_at, &[Val::reg(index_dst, WasmValType::I32)]);
1619+
Ok(Callee::BuiltinWithDifferentVmctx(builtin, vmctx_offset))
1620+
}
1621+
}
1622+
}
15931623
}
15941624

15951625
/// Returns the index of the [`ControlStackFrame`] for the given

winch/codegen/src/visitor.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,14 +1718,10 @@ where
17181718
// but the builtin function expects the init value as the last
17191719
// argument.
17201720
self.context.stack.inner_mut().swap(len - 1, len - 2);
1721-
self.context.stack.insert_many(at, &[table.try_into()?]);
17221721

1723-
FnCall::emit::<M>(
1724-
&mut self.env,
1725-
self.masm,
1726-
&mut self.context,
1727-
Callee::Builtin(builtin.clone()),
1728-
)?;
1722+
let builtin = self.prepare_builtin_defined_table_arg(table_index, at, builtin)?;
1723+
1724+
FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, builtin)?;
17291725

17301726
Ok(())
17311727
}

0 commit comments

Comments
 (0)