diff --git a/src/runtime/backing.rs b/src/runtime/backing.rs index a12ccc3e8..f326f4b86 100644 --- a/src/runtime/backing.rs +++ b/src/runtime/backing.rs @@ -10,8 +10,8 @@ use crate::runtime::{ #[derive(Debug)] pub struct LocalBacking { - memories: Box<[LinearMemory]>, - tables: Box<[TableBacking]>, + pub memories: Box<[LinearMemory]>, + pub tables: Box<[TableBacking]>, pub vm_memories: Box<[vm::LocalMemory]>, pub vm_tables: Box<[vm::LocalTable]>, diff --git a/src/runtime/instance.rs b/src/runtime/instance.rs index a1d9cb537..ed595dc06 100644 --- a/src/runtime/instance.rs +++ b/src/runtime/instance.rs @@ -14,7 +14,7 @@ use std::iter; use std::sync::Arc; pub struct Instance { - backing: LocalBacking, + pub (in crate::runtime) backing: LocalBacking, import_backing: ImportBacking, sig_registry: SigRegistry, pub module: Arc, @@ -43,6 +43,26 @@ impl Instance { Ok(instance) } + /// Call an exported webassembly function given the export name. + /// Pass arguments by wrapping each one in the `Val` enum. + /// The returned value is also returned in a `Val`. + /// + /// This will eventually return `Result>, String>` in + /// order to support multi-value returns. + pub fn call(&mut self, name: &str, args: &[Val]) -> Result, String> { + let func_index = *self + .module + .exports + .get(name) + .ok_or_else(|| "there is no export with that name".to_string()) + .and_then(|export| match export { + Export::Func(func_index) => Ok(func_index), + _ => Err("that export is not a function".to_string()), + })?; + + self.call_with_index(func_index, args) + } + fn call_with_index( &mut self, func_index: FuncIndex, @@ -54,15 +74,18 @@ impl Instance { .signature_assoc .get(func_index) .expect("broken invariant, incorrect func index"); - let signature = &self.module.signatures[sig_index]; + + { + let signature = &self.module.signatures[sig_index]; - assert!( - signature.returns.len() <= 1, - "multi-value returns not yet supported" - ); + assert!( + signature.returns.len() <= 1, + "multi-value returns not yet supported" + ); - if !signature.check_sig(args) { - return Err("incorrect signature".to_string()); + if !signature.check_sig(args) { + return Err("incorrect signature".to_string()); + } } // the vmctx will be located at the same place on the stack the entire time that this @@ -93,7 +116,7 @@ impl Instance { ); call_protected(|| { - signature + self.module.signatures[sig_index] .returns .first() .map(|ty| match ty { @@ -111,26 +134,6 @@ impl Instance { }) }) } - - /// Call an exported webassembly function given the export name. - /// Pass arguments by wrapping each one in the `Val` enum. - /// The returned value is also returned in a `Val`. - /// - /// This will eventually return `Result>, String>` in - /// order to support multi-value returns. - pub fn call(&mut self, name: &str, args: &[Val]) -> Result, String> { - let func_index = *self - .module - .exports - .get(name) - .ok_or_else(|| "there is no export with that name".to_string()) - .and_then(|export| match export { - Export::Func(func_index) => Ok(func_index), - _ => Err("that export is not a function".to_string()), - })?; - - self.call_with_index(func_index, args) - } } #[derive(Debug)] diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index ac5e3941b..e6ae9bed3 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -7,6 +7,7 @@ mod sig_registry; mod table; pub mod types; pub mod vm; +pub mod vmcalls; pub use self::backend::Compiler; pub use self::instance::{Import, Imports, Instance}; diff --git a/src/runtime/vm.rs b/src/runtime/vm.rs index 999e38dc4..ea5b383c1 100644 --- a/src/runtime/vm.rs +++ b/src/runtime/vm.rs @@ -1,8 +1,4 @@ use crate::runtime::{ - // types::{ - // MemoryIndex, TableIndex, GlobalIndex, FuncIndex, - // SigIndex, - // }, backing::{ImportBacking, LocalBacking}, sig_registry::SigRegistry, }; @@ -34,6 +30,9 @@ pub struct Ctx { /// Signature identifiers for signature-checked indirect calls. pub signatures: *const SigId, + + /// The parent instance. + pub local_backing: *mut LocalBacking, } impl Ctx { @@ -53,6 +52,7 @@ impl Ctx { imported_funcs: import_backing.functions.as_mut_ptr(), signatures: sig_registry.into_vm_signatures(), + local_backing: local_backing, } } diff --git a/src/runtime/vmcalls.rs b/src/runtime/vmcalls.rs new file mode 100644 index 000000000..0fea38970 --- /dev/null +++ b/src/runtime/vmcalls.rs @@ -0,0 +1,18 @@ +use crate::runtime::{ + vm, + memory::LinearMemory, +}; + +pub unsafe extern fn memory_grow_static(memory_index: u32, by_pages: u32, ctx: *mut vm::Ctx) -> i32 { + if let Some(old) = (*(*ctx).local_backing).memories[memory_index as usize].grow_static(by_pages) { + // Store the new size back into the vmctx. + (*(*ctx).memories.add(memory_index as usize)).size = (old as usize + by_pages as usize) * LinearMemory::PAGE_SIZE as usize; + old + } else { + -1 + } +} + +pub unsafe extern fn memory_size(memory_index: u32, ctx: *mut vm::Ctx) -> u32 { + (*(*ctx).local_backing).memories[memory_index as usize].current_pages() +} \ No newline at end of file