wasmtime: Add support for func.ref and table.grow with funcrefs

`funcref`s are implemented as `NonNull<VMCallerCheckedAnyfunc>`.

This should be more efficient than using a `VMExternRef` that points at a
`VMCallerCheckedAnyfunc` because it gets rid of an indirection, dynamic
allocation, and some reference counting.

Note that the null function reference is *NOT* a null pointer; it is a
`VMCallerCheckedAnyfunc` that has a null `func_ptr` member.

Part of #929
This commit is contained in:
Nick Fitzgerald
2020-06-18 11:04:40 -07:00
parent ddc2ce8080
commit 58bb5dd953
37 changed files with 603 additions and 305 deletions

View File

@@ -15,6 +15,7 @@
// tables: [VMTableDefinition; module.num_defined_tables],
// memories: [VMMemoryDefinition; module.num_defined_memories],
// globals: [VMGlobalDefinition; module.num_defined_globals],
// anyfuncs: [VMCallerCheckedAnyfunc; module.num_imported_functions + module.num_defined_functions],
// builtins: VMBuiltinFunctionsArray,
// }
@@ -62,6 +63,8 @@ pub struct VMOffsets {
pub num_imported_memories: u32,
/// The number of imported globals in the module.
pub num_imported_globals: u32,
/// The number of defined functions in the module.
pub num_defined_functions: u32,
/// The number of defined tables in the module.
pub num_defined_tables: u32,
/// The number of defined memories in the module.
@@ -80,6 +83,7 @@ impl VMOffsets {
num_imported_tables: cast_to_u32(module.num_imported_tables),
num_imported_memories: cast_to_u32(module.num_imported_memories),
num_imported_globals: cast_to_u32(module.num_imported_globals),
num_defined_functions: cast_to_u32(module.functions.len()),
num_defined_tables: cast_to_u32(module.table_plans.len()),
num_defined_memories: cast_to_u32(module.memory_plans.len()),
num_defined_globals: cast_to_u32(module.globals.len()),
@@ -390,8 +394,8 @@ impl VMOffsets {
align(offset, 16)
}
/// The offset of the builtin functions array.
pub fn vmctx_builtin_functions_begin(&self) -> u32 {
/// The offset of the `anyfuncs` array.
pub fn vmctx_anyfuncs_begin(&self) -> u32 {
self.vmctx_globals_begin()
.checked_add(
self.num_defined_globals
@@ -401,6 +405,19 @@ impl VMOffsets {
.unwrap()
}
/// The offset of the builtin functions array.
pub fn vmctx_builtin_functions_begin(&self) -> u32 {
self.vmctx_anyfuncs_begin()
.checked_add(
self.num_imported_functions
.checked_add(self.num_defined_functions)
.unwrap()
.checked_mul(u32::from(self.size_of_vmcaller_checked_anyfunc()))
.unwrap(),
)
.unwrap()
}
/// Return the size of the `VMContext` allocation.
pub fn size_of_vmctx(&self) -> u32 {
self.vmctx_builtin_functions_begin()
@@ -516,6 +533,19 @@ impl VMOffsets {
.unwrap()
}
/// Return the offset to the `VMCallerCheckedAnyfunc` for the given function
/// index (either imported or defined).
pub fn vmctx_anyfunc(&self, index: FuncIndex) -> u32 {
self.vmctx_anyfuncs_begin()
.checked_add(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmcaller_checked_anyfunc()))
.unwrap(),
)
.unwrap()
}
/// Return the offset to the `body` field in `*const VMFunctionBody` index `index`.
pub fn vmctx_vmfunction_import_body(&self, index: FuncIndex) -> u32 {
self.vmctx_vmfunction_import(index)