Restructure VMContext to eliminate a level of indirection.

This commit is contained in:
Dan Gohman
2019-01-03 11:02:37 -08:00
parent ff6776fe10
commit 3270369a69
10 changed files with 774 additions and 621 deletions

View File

@@ -2,7 +2,7 @@ use cast;
use cranelift_codegen::cursor::FuncCursor;
use cranelift_codegen::ir;
use cranelift_codegen::ir::condcodes::*;
use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
use cranelift_codegen::ir::immediates::{Imm64, Offset32, Uimm64};
use cranelift_codegen::ir::types::*;
use cranelift_codegen::ir::{
AbiParam, ArgumentPurpose, ExtFuncData, FuncRef, Function, InstBuilder, Signature,
@@ -60,6 +60,8 @@ pub struct FuncEnvironment<'module_environment> {
vmctx: Option<ir::GlobalValue>,
/// The Cranelift global holding the base address of the signature IDs vector.
/// TODO: Now that the bases are just offsets from vmctx rather than loads, we
/// can eliminate these base variables.
signature_ids_base: Option<ir::GlobalValue>,
/// The Cranelift global holding the base address of the imported functions table.
@@ -121,7 +123,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
imported_memory32_size_extfunc: None,
memory_grow_extfunc: None,
imported_memory_grow_extfunc: None,
offsets: VMOffsets::new(target_config.pointer_bytes()),
offsets: VMOffsets::new(target_config.pointer_bytes(), module),
}
}
@@ -141,11 +143,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_functions_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_functions())),
offset: Imm64::new(self.offsets.vmctx_imported_functions()),
global_type: pointer_type,
readonly: true,
});
self.imported_functions_base = Some(new_base);
new_base
@@ -156,11 +157,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_tables_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_tables())),
offset: Imm64::new(self.offsets.vmctx_imported_tables()),
global_type: pointer_type,
readonly: true,
});
self.imported_tables_base = Some(new_base);
new_base
@@ -171,11 +171,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_memories_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_memories())),
offset: Imm64::new(self.offsets.vmctx_imported_memories()),
global_type: pointer_type,
readonly: true,
});
self.imported_memories_base = Some(new_base);
new_base
@@ -186,11 +185,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.imported_globals_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_imported_globals())),
offset: Imm64::new(self.offsets.vmctx_imported_globals()),
global_type: pointer_type,
readonly: true,
});
self.imported_globals_base = Some(new_base);
new_base
@@ -201,11 +199,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.tables_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_tables())),
offset: Imm64::new(self.offsets.vmctx_tables()),
global_type: pointer_type,
readonly: true,
});
self.tables_base = Some(new_base);
new_base
@@ -216,11 +213,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.memories_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_memories())),
offset: Imm64::new(self.offsets.vmctx_memories()),
global_type: pointer_type,
readonly: true,
});
self.memories_base = Some(new_base);
new_base
@@ -231,11 +227,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.globals_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_globals())),
offset: Imm64::new(self.offsets.vmctx_globals()),
global_type: pointer_type,
readonly: true,
});
self.globals_base = Some(new_base);
new_base
@@ -246,11 +241,10 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
self.signature_ids_base.unwrap_or_else(|| {
let pointer_type = self.pointer_type();
let vmctx = self.vmctx(func);
let new_base = func.create_global_value(ir::GlobalValueData::Load {
let new_base = func.create_global_value(ir::GlobalValueData::IAddImm {
base: vmctx,
offset: Offset32::new(i32::from(self.offsets.vmctx_signature_ids())),
offset: Imm64::new(self.offsets.vmctx_signature_ids()),
global_type: pointer_type,
readonly: true,
});
self.signature_ids_base = Some(new_base);
new_base

View File

@@ -2,21 +2,50 @@
//! module.
use cranelift_codegen::ir;
use cranelift_entity::EntityRef;
use cranelift_wasm::{
DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
TableIndex,
SignatureIndex, TableIndex,
};
use module::Module;
/// This class computes offsets to fields within `VMContext` and other
/// related structs that JIT code accesses directly.
pub struct VMOffsets {
pointer_size: u8,
/// The size in bytes of a pointer on the target.
pub pointer_size: u8,
/// The number of signature declarations in the module.
pub num_signature_ids: u64,
/// The number of imported functions in the module.
pub num_imported_functions: u64,
/// The number of imported tables in the module.
pub num_imported_tables: u64,
/// The number of imported memories in the module.
pub num_imported_memories: u64,
/// The number of imported globals in the module.
pub num_imported_globals: u64,
/// The number of defined tables in the module.
pub num_defined_tables: u64,
/// The number of defined memories in the module.
pub num_defined_memories: u64,
/// The number of defined globals in the module.
pub num_defined_globals: u64,
}
impl VMOffsets {
/// Return a new `VMOffsets` instance, for a given pointer size.
pub fn new(pointer_size: u8) -> Self {
Self { pointer_size }
pub fn new(pointer_size: u8, module: &Module) -> Self {
Self {
pointer_size,
num_signature_ids: module.signatures.len() as u64,
num_imported_functions: module.imported_funcs.len() as u64,
num_imported_tables: module.imported_tables.len() as u64,
num_imported_memories: module.imported_memories.len() as u64,
num_imported_globals: module.imported_globals.len() as u64,
num_defined_tables: module.table_plans.len() as u64,
num_defined_memories: module.memory_plans.len() as u64,
num_defined_globals: module.globals.len() as u64,
}
}
}
@@ -208,55 +237,76 @@ impl VMOffsets {
/// Offsets for `VMContext`.
impl VMOffsets {
/// The offset of the `signature_ids` field.
pub fn vmctx_signature_ids(&self) -> u8 {
0 * self.pointer_size
pub fn vmctx_signature_ids(&self) -> i64 {
0
}
/// The offset of the `tables` field.
#[allow(clippy::erasing_op)]
pub fn vmctx_imported_functions(&self) -> u8 {
1 * self.pointer_size
pub fn vmctx_imported_functions(&self) -> i64 {
self.vmctx_signature_ids()
+ self.num_signature_ids as i64 * i64::from(self.size_of_vmshared_signature_index())
}
/// The offset of the `tables` field.
#[allow(clippy::identity_op)]
pub fn vmctx_imported_tables(&self) -> u8 {
2 * self.pointer_size
pub fn vmctx_imported_tables(&self) -> i64 {
self.vmctx_imported_functions()
+ self.num_imported_functions as i64 * i64::from(self.size_of_vmfunction_import())
}
/// The offset of the `memories` field.
pub fn vmctx_imported_memories(&self) -> u8 {
3 * self.pointer_size
pub fn vmctx_imported_memories(&self) -> i64 {
self.vmctx_imported_tables()
+ self.num_imported_tables as i64 * i64::from(self.size_of_vmtable_import())
}
/// The offset of the `globals` field.
pub fn vmctx_imported_globals(&self) -> u8 {
4 * self.pointer_size
pub fn vmctx_imported_globals(&self) -> i64 {
self.vmctx_imported_memories()
+ self.num_imported_memories as i64 * i64::from(self.size_of_vmmemory_import())
}
/// The offset of the `tables` field.
pub fn vmctx_tables(&self) -> u8 {
5 * self.pointer_size
pub fn vmctx_tables(&self) -> i64 {
self.vmctx_imported_globals()
+ self.num_imported_globals as i64 * i64::from(self.size_of_vmglobal_import())
}
/// The offset of the `memories` field.
pub fn vmctx_memories(&self) -> u8 {
6 * self.pointer_size
pub fn vmctx_memories(&self) -> i64 {
self.vmctx_tables()
+ self.num_defined_tables as i64 * i64::from(self.size_of_vmtable_definition())
}
/// The offset of the `globals` field.
pub fn vmctx_globals(&self) -> u8 {
7 * self.pointer_size
pub fn vmctx_globals(&self) -> i64 {
self.vmctx_memories()
+ self.num_defined_memories as i64 * i64::from(self.size_of_vmmemory_definition())
}
/// Return the size of `VMContext`.
/// Return the size of the `VMContext` allocation.
#[allow(dead_code)]
pub fn size_of_vmctx(&self) -> u8 {
8 * self.pointer_size
pub fn size_of_vmctx(&self) -> i64 {
self.vmctx_globals()
+ self.num_defined_globals as i64 * i64::from(self.size_of_vmglobal_definition())
}
/// Return the offset from the `signature_ids` pointer to `VMSharedSignatureId` index `index`.
pub fn index_vmshared_signature_id(&self, index: SignatureIndex) -> i32 {
assert!((index.index() as u64) < self.num_signature_ids);
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmshared_signature_index()))
.unwrap(),
)
.unwrap()
}
/// Return the offset from the `imported_functions` pointer to `VMFunctionImport` index `index`.
fn index_vmfunction_import(&self, index: FuncIndex) -> i32 {
pub fn index_vmfunction_import(&self, index: FuncIndex) -> i32 {
assert!((index.index() as u64) < self.num_imported_functions);
cast::i32(
index
.as_u32()
@@ -267,7 +317,8 @@ impl VMOffsets {
}
/// Return the offset from the `imported_tables` pointer to `VMTableImport` index `index`.
fn index_vmtable_import(&self, index: TableIndex) -> i32 {
pub fn index_vmtable_import(&self, index: TableIndex) -> i32 {
assert!((index.index() as u64) < self.num_imported_tables);
cast::i32(
index
.as_u32()
@@ -277,19 +328,9 @@ impl VMOffsets {
.unwrap()
}
/// Return the offset from the `tables` pointer to `VMTableDefinition` index `index`.
fn index_vmtable_definition(&self, index: DefinedTableIndex) -> i32 {
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmtable_definition()))
.unwrap(),
)
.unwrap()
}
/// Return the offset from the `imported_memories` pointer to `VMMemoryImport` index `index`.
fn index_vmmemory_import(&self, index: MemoryIndex) -> i32 {
pub fn index_vmmemory_import(&self, index: MemoryIndex) -> i32 {
assert!((index.index() as u64) < self.num_imported_memories);
cast::i32(
index
.as_u32()
@@ -299,8 +340,33 @@ impl VMOffsets {
.unwrap()
}
/// Return the offset from the `imported_globals` pointer to `VMGlobalImport` index `index`.
pub fn index_vmglobal_import(&self, index: GlobalIndex) -> i32 {
assert!((index.index() as u64) < self.num_imported_globals);
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmglobal_import()))
.unwrap(),
)
.unwrap()
}
/// Return the offset from the `tables` pointer to `VMTableDefinition` index `index`.
pub fn index_vmtable_definition(&self, index: DefinedTableIndex) -> i32 {
assert!((index.index() as u64) < self.num_defined_tables);
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmtable_definition()))
.unwrap(),
)
.unwrap()
}
/// Return the offset from the `memories` pointer to `VMMemoryDefinition` index `index`.
fn index_vmmemory_definition(&self, index: DefinedMemoryIndex) -> i32 {
pub fn index_vmmemory_definition(&self, index: DefinedMemoryIndex) -> i32 {
assert!((index.index() as u64) < self.num_defined_memories);
cast::i32(
index
.as_u32()
@@ -310,12 +376,14 @@ impl VMOffsets {
.unwrap()
}
/// Return the offset from the `imported_globals` pointer to `VMGlobalImport` index `index`.
fn index_vmglobal_import(&self, index: GlobalIndex) -> i32 {
/// Return the offset from the `globals` pointer to the `VMGlobalDefinition`
/// index `index`.
pub fn index_vmglobal_definition(&self, index: DefinedGlobalIndex) -> i32 {
assert!((index.index() as u64) < self.num_defined_globals);
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmglobal_import()))
.checked_mul(u32::from(self.size_of_vmglobal_definition()))
.unwrap(),
)
.unwrap()
@@ -400,16 +468,4 @@ impl VMOffsets {
.checked_add(i32::from(self.vmglobal_import_from()))
.unwrap()
}
/// Return the offset from the `globals` pointer to the `VMGlobalDefinition`
/// index `index`.
pub fn index_vmglobal_definition(&self, index: DefinedGlobalIndex) -> i32 {
cast::i32(
index
.as_u32()
.checked_mul(u32::from(self.size_of_vmglobal_definition()))
.unwrap(),
)
.unwrap()
}
}

View File

@@ -159,7 +159,7 @@ impl CompiledModule {
/// Note that if only one instance of this module is needed, it may be more
/// efficient to call the top-level `instantiate`, since that avoids copying
/// the data initializers.
pub fn instantiate(&mut self) -> Result<Box<Instance>, InstantiationError> {
pub fn instantiate(&mut self) -> Result<Instance, InstantiationError> {
let data_initializers = self
.data_initializers
.iter()
@@ -205,7 +205,7 @@ pub fn instantiate(
compiler: &mut Compiler,
data: &[u8],
resolver: &mut Resolver,
) -> Result<Box<Instance>, SetupError> {
) -> Result<Instance, SetupError> {
let raw = RawCompiledModule::new(compiler, data, resolver)?;
Instance::new(

View File

@@ -7,7 +7,6 @@ use action::{ActionError, ActionOutcome, RuntimeValue};
use compiler::Compiler;
use cranelift_entity::PrimaryMap;
use resolver::Resolver;
use std::boxed::Box;
use std::collections::HashMap;
use std::string::String;
use wasmtime_runtime::{Export, Instance};
@@ -26,7 +25,7 @@ pub struct Namespace {
names: HashMap<String, InstanceIndex>,
/// The instances, available by index.
instances: PrimaryMap<InstanceIndex, Box<Instance>>,
instances: PrimaryMap<InstanceIndex, Instance>,
}
impl Namespace {
@@ -40,11 +39,7 @@ impl Namespace {
/// Install a new `Instance` in this `Namespace`, optionally with the
/// given name, and return its index.
pub fn instance(
&mut self,
instance_name: Option<&str>,
instance: Box<Instance>,
) -> InstanceIndex {
pub fn instance(&mut self, instance_name: Option<&str>, instance: Instance) -> InstanceIndex {
let index = self.instances.push(instance);
if let Some(instance_name) = instance_name {
self.names.insert(instance_name.into(), index);

File diff suppressed because it is too large Load Diff

View File

@@ -94,10 +94,10 @@ pub unsafe extern "C" fn wasmtime_memory32_grow(
memory_index: u32,
vmctx: *mut VMContext,
) -> u32 {
let instance = (&mut *vmctx).instance();
let instance_contents = (&mut *vmctx).instance_contents();
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
instance
instance_contents
.memory_grow(memory_index, delta)
.unwrap_or(u32::max_value())
}
@@ -109,30 +109,21 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_grow(
memory_index: u32,
vmctx: *mut VMContext,
) -> u32 {
let instance = (&mut *vmctx).instance();
assert!(
(memory_index as usize) < instance.num_imported_memories(),
"imported memory index for memory.grow out of bounds"
);
let instance_contents = (&mut *vmctx).instance_contents();
let memory_index = MemoryIndex::from_u32(memory_index);
let import = instance.vmctx().imported_memory(memory_index);
let foreign_instance = (&mut *import.vmctx).instance();
let foreign_memory = &mut *import.from;
let foreign_index = foreign_instance.vmctx().memory_index(foreign_memory);
foreign_instance
.memory_grow(foreign_index, delta)
instance_contents
.imported_memory_grow(memory_index, delta)
.unwrap_or(u32::max_value())
}
/// Implementation of memory.size for locally-defined 32-bit memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_memory32_size(memory_index: u32, vmctx: *mut VMContext) -> u32 {
let instance = (&mut *vmctx).instance();
let instance_contents = (&mut *vmctx).instance_contents();
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
instance.memory_size(memory_index)
instance_contents.memory_size(memory_index)
}
/// Implementation of memory.size for imported 32-bit memories.
@@ -141,17 +132,8 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_size(
memory_index: u32,
vmctx: *mut VMContext,
) -> u32 {
let instance = (&mut *vmctx).instance();
assert!(
(memory_index as usize) < instance.num_imported_memories(),
"imported memory index for memory.grow out of bounds"
);
let instance_contents = (&mut *vmctx).instance_contents();
let memory_index = MemoryIndex::from_u32(memory_index);
let import = instance.vmctx().imported_memory(memory_index);
let foreign_instance = (&mut *import.vmctx).instance();
let foreign_memory = &mut *import.from;
let foreign_index = foreign_instance.vmctx().memory_index(foreign_memory);
foreign_instance.memory_size(foreign_index)
instance_contents.imported_memory_size(memory_index)
}

View File

@@ -94,9 +94,9 @@ pub extern "C" fn wasmtime_init_finish(vmctx: &mut VMContext) {
})
}
let instance = unsafe { vmctx.instance() };
let instance_contents = unsafe { vmctx.instance_contents() };
let have_signal_handlers = TRAP_CONTEXT.with(|cx| cx.borrow().haveSignalHandlers);
if !have_signal_handlers && instance.needs_signal_handlers() {
if !have_signal_handlers && instance_contents.needs_signal_handlers() {
panic!("failed to install signal handlers");
}
}

View File

@@ -1,13 +1,8 @@
//! This file declares `VMContext` and several related structs which contain
//! fields that compiled wasm code accesses directly.
use cranelift_entity::EntityRef;
use cranelift_wasm::{
DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
TableIndex,
};
use instance::Instance;
use std::{mem, ptr, u32};
use instance::InstanceContents;
use std::{ptr, u32};
/// An imported function.
#[derive(Debug, Copy, Clone)]
@@ -24,11 +19,12 @@ pub struct VMFunctionImport {
mod test_vmfunction_import {
use super::VMFunctionImport;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmfunction_import_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMFunctionImport>(),
usize::from(offsets.size_of_vmfunction_import())
@@ -78,11 +74,12 @@ pub struct VMTableImport {
mod test_vmtable_import {
use super::VMTableImport;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmtable_import_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMTableImport>(),
usize::from(offsets.size_of_vmtable_import())
@@ -114,11 +111,12 @@ pub struct VMMemoryImport {
mod test_vmmemory_import {
use super::VMMemoryImport;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmmemory_import_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMMemoryImport>(),
usize::from(offsets.size_of_vmmemory_import())
@@ -147,11 +145,12 @@ pub struct VMGlobalImport {
mod test_vmglobal_import {
use super::VMGlobalImport;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmglobal_import_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMGlobalImport>(),
usize::from(offsets.size_of_vmglobal_import())
@@ -180,11 +179,12 @@ pub struct VMMemoryDefinition {
mod test_vmmemory_definition {
use super::VMMemoryDefinition;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmmemory_definition_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMMemoryDefinition>(),
usize::from(offsets.size_of_vmmemory_definition())
@@ -222,11 +222,12 @@ pub struct VMTableDefinition {
mod test_vmtable_definition {
use super::VMTableDefinition;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmtable_definition_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMTableDefinition>(),
usize::from(offsets.size_of_vmtable_definition())
@@ -257,7 +258,7 @@ pub struct VMGlobalDefinition {
mod test_vmglobal_definition {
use super::VMGlobalDefinition;
use std::mem::{align_of, size_of};
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmglobal_definition_alignment() {
@@ -269,7 +270,8 @@ mod test_vmglobal_definition {
#[test]
fn check_vmglobal_definition_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMGlobalDefinition>(),
usize::from(offsets.size_of_vmglobal_definition())
@@ -390,11 +392,12 @@ pub struct VMSharedSignatureIndex(u32);
mod test_vmshared_signature_index {
use super::VMSharedSignatureIndex;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmshared_signature_index() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMSharedSignatureIndex>(),
usize::from(offsets.size_of_vmshared_signature_index())
@@ -425,11 +428,12 @@ pub struct VMCallerCheckedAnyfunc {
mod test_vmcaller_checked_anyfunc {
use super::VMCallerCheckedAnyfunc;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
use wasmtime_environ::{Module, VMOffsets};
#[test]
fn check_vmcaller_checked_anyfunc_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
let module = Module::new();
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8, &module);
assert_eq!(
size_of::<VMCallerCheckedAnyfunc>(),
usize::from(offsets.size_of_vmcaller_checked_anyfunc())
@@ -460,186 +464,23 @@ impl Default for VMCallerCheckedAnyfunc {
}
/// The VM "context", which is pointed to by the `vmctx` arg in Cranelift.
/// This has pointers to the globals, memories, tables, and other runtime
/// This has information about globals, memories, tables, and other runtime
/// state associated with the current instance.
///
/// TODO: The number of memories, globals, tables, and signature IDs does
/// not change dynamically, and pointer arrays are not indexed dynamically,
/// so these fields could all be contiguously allocated.
/// The struct here is empty, as the sizes of these fields are dynamic, and
/// we can't describe them in Rust's type system. Sufficient memory is
/// allocated at runtime.
///
/// TODO: We could move the globals into the `vmctx` allocation too.
#[derive(Debug)]
#[repr(C)]
pub struct VMContext {
/// Signature identifiers for signature-checking indirect calls.
signature_ids: *mut VMSharedSignatureIndex,
/// A pointer to an array of `*const VMFunctionBody` instances, indexed by `FuncIndex`.
imported_functions: *const VMFunctionImport,
/// A pointer to an array of `VMTableImport` instances, indexed by `TableIndex`.
imported_tables: *const VMTableImport,
/// A pointer to an array of `VMMemoryImport` instances, indexed by `MemoryIndex`.
imported_memories: *const VMMemoryImport,
/// A pointer to an array of `VMGlobalImport` instances, indexed by `GlobalIndex`.
imported_globals: *const VMGlobalImport,
/// A pointer to an array of locally-defined `VMTableDefinition` instances,
/// indexed by `DefinedTableIndex`.
tables: *mut VMTableDefinition,
/// A pointer to an array of locally-defined `VMMemoryDefinition` instances,
/// indexed by `DefinedMemoryIndex`.
memories: *mut VMMemoryDefinition,
/// A pointer to an array of locally-defined `VMGlobalDefinition` instances,
/// indexed by `DefinedGlobalIndex`.
globals: *mut VMGlobalDefinition,
// If more elements are added here, remember to add offset_of tests below!
}
#[cfg(test)]
mod test {
use super::VMContext;
use std::mem::size_of;
use wasmtime_environ::VMOffsets;
#[test]
fn check_vmctx_offsets() {
let offsets = VMOffsets::new(size_of::<*mut u8>() as u8);
assert_eq!(size_of::<VMContext>(), usize::from(offsets.size_of_vmctx()));
assert_eq!(
offset_of!(VMContext, signature_ids),
usize::from(offsets.vmctx_signature_ids())
);
assert_eq!(
offset_of!(VMContext, imported_functions),
usize::from(offsets.vmctx_imported_functions())
);
assert_eq!(
offset_of!(VMContext, imported_tables),
usize::from(offsets.vmctx_imported_tables())
);
assert_eq!(
offset_of!(VMContext, imported_memories),
usize::from(offsets.vmctx_imported_memories())
);
assert_eq!(
offset_of!(VMContext, imported_globals),
usize::from(offsets.vmctx_imported_globals())
);
assert_eq!(
offset_of!(VMContext, tables),
usize::from(offsets.vmctx_tables())
);
assert_eq!(
offset_of!(VMContext, memories),
usize::from(offsets.vmctx_memories())
);
assert_eq!(
offset_of!(VMContext, globals),
usize::from(offsets.vmctx_globals())
);
}
}
pub struct VMContext {}
impl VMContext {
/// Create a new `VMContext` instance.
pub fn new(
imported_functions: *const VMFunctionImport,
imported_tables: *const VMTableImport,
imported_memories: *const VMMemoryImport,
imported_globals: *const VMGlobalImport,
tables: *mut VMTableDefinition,
memories: *mut VMMemoryDefinition,
globals: *mut VMGlobalDefinition,
signature_ids: *mut VMSharedSignatureIndex,
) -> Self {
Self {
imported_functions,
imported_tables,
imported_memories,
imported_globals,
tables,
memories,
globals,
signature_ids,
}
}
/// Return a reference to imported function `index`.
pub unsafe fn imported_function(&self, index: FuncIndex) -> &VMFunctionImport {
&*self.imported_functions.add(index.index())
}
/// Return a reference to imported table `index`.
pub unsafe fn imported_table(&self, index: TableIndex) -> &VMTableImport {
&*self.imported_tables.add(index.index())
}
/// Return a reference to imported memory `index`.
pub unsafe fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport {
&*self.imported_memories.add(index.index())
}
/// Return a reference to imported global `index`.
pub unsafe fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport {
&*self.imported_globals.add(index.index())
}
/// Return a reference to locally-defined table `index`.
pub unsafe fn table(&self, index: DefinedTableIndex) -> &VMTableDefinition {
&*self.tables.add(index.index())
}
/// Return a mutable reference to locally-defined table `index`.
pub unsafe fn table_mut(&mut self, index: DefinedTableIndex) -> &mut VMTableDefinition {
&mut *self.tables.add(index.index())
}
/// Return a reference to locally-defined linear memory `index`.
pub unsafe fn memory(&self, index: DefinedMemoryIndex) -> &VMMemoryDefinition {
&*self.memories.add(index.index())
}
/// Return a mutable reference to locally-defined linear memory `index`.
pub unsafe fn memory_mut(&mut self, index: DefinedMemoryIndex) -> &mut VMMemoryDefinition {
&mut *self.memories.add(index.index())
}
/// Return a reference to locally-defined global variable `index`.
pub unsafe fn global(&self, index: DefinedGlobalIndex) -> &VMGlobalDefinition {
&*self.globals.add(index.index())
}
/// Return a mutable reference to locally-defined global variable `index`.
pub unsafe fn global_mut(&mut self, index: DefinedGlobalIndex) -> &mut VMGlobalDefinition {
&mut *self.globals.add(index.index())
}
/// Return a mutable reference to the associated `Instance`.
#[allow(clippy::cast_ptr_alignment)]
pub unsafe fn instance(&mut self) -> &mut Instance {
&mut *((self as *mut Self as *mut u8).offset(-Instance::vmctx_offset()) as *mut Instance)
}
/// Return the table index for the given `VMTableDefinition`.
pub fn table_index(&self, table: &mut VMTableDefinition) -> DefinedTableIndex {
// TODO: Use `offset_from` once it stablizes.
let begin = self.tables;
let end: *mut VMTableDefinition = table;
DefinedTableIndex::new(
(end as usize - begin as usize) / mem::size_of::<VMTableDefinition>(),
)
}
/// Return the memory index for the given `VMMemoryDefinition`.
pub fn memory_index(&self, memory: &mut VMMemoryDefinition) -> DefinedMemoryIndex {
// TODO: Use `offset_from` once it stablizes.
let begin = self.memories;
let end: *mut VMMemoryDefinition = memory;
DefinedMemoryIndex::new(
(end as usize - begin as usize) / mem::size_of::<VMMemoryDefinition>(),
)
pub(crate) unsafe fn instance_contents(&mut self) -> &mut InstanceContents {
&mut *((self as *mut Self as *mut u8).offset(-InstanceContents::vmctx_offset())
as *mut InstanceContents)
}
}

View File

@@ -45,7 +45,7 @@ extern "C" fn spectest_print_f64_f64(x: f64, y: f64) {
/// Return an instance implementing the "spectest" interface used in the
/// spec testsuite.
pub fn instantiate_spectest() -> Result<Box<Instance>, InstantiationError> {
pub fn instantiate_spectest() -> Result<Instance, InstantiationError> {
let call_conv = isa::CallConv::triple_default(&HOST);
let pointer_type = types::Type::triple_pointer_type(&HOST);
let mut module = Module::new();

View File

@@ -111,7 +111,7 @@ impl WastContext {
}
}
fn instantiate(&mut self, module: ModuleBinary) -> Result<Box<Instance>, SetupError> {
fn instantiate(&mut self, module: ModuleBinary) -> Result<Instance, SetupError> {
let data = module.into_vec();
self.validate(&data).map_err(SetupError::Validate)?;