2019-01-08 17:09:47 +00:00
|
|
|
use crate::{
|
2019-01-18 20:13:01 +00:00
|
|
|
backend::Token,
|
2019-01-08 17:09:47 +00:00
|
|
|
backing::{ImportBacking, LocalBacking},
|
2019-01-23 23:30:35 +00:00
|
|
|
error::{CallError, CallResult, ResolveError, ResolveResult, Result},
|
2019-01-25 23:28:54 +00:00
|
|
|
export::{Context, Export, ExportIter, FuncPointer, GlobalPointer, TablePointer},
|
2019-01-21 22:43:04 +00:00
|
|
|
import::{ImportObject, LikeNamespace},
|
2019-01-25 23:28:54 +00:00
|
|
|
memory::Memory,
|
2019-01-13 03:02:19 +00:00
|
|
|
module::{ExportIndex, Module, ModuleInner},
|
2019-01-13 22:45:36 +00:00
|
|
|
types::{
|
2019-01-25 23:28:54 +00:00
|
|
|
FuncIndex, FuncSig, GlobalDesc, GlobalIndex, LocalOrImport, MemoryIndex, TableDesc,
|
2019-01-18 21:29:43 +00:00
|
|
|
TableIndex, Value,
|
2019-01-13 22:45:36 +00:00
|
|
|
},
|
2019-01-08 17:09:47 +00:00
|
|
|
vm,
|
|
|
|
};
|
2019-01-23 23:30:35 +00:00
|
|
|
use std::{mem, rc::Rc};
|
2019-01-08 17:09:47 +00:00
|
|
|
|
2019-01-13 21:44:14 +00:00
|
|
|
pub(crate) struct InstanceInner {
|
2019-01-11 03:59:57 +00:00
|
|
|
#[allow(dead_code)]
|
2019-01-08 17:09:47 +00:00
|
|
|
pub(crate) backing: LocalBacking,
|
|
|
|
import_backing: ImportBacking,
|
2019-01-11 03:59:57 +00:00
|
|
|
vmctx: Box<vm::Ctx>,
|
2019-01-08 17:09:47 +00:00
|
|
|
}
|
|
|
|
|
2019-01-23 20:34:15 +00:00
|
|
|
/// An instantiated WebAssembly module.
|
|
|
|
///
|
|
|
|
/// An `Instance` represents a WebAssembly module that
|
|
|
|
/// has been instantiated with an [`ImportObject`] and is
|
|
|
|
/// ready to be called.
|
|
|
|
///
|
|
|
|
/// [`ImportObject`]: struct.ImportObject.html
|
2019-01-12 22:52:14 +00:00
|
|
|
pub struct Instance {
|
2019-01-23 20:34:15 +00:00
|
|
|
module: Rc<ModuleInner>,
|
2019-01-12 22:52:14 +00:00
|
|
|
inner: Box<InstanceInner>,
|
2019-01-17 22:13:28 +00:00
|
|
|
#[allow(dead_code)]
|
2019-01-21 22:43:04 +00:00
|
|
|
imports: Box<ImportObject>,
|
2019-01-12 22:52:14 +00:00
|
|
|
}
|
|
|
|
|
2019-01-08 17:09:47 +00:00
|
|
|
impl Instance {
|
2019-01-21 22:43:04 +00:00
|
|
|
pub(crate) fn new(module: Rc<ModuleInner>, mut imports: Box<ImportObject>) -> Result<Instance> {
|
2019-01-11 03:59:57 +00:00
|
|
|
// We need the backing and import_backing to create a vm::Ctx, but we need
|
|
|
|
// a vm::Ctx to create a backing and an import_backing. The solution is to create an
|
|
|
|
// uninitialized vm::Ctx and then initialize it in-place.
|
|
|
|
let mut vmctx = unsafe { Box::new(mem::uninitialized()) };
|
2019-01-08 17:09:47 +00:00
|
|
|
|
2019-01-17 22:13:28 +00:00
|
|
|
let import_backing = ImportBacking::new(&module, &mut imports, &mut *vmctx)?;
|
2019-01-11 03:59:57 +00:00
|
|
|
let backing = LocalBacking::new(&module, &import_backing, &mut *vmctx);
|
2019-01-08 17:09:47 +00:00
|
|
|
|
2019-01-11 03:59:57 +00:00
|
|
|
// When Pin is stablized, this will use `Box::pinned` instead of `Box::new`.
|
2019-01-12 22:52:14 +00:00
|
|
|
let mut inner = Box::new(InstanceInner {
|
2019-01-08 17:09:47 +00:00
|
|
|
backing,
|
|
|
|
import_backing,
|
2019-01-11 03:59:57 +00:00
|
|
|
vmctx,
|
2019-01-08 17:09:47 +00:00
|
|
|
});
|
|
|
|
|
2019-01-12 23:02:47 +00:00
|
|
|
// Initialize the vm::Ctx in-place after the backing
|
2019-01-11 03:59:57 +00:00
|
|
|
// has been boxed.
|
2019-01-21 17:59:53 +00:00
|
|
|
*inner.vmctx =
|
|
|
|
unsafe { vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module) };
|
2019-01-12 22:52:14 +00:00
|
|
|
|
2019-01-17 22:13:28 +00:00
|
|
|
let mut instance = Instance {
|
|
|
|
module,
|
|
|
|
inner,
|
|
|
|
imports,
|
|
|
|
};
|
2019-01-11 03:59:57 +00:00
|
|
|
|
|
|
|
if let Some(start_index) = instance.module.start_func {
|
2019-01-08 17:09:47 +00:00
|
|
|
instance.call_with_index(start_index, &[])?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(instance)
|
|
|
|
}
|
|
|
|
|
2019-01-23 23:30:35 +00:00
|
|
|
/// This returns the representation of a function that can be called
|
|
|
|
/// safely.
|
|
|
|
///
|
|
|
|
/// # Usage:
|
|
|
|
/// ```
|
|
|
|
/// # use wasmer_runtime_core::Instance;
|
2019-01-23 23:36:13 +00:00
|
|
|
/// # use wasmer_runtime_core::error::CallResult;
|
|
|
|
/// # fn call_foo(instance: &mut Instance) -> CallResult<()> {
|
2019-01-23 23:30:35 +00:00
|
|
|
/// instance
|
|
|
|
/// .func("foo")?
|
|
|
|
/// .call(&[])?;
|
2019-01-23 23:36:13 +00:00
|
|
|
/// # Ok(())
|
2019-01-23 23:30:35 +00:00
|
|
|
/// # }
|
|
|
|
/// ```
|
|
|
|
pub fn func(&mut self, name: &str) -> ResolveResult<Function> {
|
|
|
|
let export_index =
|
|
|
|
self.module
|
|
|
|
.exports
|
|
|
|
.get(name)
|
2019-01-24 00:51:34 +00:00
|
|
|
.ok_or_else(|| ResolveError::ExportNotFound {
|
2019-01-23 23:30:35 +00:00
|
|
|
name: name.to_string(),
|
|
|
|
})?;
|
|
|
|
|
|
|
|
if let ExportIndex::Func(func_index) = export_index {
|
|
|
|
let sig_index = *self
|
|
|
|
.module
|
|
|
|
.func_assoc
|
|
|
|
.get(*func_index)
|
|
|
|
.expect("broken invariant, incorrect func index");
|
|
|
|
let signature = self.module.sig_registry.lookup_func_sig(sig_index);
|
|
|
|
|
|
|
|
Ok(Function {
|
|
|
|
signature,
|
|
|
|
module: &self.module,
|
|
|
|
instance_inner: &mut self.inner,
|
|
|
|
func_index: *func_index,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
Err(ResolveError::ExportWrongType {
|
|
|
|
name: name.to_string(),
|
|
|
|
}
|
|
|
|
.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-08 17:09:47 +00:00
|
|
|
/// Call an exported webassembly function given the export name.
|
2019-01-23 20:34:15 +00:00
|
|
|
/// Pass arguments by wrapping each one in the [`Value`] enum.
|
|
|
|
/// The returned values are also each wrapped in a [`Value`].
|
2019-01-08 17:09:47 +00:00
|
|
|
///
|
2019-01-23 20:34:15 +00:00
|
|
|
/// [`Value`]: enum.Value.html
|
|
|
|
///
|
|
|
|
/// # Note:
|
2019-01-18 20:13:01 +00:00
|
|
|
/// This returns `CallResult<Vec<Value>>` in order to support
|
|
|
|
/// the future multi-value returns webassembly feature.
|
2019-01-23 20:34:15 +00:00
|
|
|
///
|
|
|
|
/// # Usage:
|
|
|
|
/// ```
|
|
|
|
/// # use wasmer_runtime_core::types::Value;
|
|
|
|
/// # use wasmer_runtime_core::error::Result;
|
|
|
|
/// # use wasmer_runtime_core::Instance;
|
|
|
|
/// # fn call_foo(instance: &mut Instance) -> Result<()> {
|
|
|
|
/// // ...
|
|
|
|
/// let results = instance.call("foo", &[Value::I32(42)])?;
|
|
|
|
/// // ...
|
|
|
|
/// # Ok(())
|
|
|
|
/// # }
|
|
|
|
/// ```
|
2019-01-18 20:13:01 +00:00
|
|
|
pub fn call(&mut self, name: &str, args: &[Value]) -> CallResult<Vec<Value>> {
|
2019-01-18 18:54:16 +00:00
|
|
|
let export_index =
|
|
|
|
self.module
|
|
|
|
.exports
|
|
|
|
.get(name)
|
2019-01-24 00:51:34 +00:00
|
|
|
.ok_or_else(|| ResolveError::ExportNotFound {
|
2019-01-18 18:54:16 +00:00
|
|
|
name: name.to_string(),
|
|
|
|
})?;
|
2019-01-11 03:59:57 +00:00
|
|
|
|
|
|
|
let func_index = if let ExportIndex::Func(func_index) = export_index {
|
|
|
|
*func_index
|
|
|
|
} else {
|
2019-01-23 23:30:35 +00:00
|
|
|
return Err(CallError::Resolve(ResolveError::ExportWrongType {
|
2019-01-18 18:54:16 +00:00
|
|
|
name: name.to_string(),
|
2019-01-23 23:30:35 +00:00
|
|
|
})
|
2019-01-18 18:54:16 +00:00
|
|
|
.into());
|
2019-01-11 03:59:57 +00:00
|
|
|
};
|
2019-01-08 17:09:47 +00:00
|
|
|
|
|
|
|
self.call_with_index(func_index, args)
|
|
|
|
}
|
|
|
|
|
2019-01-23 23:58:15 +00:00
|
|
|
/// Returns a immutable reference to the
|
|
|
|
/// [`Ctx`] used by this Instance.
|
|
|
|
///
|
|
|
|
/// [`Ctx`]: struct.Ctx.html
|
|
|
|
pub fn context(&self) -> &vm::Ctx {
|
|
|
|
&self.inner.vmctx
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a mutable reference to the
|
|
|
|
/// [`Ctx`] used by this Instance.
|
|
|
|
///
|
|
|
|
/// [`Ctx`]: struct.Ctx.html
|
|
|
|
pub fn context_mut(&mut self) -> &mut vm::Ctx {
|
|
|
|
&mut self.inner.vmctx
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a iterator over all of the items
|
|
|
|
/// exported from this instance.
|
2019-01-13 21:44:14 +00:00
|
|
|
pub fn exports(&mut self) -> ExportIter {
|
|
|
|
ExportIter::new(&self.module, &mut self.inner)
|
2019-01-12 22:52:14 +00:00
|
|
|
}
|
2019-01-13 03:02:19 +00:00
|
|
|
|
2019-01-23 23:58:15 +00:00
|
|
|
/// The module used to instantiate this Instance.
|
2019-01-13 03:02:19 +00:00
|
|
|
pub fn module(&self) -> Module {
|
|
|
|
Module::new(Rc::clone(&self.module))
|
|
|
|
}
|
2019-01-12 22:52:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Instance {
|
2019-01-18 20:13:01 +00:00
|
|
|
fn call_with_index(&mut self, func_index: FuncIndex, args: &[Value]) -> CallResult<Vec<Value>> {
|
|
|
|
let sig_index = *self
|
|
|
|
.module
|
|
|
|
.func_assoc
|
|
|
|
.get(func_index)
|
|
|
|
.expect("broken invariant, incorrect func index");
|
|
|
|
let signature = self.module.sig_registry.lookup_func_sig(sig_index);
|
2019-01-08 17:09:47 +00:00
|
|
|
|
2019-01-11 03:59:57 +00:00
|
|
|
if !signature.check_sig(args) {
|
2019-01-23 23:30:35 +00:00
|
|
|
Err(ResolveError::Signature {
|
2019-01-18 18:54:16 +00:00
|
|
|
expected: signature.clone(),
|
|
|
|
found: args.iter().map(|val| val.ty()).collect(),
|
|
|
|
})?
|
2019-01-11 03:59:57 +00:00
|
|
|
}
|
2019-01-08 17:09:47 +00:00
|
|
|
|
2019-01-18 20:13:01 +00:00
|
|
|
let vmctx = match func_index.local_or_import(&self.module) {
|
2019-01-18 21:29:43 +00:00
|
|
|
LocalOrImport::Local(_) => &mut *self.inner.vmctx,
|
2019-01-18 20:13:01 +00:00
|
|
|
LocalOrImport::Import(imported_func_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
self.inner.import_backing.vm_functions[imported_func_index].vmctx
|
2019-01-18 20:13:01 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let token = Token::generate();
|
|
|
|
|
2019-01-22 23:00:27 +00:00
|
|
|
let returns = self.module.protected_caller.call(
|
2019-01-18 20:13:01 +00:00
|
|
|
&self.module,
|
|
|
|
func_index,
|
|
|
|
args,
|
2019-01-18 21:29:43 +00:00
|
|
|
&self.inner.import_backing,
|
2019-01-18 20:13:01 +00:00
|
|
|
vmctx,
|
|
|
|
token,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(returns)
|
2019-01-08 17:09:47 +00:00
|
|
|
}
|
2019-01-13 21:44:14 +00:00
|
|
|
}
|
2019-01-11 03:59:57 +00:00
|
|
|
|
2019-01-13 21:44:14 +00:00
|
|
|
impl InstanceInner {
|
|
|
|
pub(crate) fn get_export_from_index(
|
|
|
|
&mut self,
|
|
|
|
module: &ModuleInner,
|
|
|
|
export_index: &ExportIndex,
|
|
|
|
) -> Export {
|
2019-01-11 03:59:57 +00:00
|
|
|
match export_index {
|
|
|
|
ExportIndex::Func(func_index) => {
|
2019-01-13 21:44:14 +00:00
|
|
|
let (func, ctx, signature) = self.get_func_from_index(module, *func_index);
|
2019-01-11 03:59:57 +00:00
|
|
|
|
|
|
|
Export::Function {
|
|
|
|
func,
|
|
|
|
ctx: match ctx {
|
2019-01-13 21:52:25 +00:00
|
|
|
Context::Internal => Context::External(&mut *self.vmctx),
|
2019-01-11 03:59:57 +00:00
|
|
|
ctx @ Context::External(_) => ctx,
|
|
|
|
},
|
|
|
|
signature,
|
|
|
|
}
|
|
|
|
}
|
2019-01-12 20:34:23 +00:00
|
|
|
ExportIndex::Memory(memory_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
let memory = self.get_memory_from_index(module, *memory_index);
|
|
|
|
Export::Memory(memory)
|
2019-01-12 20:34:23 +00:00
|
|
|
}
|
2019-01-13 22:45:36 +00:00
|
|
|
ExportIndex::Global(global_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
let (local, desc) = self.get_global_from_index(module, *global_index);
|
|
|
|
Export::Global { local, desc }
|
2019-01-13 22:45:36 +00:00
|
|
|
}
|
2019-01-13 16:46:04 +00:00
|
|
|
ExportIndex::Table(table_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
let (local, ctx, desc) = self.get_table_from_index(module, *table_index);
|
2019-01-13 16:46:04 +00:00
|
|
|
Export::Table {
|
|
|
|
local,
|
|
|
|
ctx: match ctx {
|
2019-01-13 21:52:25 +00:00
|
|
|
Context::Internal => Context::External(&mut *self.vmctx),
|
2019-01-13 16:46:04 +00:00
|
|
|
ctx @ Context::External(_) => ctx,
|
|
|
|
},
|
2019-01-25 23:28:54 +00:00
|
|
|
desc,
|
2019-01-13 16:46:04 +00:00
|
|
|
}
|
2019-01-13 21:52:25 +00:00
|
|
|
}
|
2019-01-11 03:59:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-13 21:44:14 +00:00
|
|
|
fn get_func_from_index(
|
|
|
|
&mut self,
|
|
|
|
module: &ModuleInner,
|
|
|
|
func_index: FuncIndex,
|
|
|
|
) -> (FuncPointer, Context, FuncSig) {
|
|
|
|
let sig_index = *module
|
2019-01-11 03:59:57 +00:00
|
|
|
.func_assoc
|
|
|
|
.get(func_index)
|
|
|
|
.expect("broken invariant, incorrect func index");
|
|
|
|
|
2019-01-16 18:26:10 +00:00
|
|
|
let (func_ptr, ctx) = match func_index.local_or_import(module) {
|
|
|
|
LocalOrImport::Local(local_func_index) => (
|
2019-01-13 21:44:14 +00:00
|
|
|
module
|
2019-01-11 03:59:57 +00:00
|
|
|
.func_resolver
|
2019-01-16 18:26:10 +00:00
|
|
|
.get(&module, local_func_index)
|
2019-01-11 03:59:57 +00:00
|
|
|
.expect("broken invariant, func resolver not synced with module.exports")
|
|
|
|
.cast()
|
|
|
|
.as_ptr() as *const _,
|
|
|
|
Context::Internal,
|
2019-01-16 18:26:10 +00:00
|
|
|
),
|
|
|
|
LocalOrImport::Import(imported_func_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
let imported_func = &self.import_backing.vm_functions[imported_func_index];
|
2019-01-16 18:26:10 +00:00
|
|
|
(
|
|
|
|
imported_func.func as *const _,
|
|
|
|
Context::External(imported_func.vmctx),
|
|
|
|
)
|
|
|
|
}
|
2019-01-11 03:59:57 +00:00
|
|
|
};
|
|
|
|
|
2019-01-13 21:44:14 +00:00
|
|
|
let signature = module.sig_registry.lookup_func_sig(sig_index).clone();
|
2019-01-11 03:59:57 +00:00
|
|
|
|
2019-01-12 22:52:14 +00:00
|
|
|
(unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
|
2019-01-11 03:59:57 +00:00
|
|
|
}
|
2019-01-12 20:34:23 +00:00
|
|
|
|
2019-01-25 23:28:54 +00:00
|
|
|
fn get_memory_from_index(&mut self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory {
|
2019-01-16 18:26:10 +00:00
|
|
|
match mem_index.local_or_import(module) {
|
2019-01-25 23:28:54 +00:00
|
|
|
LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(),
|
2019-01-16 18:26:10 +00:00
|
|
|
LocalOrImport::Import(imported_mem_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
self.import_backing.memories[imported_mem_index].clone()
|
2019-01-16 18:26:10 +00:00
|
|
|
}
|
2019-01-12 20:34:23 +00:00
|
|
|
}
|
|
|
|
}
|
2019-01-13 16:46:04 +00:00
|
|
|
|
2019-01-13 22:45:36 +00:00
|
|
|
fn get_global_from_index(
|
|
|
|
&mut self,
|
|
|
|
module: &ModuleInner,
|
|
|
|
global_index: GlobalIndex,
|
|
|
|
) -> (GlobalPointer, GlobalDesc) {
|
2019-01-16 18:26:10 +00:00
|
|
|
match global_index.local_or_import(module) {
|
|
|
|
LocalOrImport::Local(local_global_index) => {
|
|
|
|
let vm_global = &mut self.backing.vm_globals[local_global_index];
|
|
|
|
(
|
|
|
|
unsafe { GlobalPointer::new(vm_global) },
|
|
|
|
module
|
|
|
|
.globals
|
|
|
|
.get(local_global_index)
|
|
|
|
.expect("broken invariant, globals")
|
|
|
|
.desc,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
LocalOrImport::Import(imported_global_index) => {
|
2019-01-17 01:59:12 +00:00
|
|
|
let &(_, imported_global_desc) = &module
|
2019-01-16 18:26:10 +00:00
|
|
|
.imported_globals
|
|
|
|
.get(imported_global_index)
|
|
|
|
.expect("missing imported global index");
|
|
|
|
let vm::ImportedGlobal { global } =
|
2019-01-25 23:28:54 +00:00
|
|
|
&self.import_backing.vm_globals[imported_global_index];
|
2019-01-17 01:59:12 +00:00
|
|
|
(
|
|
|
|
unsafe { GlobalPointer::new(*global) },
|
|
|
|
*imported_global_desc,
|
|
|
|
)
|
2019-01-16 18:26:10 +00:00
|
|
|
}
|
2019-01-13 22:45:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-13 21:52:25 +00:00
|
|
|
fn get_table_from_index(
|
|
|
|
&mut self,
|
|
|
|
module: &ModuleInner,
|
|
|
|
table_index: TableIndex,
|
2019-01-25 23:28:54 +00:00
|
|
|
) -> (TablePointer, Context, TableDesc) {
|
2019-01-16 18:26:10 +00:00
|
|
|
match table_index.local_or_import(module) {
|
|
|
|
LocalOrImport::Local(local_table_index) => {
|
2019-01-18 22:18:06 +00:00
|
|
|
let vm_table = &mut self.backing.vm_tables[local_table_index];
|
2019-01-16 18:26:10 +00:00
|
|
|
(
|
2019-01-18 22:18:06 +00:00
|
|
|
unsafe { TablePointer::new(vm_table) },
|
2019-01-16 18:26:10 +00:00
|
|
|
Context::Internal,
|
|
|
|
*module
|
|
|
|
.tables
|
|
|
|
.get(local_table_index)
|
|
|
|
.expect("broken invariant, tables"),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
LocalOrImport::Import(imported_table_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
let &(_, desc) = &module
|
2019-01-16 18:26:10 +00:00
|
|
|
.imported_tables
|
|
|
|
.get(imported_table_index)
|
|
|
|
.expect("missing imported table index");
|
|
|
|
let vm::ImportedTable { table, vmctx } =
|
2019-01-25 23:28:54 +00:00
|
|
|
&self.import_backing.vm_tables[imported_table_index];
|
2019-01-16 18:26:10 +00:00
|
|
|
(
|
|
|
|
unsafe { TablePointer::new(*table) },
|
|
|
|
Context::External(*vmctx),
|
2019-01-25 23:28:54 +00:00
|
|
|
*desc,
|
2019-01-16 18:26:10 +00:00
|
|
|
)
|
|
|
|
}
|
2019-01-13 16:46:04 +00:00
|
|
|
}
|
|
|
|
}
|
2019-01-08 17:09:47 +00:00
|
|
|
}
|
|
|
|
|
2019-01-21 22:43:04 +00:00
|
|
|
impl LikeNamespace for Instance {
|
2019-01-13 21:44:14 +00:00
|
|
|
fn get_export(&mut self, name: &str) -> Option<Export> {
|
2019-01-12 21:24:17 +00:00
|
|
|
let export_index = self.module.exports.get(name)?;
|
|
|
|
|
2019-01-13 21:44:14 +00:00
|
|
|
Some(self.inner.get_export_from_index(&self.module, export_index))
|
2019-01-12 21:24:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-23 23:30:35 +00:00
|
|
|
/// A representation of an exported WebAssembly function.
|
|
|
|
pub struct Function<'a> {
|
|
|
|
signature: &'a FuncSig,
|
|
|
|
module: &'a ModuleInner,
|
|
|
|
instance_inner: &'a mut InstanceInner,
|
|
|
|
func_index: FuncIndex,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Function<'a> {
|
|
|
|
/// Call an exported webassembly function safely.
|
|
|
|
///
|
|
|
|
/// Pass arguments by wrapping each one in the [`Value`] enum.
|
|
|
|
/// The returned values are also each wrapped in a [`Value`].
|
|
|
|
///
|
|
|
|
/// [`Value`]: enum.Value.html
|
|
|
|
///
|
|
|
|
/// # Note:
|
|
|
|
/// This returns `CallResult<Vec<Value>>` in order to support
|
|
|
|
/// the future multi-value returns webassembly feature.
|
|
|
|
///
|
|
|
|
/// # Usage:
|
|
|
|
/// ```
|
|
|
|
/// # use wasmer_runtime_core::Instance;
|
2019-01-23 23:36:13 +00:00
|
|
|
/// # use wasmer_runtime_core::error::CallResult;
|
|
|
|
/// # fn call_foo(instance: &mut Instance) -> CallResult<()> {
|
2019-01-23 23:30:35 +00:00
|
|
|
/// instance
|
|
|
|
/// .func("foo")?
|
|
|
|
/// .call(&[])?;
|
2019-01-23 23:36:13 +00:00
|
|
|
/// # Ok(())
|
2019-01-23 23:30:35 +00:00
|
|
|
/// # }
|
|
|
|
/// ```
|
|
|
|
pub fn call(&mut self, params: &[Value]) -> CallResult<Vec<Value>> {
|
|
|
|
if !self.signature.check_sig(params) {
|
|
|
|
Err(ResolveError::Signature {
|
|
|
|
expected: self.signature.clone(),
|
|
|
|
found: params.iter().map(|val| val.ty()).collect(),
|
|
|
|
})?
|
|
|
|
}
|
|
|
|
|
|
|
|
let vmctx = match self.func_index.local_or_import(self.module) {
|
|
|
|
LocalOrImport::Local(_) => &mut *self.instance_inner.vmctx,
|
|
|
|
LocalOrImport::Import(imported_func_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
self.instance_inner.import_backing.vm_functions[imported_func_index].vmctx
|
2019-01-23 23:30:35 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let token = Token::generate();
|
|
|
|
|
|
|
|
let returns = self.module.protected_caller.call(
|
|
|
|
&self.module,
|
|
|
|
self.func_index,
|
|
|
|
params,
|
|
|
|
&self.instance_inner.import_backing,
|
|
|
|
vmctx,
|
|
|
|
token,
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(returns)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn signature(&self) -> &FuncSig {
|
|
|
|
self.signature
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn raw(&self) -> *const vm::Func {
|
|
|
|
match self.func_index.local_or_import(self.module) {
|
|
|
|
LocalOrImport::Local(local_func_index) => self
|
|
|
|
.module
|
|
|
|
.func_resolver
|
|
|
|
.get(self.module, local_func_index)
|
|
|
|
.unwrap()
|
|
|
|
.as_ptr(),
|
|
|
|
LocalOrImport::Import(import_func_index) => {
|
2019-01-25 23:28:54 +00:00
|
|
|
self.instance_inner.import_backing.vm_functions[import_func_index].func
|
2019-01-23 23:30:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-23 20:34:15 +00:00
|
|
|
#[doc(hidden)]
|
2019-01-10 01:45:48 +00:00
|
|
|
impl Instance {
|
2019-01-23 20:34:15 +00:00
|
|
|
pub fn memory_offset_addr(&self, _: u32, _: usize) -> *const u8 {
|
2019-01-16 11:41:06 +00:00
|
|
|
unimplemented!()
|
2019-01-10 01:45:48 +00:00
|
|
|
}
|
|
|
|
}
|