Add memory_grow*, memory_size vmcalls

This commit is contained in:
Lachlan Sneff 2018-12-27 00:58:16 -05:00
parent 0f3833fecb
commit 98c9ce5ed9
5 changed files with 57 additions and 35 deletions

View File

@ -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]>,

View File

@ -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<Module>,
@ -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<Option<Vec<Val>>, String>` in
/// order to support multi-value returns.
pub fn call(&mut self, name: &str, args: &[Val]) -> Result<Option<Val>, 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<Option<Vec<Val>>, String>` in
/// order to support multi-value returns.
pub fn call(&mut self, name: &str, args: &[Val]) -> Result<Option<Val>, 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)]

View File

@ -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};

View File

@ -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,
}
}

18
src/runtime/vmcalls.rs Normal file
View File

@ -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()
}