Move Instance's module field into InstanceContents.
This commit is contained in:
@@ -184,6 +184,9 @@ fn global_mut<'vmctx>(
|
|||||||
/// FIXME: Should this be pub(crate)?
|
/// FIXME: Should this be pub(crate)?
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct InstanceContents {
|
pub struct InstanceContents {
|
||||||
|
/// The `Module` this `Instance` was instantiated from.
|
||||||
|
module: Rc<Module>,
|
||||||
|
|
||||||
/// Offsets in the `vmctx` region.
|
/// Offsets in the `vmctx` region.
|
||||||
offsets: VMOffsets,
|
offsets: VMOffsets,
|
||||||
|
|
||||||
@@ -204,7 +207,7 @@ pub struct InstanceContents {
|
|||||||
/// Hosts can store arbitrary per-instance information here.
|
/// Hosts can store arbitrary per-instance information here.
|
||||||
host_state: Box<dyn Any>,
|
host_state: Box<dyn Any>,
|
||||||
|
|
||||||
/// Context pointer used by compiled wasm code. This field is last, and
|
/// Additional context used by compiled wasm code. This field is last, and
|
||||||
/// represents a dynamically-sized array that extends beyond the nominal
|
/// represents a dynamically-sized array that extends beyond the nominal
|
||||||
/// end of the struct (similar to a flexible array member).
|
/// end of the struct (similar to a flexible array member).
|
||||||
vmctx: VMContext,
|
vmctx: VMContext,
|
||||||
@@ -364,14 +367,10 @@ impl InstanceContents {
|
|||||||
self.vmctx_mut()
|
self.vmctx_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invoke_function(
|
fn invoke_function(&mut self, index: FuncIndex) -> Result<(), InstantiationError> {
|
||||||
&mut self,
|
|
||||||
module: &Module,
|
|
||||||
index: FuncIndex,
|
|
||||||
) -> Result<(), InstantiationError> {
|
|
||||||
// TODO: Check that the callee's calling convention matches what we expect.
|
// TODO: Check that the callee's calling convention matches what we expect.
|
||||||
|
|
||||||
let (callee_address, callee_vmctx) = match module.defined_func_index(index) {
|
let (callee_address, callee_vmctx) = match self.module.defined_func_index(index) {
|
||||||
Some(defined_index) => {
|
Some(defined_index) => {
|
||||||
let body = *self
|
let body = *self
|
||||||
.finished_functions
|
.finished_functions
|
||||||
@@ -380,7 +379,7 @@ impl InstanceContents {
|
|||||||
(body, self.vmctx_mut() as *mut VMContext)
|
(body, self.vmctx_mut() as *mut VMContext)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
assert!(index.index() < module.imported_funcs.len());
|
assert!(index.index() < self.module.imported_funcs.len());
|
||||||
let import = self.imported_function(index);
|
let import = self.imported_function(index);
|
||||||
(import.body, import.vmctx)
|
(import.body, import.vmctx)
|
||||||
}
|
}
|
||||||
@@ -392,34 +391,34 @@ impl InstanceContents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Invoke the WebAssembly start function of the instance, if one is present.
|
/// Invoke the WebAssembly start function of the instance, if one is present.
|
||||||
fn invoke_start_function(&mut self, module: &Module) -> Result<(), InstantiationError> {
|
fn invoke_start_function(&mut self) -> Result<(), InstantiationError> {
|
||||||
if let Some(start_index) = module.start_func {
|
if let Some(start_index) = self.module.start_func {
|
||||||
self.invoke_function(module, start_index)
|
self.invoke_function(start_index)
|
||||||
} else if let Some(start_export) = module.exports.get("_start") {
|
} else if let Some(start_export) = self.module.exports.get("_start") {
|
||||||
// As a compatibility measure, if the module doesn't have a start
|
// As a compatibility measure, if the module doesn't have a start
|
||||||
// function but does have a _start function exported, call that.
|
// function but does have a _start function exported, call that.
|
||||||
match start_export {
|
match start_export {
|
||||||
wasmtime_environ::Export::Function(func_index) => {
|
wasmtime_environ::Export::Function(func_index) => {
|
||||||
let sig = &module.signatures[module.functions[*func_index]];
|
let sig = &self.module.signatures[self.module.functions[*func_index]];
|
||||||
// No wasm params or returns; just the vmctx param.
|
// No wasm params or returns; just the vmctx param.
|
||||||
if sig.params.len() == 1 && sig.returns.is_empty() {
|
if sig.params.len() == 1 && sig.returns.is_empty() {
|
||||||
self.invoke_function(module, *func_index)
|
self.invoke_function(*func_index)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
} else if let Some(main_export) = module.exports.get("main") {
|
} else if let Some(main_export) = self.module.exports.get("main") {
|
||||||
// As a further compatibility measure, if the module doesn't have a
|
// As a further compatibility measure, if the module doesn't have a
|
||||||
// start function or a _start function exported, but does have a main
|
// start function or a _start function exported, but does have a main
|
||||||
// function exported, call that.
|
// function exported, call that.
|
||||||
match main_export {
|
match main_export {
|
||||||
wasmtime_environ::Export::Function(func_index) => {
|
wasmtime_environ::Export::Function(func_index) => {
|
||||||
let sig = &module.signatures[module.functions[*func_index]];
|
let sig = &self.module.signatures[self.module.functions[*func_index]];
|
||||||
// No wasm params or returns; just the vmctx param.
|
// No wasm params or returns; just the vmctx param.
|
||||||
if sig.params.len() == 1 && sig.returns.is_empty() {
|
if sig.params.len() == 1 && sig.returns.is_empty() {
|
||||||
self.invoke_function(module, *func_index)
|
self.invoke_function(*func_index)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -584,9 +583,6 @@ impl Drop for MmapField {
|
|||||||
/// Note that compiled wasm code passes around raw pointers to `Instance`, so
|
/// Note that compiled wasm code passes around raw pointers to `Instance`, so
|
||||||
/// this shouldn't be moved.
|
/// this shouldn't be moved.
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
/// The `Module` this `Instance` was instantiated from.
|
|
||||||
module: Rc<Module>,
|
|
||||||
|
|
||||||
/// The `Mmap` containing the contents of the instance.
|
/// The `Mmap` containing the contents of the instance.
|
||||||
mmap_field: MmapField,
|
mmap_field: MmapField,
|
||||||
}
|
}
|
||||||
@@ -632,6 +628,7 @@ impl Instance {
|
|||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
let contents_ptr = contents_mmap.as_mut_ptr() as *mut InstanceContents;
|
let contents_ptr = contents_mmap.as_mut_ptr() as *mut InstanceContents;
|
||||||
let contents = InstanceContents {
|
let contents = InstanceContents {
|
||||||
|
module,
|
||||||
global_exports,
|
global_exports,
|
||||||
offsets,
|
offsets,
|
||||||
memories,
|
memories,
|
||||||
@@ -690,16 +687,16 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check initializer bounds before initializing anything.
|
// Check initializer bounds before initializing anything.
|
||||||
check_table_init_bounds(&*module, contents)?;
|
check_table_init_bounds(contents)?;
|
||||||
check_memory_init_bounds(&*module, contents, data_initializers)?;
|
check_memory_init_bounds(contents, data_initializers)?;
|
||||||
|
|
||||||
// Apply the initializers.
|
// Apply the initializers.
|
||||||
initialize_tables(&*module, contents)?;
|
initialize_tables(contents)?;
|
||||||
initialize_memories(&*module, contents, data_initializers)?;
|
initialize_memories(contents, data_initializers)?;
|
||||||
initialize_globals(&*module, contents);
|
initialize_globals(contents);
|
||||||
|
|
||||||
// Collect the exports for the global export map.
|
// Collect the exports for the global export map.
|
||||||
for (field, decl) in &module.exports {
|
for (field, decl) in &contents.module.exports {
|
||||||
use std::collections::hash_map::Entry::*;
|
use std::collections::hash_map::Entry::*;
|
||||||
let cell: &RefCell<HashMap<std::string::String, core::option::Option<Export>>> =
|
let cell: &RefCell<HashMap<std::string::String, core::option::Option<Export>>> =
|
||||||
contents.global_exports.borrow();
|
contents.global_exports.borrow();
|
||||||
@@ -708,7 +705,7 @@ impl Instance {
|
|||||||
match map.entry(field.to_string()) {
|
match map.entry(field.to_string()) {
|
||||||
Vacant(entry) => {
|
Vacant(entry) => {
|
||||||
entry.insert(Some(lookup_by_declaration(
|
entry.insert(Some(lookup_by_declaration(
|
||||||
&module,
|
&contents.module,
|
||||||
&mut contents.vmctx,
|
&mut contents.vmctx,
|
||||||
&contents.offsets,
|
&contents.offsets,
|
||||||
&contents.finished_functions,
|
&contents.finished_functions,
|
||||||
@@ -726,10 +723,9 @@ impl Instance {
|
|||||||
|
|
||||||
// The WebAssembly spec specifies that the start function is
|
// The WebAssembly spec specifies that the start function is
|
||||||
// invoked automatically at instantiation time.
|
// invoked automatically at instantiation time.
|
||||||
contents.invoke_start_function(&*module)?;
|
contents.invoke_start_function()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
module,
|
|
||||||
mmap_field: MmapField {
|
mmap_field: MmapField {
|
||||||
mmap: contents_mmap,
|
mmap: contents_mmap,
|
||||||
},
|
},
|
||||||
@@ -758,7 +754,7 @@ impl Instance {
|
|||||||
|
|
||||||
/// Lookup an export with the given name.
|
/// Lookup an export with the given name.
|
||||||
pub fn lookup(&mut self, field: &str) -> Option<Export> {
|
pub fn lookup(&mut self, field: &str) -> Option<Export> {
|
||||||
let export = if let Some(export) = self.module.exports.get(field) {
|
let export = if let Some(export) = self.mmap_field.contents().module.exports.get(field) {
|
||||||
export.clone()
|
export.clone()
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
@@ -784,7 +780,7 @@ impl Instance {
|
|||||||
pub fn lookup_by_declaration(&mut self, export: &wasmtime_environ::Export) -> Export {
|
pub fn lookup_by_declaration(&mut self, export: &wasmtime_environ::Export) -> Export {
|
||||||
let contents = self.mmap_field.contents_mut();
|
let contents = self.mmap_field.contents_mut();
|
||||||
lookup_by_declaration(
|
lookup_by_declaration(
|
||||||
&self.module,
|
&contents.module,
|
||||||
&mut contents.vmctx,
|
&mut contents.vmctx,
|
||||||
&contents.offsets,
|
&contents.offsets,
|
||||||
&contents.finished_functions,
|
&contents.finished_functions,
|
||||||
@@ -810,7 +806,7 @@ impl Instance {
|
|||||||
/// are export names, and the values are export declarations which can be
|
/// are export names, and the values are export declarations which can be
|
||||||
/// resolved `lookup_by_declaration`.
|
/// resolved `lookup_by_declaration`.
|
||||||
pub fn exports(&self) -> indexmap::map::Iter<String, wasmtime_environ::Export> {
|
pub fn exports(&self) -> indexmap::map::Iter<String, wasmtime_environ::Export> {
|
||||||
self.module.exports.iter()
|
self.mmap_field.contents().module.exports.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,15 +875,13 @@ fn lookup_by_declaration(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_table_init_bounds(
|
fn check_table_init_bounds(contents: &mut InstanceContents) -> Result<(), InstantiationError> {
|
||||||
module: &Module,
|
let module = Rc::clone(&contents.module);
|
||||||
contents: &mut InstanceContents,
|
|
||||||
) -> Result<(), InstantiationError> {
|
|
||||||
for init in &module.table_elements {
|
for init in &module.table_elements {
|
||||||
let start = get_table_init_start(init, module, contents);
|
let start = get_table_init_start(init, contents);
|
||||||
let slice = get_table_slice(
|
let slice = get_table_slice(
|
||||||
init,
|
init,
|
||||||
module,
|
&contents.module,
|
||||||
&mut contents.tables,
|
&mut contents.tables,
|
||||||
&contents.vmctx,
|
&contents.vmctx,
|
||||||
&contents.offsets,
|
&contents.offsets,
|
||||||
@@ -904,15 +898,11 @@ fn check_table_init_bounds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the offset for a memory data initializer.
|
/// Compute the offset for a memory data initializer.
|
||||||
fn get_memory_init_start(
|
fn get_memory_init_start(init: &DataInitializer<'_>, contents: &mut InstanceContents) -> usize {
|
||||||
init: &DataInitializer<'_>,
|
|
||||||
module: &Module,
|
|
||||||
contents: &mut InstanceContents,
|
|
||||||
) -> usize {
|
|
||||||
let mut start = init.location.offset;
|
let mut start = init.location.offset;
|
||||||
|
|
||||||
if let Some(base) = init.location.base {
|
if let Some(base) = init.location.base {
|
||||||
let global = if let Some(def_index) = module.defined_global_index(base) {
|
let global = if let Some(def_index) = contents.module.defined_global_index(base) {
|
||||||
contents.global_mut(def_index)
|
contents.global_mut(def_index)
|
||||||
} else {
|
} else {
|
||||||
contents.imported_global(base).from
|
contents.imported_global(base).from
|
||||||
@@ -926,11 +916,11 @@ fn get_memory_init_start(
|
|||||||
/// Return a byte-slice view of a memory's data.
|
/// Return a byte-slice view of a memory's data.
|
||||||
fn get_memory_slice<'contents>(
|
fn get_memory_slice<'contents>(
|
||||||
init: &DataInitializer<'_>,
|
init: &DataInitializer<'_>,
|
||||||
module: &Module,
|
|
||||||
contents: &'contents mut InstanceContents,
|
contents: &'contents mut InstanceContents,
|
||||||
) -> &'contents mut [u8] {
|
) -> &'contents mut [u8] {
|
||||||
let memory = if let Some(defined_memory_index) =
|
let memory = if let Some(defined_memory_index) = contents
|
||||||
module.defined_memory_index(init.location.memory_index)
|
.module
|
||||||
|
.defined_memory_index(init.location.memory_index)
|
||||||
{
|
{
|
||||||
contents.memory(defined_memory_index)
|
contents.memory(defined_memory_index)
|
||||||
} else {
|
} else {
|
||||||
@@ -944,13 +934,12 @@ fn get_memory_slice<'contents>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_memory_init_bounds(
|
fn check_memory_init_bounds(
|
||||||
module: &Module,
|
|
||||||
contents: &mut InstanceContents,
|
contents: &mut InstanceContents,
|
||||||
data_initializers: &[DataInitializer<'_>],
|
data_initializers: &[DataInitializer<'_>],
|
||||||
) -> Result<(), InstantiationError> {
|
) -> Result<(), InstantiationError> {
|
||||||
for init in data_initializers {
|
for init in data_initializers {
|
||||||
let start = get_memory_init_start(init, module, contents);
|
let start = get_memory_init_start(init, contents);
|
||||||
let mem_slice = get_memory_slice(init, module, contents);
|
let mem_slice = get_memory_slice(init, contents);
|
||||||
|
|
||||||
if mem_slice.get_mut(start..start + init.data.len()).is_none() {
|
if mem_slice.get_mut(start..start + init.data.len()).is_none() {
|
||||||
return Err(InstantiationError::Link(LinkError(
|
return Err(InstantiationError::Link(LinkError(
|
||||||
@@ -974,15 +963,11 @@ fn create_tables(module: &Module) -> BoxedSlice<DefinedTableIndex, Table> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the offset for a table element initializer.
|
/// Compute the offset for a table element initializer.
|
||||||
fn get_table_init_start(
|
fn get_table_init_start(init: &TableElements, contents: &mut InstanceContents) -> usize {
|
||||||
init: &TableElements,
|
|
||||||
module: &Module,
|
|
||||||
contents: &mut InstanceContents,
|
|
||||||
) -> usize {
|
|
||||||
let mut start = init.offset;
|
let mut start = init.offset;
|
||||||
|
|
||||||
if let Some(base) = init.base {
|
if let Some(base) = init.base {
|
||||||
let global = if let Some(def_index) = module.defined_global_index(base) {
|
let global = if let Some(def_index) = contents.module.defined_global_index(base) {
|
||||||
contents.global_mut(def_index)
|
contents.global_mut(def_index)
|
||||||
} else {
|
} else {
|
||||||
contents.imported_global(base).from
|
contents.imported_global(base).from
|
||||||
@@ -1013,16 +998,14 @@ fn get_table_slice<'contents>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize the table memory from the provided initializers.
|
/// Initialize the table memory from the provided initializers.
|
||||||
fn initialize_tables(
|
fn initialize_tables(contents: &mut InstanceContents) -> Result<(), InstantiationError> {
|
||||||
module: &Module,
|
|
||||||
contents: &mut InstanceContents,
|
|
||||||
) -> Result<(), InstantiationError> {
|
|
||||||
let vmctx: *mut VMContext = contents.vmctx_mut();
|
let vmctx: *mut VMContext = contents.vmctx_mut();
|
||||||
|
let module = Rc::clone(&contents.module);
|
||||||
for init in &module.table_elements {
|
for init in &module.table_elements {
|
||||||
let start = get_table_init_start(init, module, contents);
|
let start = get_table_init_start(init, contents);
|
||||||
let slice = get_table_slice(
|
let slice = get_table_slice(
|
||||||
init,
|
init,
|
||||||
module,
|
&contents.module,
|
||||||
&mut contents.tables,
|
&mut contents.tables,
|
||||||
&contents.vmctx,
|
&contents.vmctx,
|
||||||
&contents.offsets,
|
&contents.offsets,
|
||||||
@@ -1030,9 +1013,9 @@ fn initialize_tables(
|
|||||||
|
|
||||||
let subslice = &mut slice[start..start + init.elements.len()];
|
let subslice = &mut slice[start..start + init.elements.len()];
|
||||||
for (i, func_idx) in init.elements.iter().enumerate() {
|
for (i, func_idx) in init.elements.iter().enumerate() {
|
||||||
let callee_sig = module.functions[*func_idx];
|
let callee_sig = contents.module.functions[*func_idx];
|
||||||
let (callee_ptr, callee_vmctx) =
|
let (callee_ptr, callee_vmctx) =
|
||||||
if let Some(index) = module.defined_func_index(*func_idx) {
|
if let Some(index) = contents.module.defined_func_index(*func_idx) {
|
||||||
(contents.finished_functions[index], vmctx)
|
(contents.finished_functions[index], vmctx)
|
||||||
} else {
|
} else {
|
||||||
let imported_func =
|
let imported_func =
|
||||||
@@ -1066,13 +1049,12 @@ fn create_memories(
|
|||||||
|
|
||||||
/// Initialize the table memory from the provided initializers.
|
/// Initialize the table memory from the provided initializers.
|
||||||
fn initialize_memories(
|
fn initialize_memories(
|
||||||
module: &Module,
|
|
||||||
contents: &mut InstanceContents,
|
contents: &mut InstanceContents,
|
||||||
data_initializers: &[DataInitializer<'_>],
|
data_initializers: &[DataInitializer<'_>],
|
||||||
) -> Result<(), InstantiationError> {
|
) -> Result<(), InstantiationError> {
|
||||||
for init in data_initializers {
|
for init in data_initializers {
|
||||||
let start = get_memory_init_start(init, module, contents);
|
let start = get_memory_init_start(init, contents);
|
||||||
let mem_slice = get_memory_slice(init, module, contents);
|
let mem_slice = get_memory_slice(init, contents);
|
||||||
|
|
||||||
let to_init = &mut mem_slice[start..start + init.data.len()];
|
let to_init = &mut mem_slice[start..start + init.data.len()];
|
||||||
to_init.copy_from_slice(init.data);
|
to_init.copy_from_slice(init.data);
|
||||||
@@ -1094,7 +1076,8 @@ fn create_globals(module: &Module) -> BoxedSlice<DefinedGlobalIndex, VMGlobalDef
|
|||||||
vmctx_globals.into_boxed_slice()
|
vmctx_globals.into_boxed_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_globals(module: &Module, contents: &mut InstanceContents) {
|
fn initialize_globals(contents: &mut InstanceContents) {
|
||||||
|
let module = Rc::clone(&contents.module);
|
||||||
let num_imports = module.imported_globals.len();
|
let num_imports = module.imported_globals.len();
|
||||||
for (index, global) in module.globals.iter().skip(num_imports) {
|
for (index, global) in module.globals.iter().skip(num_imports) {
|
||||||
let def_index = module.defined_global_index(index).unwrap();
|
let def_index = module.defined_global_index(index).unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user