Rearrange some apis

This commit is contained in:
Lachlan Sneff
2019-01-12 17:52:14 -05:00
parent 60201ea7a6
commit a983e9ce8b
71 changed files with 16821 additions and 74919 deletions

View File

@ -205,7 +205,7 @@ fn import_memories(
}) => {
if expected_memory_desc.fits_in_imported(&memory_desc) {
memories.push(vm::ImportedMemory {
memory: local,
memory: local.inner(),
vmctx: match ctx {
Context::External(ctx) => ctx,
Context::Internal => vmctx,
@ -284,7 +284,7 @@ fn import_globals(
match import {
Some(Export::Global { local, global }) => {
if &global == global_desc {
globals.push(vm::ImportedGlobal { global: local });
globals.push(vm::ImportedGlobal { global: local.inner() });
} else {
return Err(format!(
"unexpected global description for {:?}:{:?}",

View File

@ -1,8 +1,10 @@
use crate::{
instance::FuncRef,
types::{FuncSig, GlobalDesc, Memory, Table},
module::ExportIndex,
vm,
Instance,
};
use hashbrown::hash_map;
#[derive(Debug, Copy, Clone)]
pub enum Context {
@ -13,22 +15,111 @@ pub enum Context {
#[derive(Debug, Clone)]
pub enum Export {
Function {
func: FuncRef,
func: FuncPointer,
ctx: Context,
signature: FuncSig,
},
Memory {
local: *mut vm::LocalMemory,
local: MemoryPointer,
ctx: Context,
memory: Memory,
},
Table {
local: *mut vm::LocalTable,
local: TablePointer,
ctx: Context,
table: Table,
},
Global {
local: *mut vm::LocalGlobal,
local: GlobalPointer,
global: GlobalDesc,
},
}
#[derive(Debug, Clone)]
pub struct FuncPointer(*const vm::Func);
impl FuncPointer {
/// This needs to be unsafe because there is
/// no way to check whether the passed function
/// is valid and has the right signature.
pub unsafe fn new(f: *const vm::Func) -> Self {
FuncPointer(f)
}
pub(crate) fn inner(&self) -> *const vm::Func {
self.0
}
}
#[derive(Debug, Clone)]
pub struct MemoryPointer(*mut vm::LocalMemory);
impl MemoryPointer {
/// This needs to be unsafe because there is
/// no way to check whether the passed function
/// is valid and has the right signature.
pub unsafe fn new(f: *mut vm::LocalMemory) -> Self {
MemoryPointer(f)
}
pub(crate) fn inner(&self) -> *mut vm::LocalMemory {
self.0
}
}
#[derive(Debug, Clone)]
pub struct TablePointer(*mut vm::LocalTable);
impl TablePointer {
/// This needs to be unsafe because there is
/// no way to check whether the passed function
/// is valid and has the right signature.
pub unsafe fn new(f: *mut vm::LocalTable) -> Self {
TablePointer(f)
}
pub(crate) fn inner(&self) -> *mut vm::LocalTable {
self.0
}
}
#[derive(Debug, Clone)]
pub struct GlobalPointer(*mut vm::LocalGlobal);
impl GlobalPointer {
/// This needs to be unsafe because there is
/// no way to check whether the passed function
/// is valid and has the right signature.
pub unsafe fn new(f: *mut vm::LocalGlobal) -> Self {
GlobalPointer(f)
}
pub(crate) fn inner(&self) -> *mut vm::LocalGlobal {
self.0
}
}
pub struct ExportIter<'a> {
instance: &'a Instance,
iter: hash_map::Iter<'a, String, ExportIndex>,
}
impl<'a> ExportIter<'a> {
pub(crate) fn new(instance: &'a Instance) -> Self {
Self {
instance,
iter: instance.module.exports.iter(),
}
}
}
impl<'a> Iterator for ExportIter<'a> {
type Item = (String, Export);
fn next(&mut self) -> Option<(String, Export)> {
let (name, export_index) = self.iter.next()?;
Some((
name.clone(),
self.instance.get_export_from_index(export_index),
))
}
}

View File

@ -1,19 +1,17 @@
use crate::recovery::call_protected;
use crate::{
backing::{ImportBacking, LocalBacking},
export::{Context, Export},
export::{Context, Export, ExportIter, FuncPointer, MemoryPointer},
import::{ImportResolver, Namespace},
module::{ExportIndex, Module},
types::{FuncIndex, FuncSig, MapIndex, Memory, MemoryIndex, Type, Value},
vm,
};
use hashbrown::hash_map;
use libffi::high::{arg as libffi_arg, call as libffi_call, CodePtr};
use std::rc::Rc;
use std::{iter, mem};
pub struct Instance {
pub module: Module,
struct InstanceInner {
#[allow(dead_code)]
pub(crate) backing: LocalBacking,
#[allow(dead_code)]
@ -22,11 +20,16 @@ pub struct Instance {
vmctx: Box<vm::Ctx>,
}
pub struct Instance {
pub module: Module,
inner: Box<InstanceInner>,
}
impl Instance {
pub(crate) fn new(
module: Module,
imports: Rc<dyn ImportResolver>,
) -> Result<Box<Instance>, String> {
) -> Result<Instance, String> {
// 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.
@ -36,8 +39,7 @@ impl Instance {
let backing = LocalBacking::new(&module, &import_backing, &mut *vmctx);
// When Pin is stablized, this will use `Box::pinned` instead of `Box::new`.
let mut instance = Box::new(Instance {
module,
let mut inner = Box::new(InstanceInner {
backing,
imports,
import_backing,
@ -46,7 +48,12 @@ impl Instance {
// Initialize the vm::Ctx in-place after the import_backing
// has been boxed.
*instance.vmctx = vm::Ctx::new(&mut instance.backing, &mut instance.import_backing);
*inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing);
let mut instance = Instance {
module,
inner,
};
if let Some(start_index) = instance.module.start_func {
instance.call_with_index(start_index, &[])?;
@ -77,6 +84,12 @@ impl Instance {
self.call_with_index(func_index, args)
}
pub fn exports(&self) -> ExportIter {
ExportIter::new(self)
}
}
impl Instance {
fn call_with_index(
&mut self,
func_index: FuncIndex,
@ -87,7 +100,7 @@ impl Instance {
let func_ptr = CodePtr::from_ptr(func_ref.inner() as _);
let vmctx_ptr = match ctx {
Context::External(vmctx) => vmctx,
Context::Internal => &mut *self.vmctx,
Context::Internal => &mut *self.inner.vmctx,
};
assert!(
@ -130,11 +143,7 @@ impl Instance {
})
}
pub fn exports(&self) -> ExportIter {
ExportIter::new(self)
}
fn get_export_from_index(&self, export_index: &ExportIndex) -> Export {
pub(crate) fn get_export_from_index(&self, export_index: &ExportIndex) -> Export {
match export_index {
ExportIndex::Func(func_index) => {
let (func, ctx, signature) = self.get_func_from_index(*func_index);
@ -143,7 +152,7 @@ impl Instance {
func,
ctx: match ctx {
Context::Internal => {
Context::External(&*self.vmctx as *const vm::Ctx as *mut vm::Ctx)
Context::External(&*self.inner.vmctx as *const vm::Ctx as *mut vm::Ctx)
}
ctx @ Context::External(_) => ctx,
},
@ -156,7 +165,7 @@ impl Instance {
local,
ctx: match ctx {
Context::Internal => {
Context::External(&*self.vmctx as *const vm::Ctx as *mut vm::Ctx)
Context::External(&*self.inner.vmctx as *const vm::Ctx as *mut vm::Ctx)
}
ctx @ Context::External(_) => ctx,
},
@ -168,7 +177,7 @@ impl Instance {
}
}
fn get_func_from_index(&self, func_index: FuncIndex) -> (FuncRef, Context, FuncSig) {
fn get_func_from_index(&self, func_index: FuncIndex) -> (FuncPointer, Context, FuncSig) {
let sig_index = *self
.module
.func_assoc
@ -176,7 +185,7 @@ impl Instance {
.expect("broken invariant, incorrect func index");
let (func_ptr, ctx) = if self.module.is_imported_function(func_index) {
let imported_func = &self.import_backing.functions[func_index.index()];
let imported_func = &self.inner.import_backing.functions[func_index.index()];
(
imported_func.func as *const _,
Context::External(imported_func.vmctx),
@ -195,13 +204,13 @@ impl Instance {
let signature = self.module.sig_registry.lookup_func_sig(sig_index).clone();
(FuncRef(func_ptr), ctx, signature)
(unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
}
fn get_memory_from_index(
&self,
mem_index: MemoryIndex,
) -> (*mut vm::LocalMemory, Context, Memory) {
) -> (MemoryPointer, Context, Memory) {
if self.module.is_imported_memory(mem_index) {
let &(_, mem) = &self
.module
@ -209,14 +218,12 @@ impl Instance {
.get(mem_index)
.expect("missing imported memory index");
let vm::ImportedMemory { memory, vmctx } =
&self.import_backing.memories[mem_index.index()];
(*memory, Context::External(*vmctx), *mem)
&self.inner.import_backing.memories[mem_index.index()];
(unsafe { MemoryPointer::new(*memory) }, Context::External(*vmctx), *mem)
} else {
// let vm_mem = .memories[mem_index.index() as usize];
let vm_mem =
unsafe { &mut (*self.vmctx.local_backing).memories[mem_index.index() as usize] };
let vm_mem = &self.inner.backing.memories[mem_index.index() as usize];
(
&mut vm_mem.into_vm_memory(),
unsafe { MemoryPointer::new(&mut vm_mem.into_vm_memory()) },
Context::Internal,
*self
.module
@ -228,7 +235,7 @@ impl Instance {
}
}
impl Namespace for Box<Instance> {
impl Namespace for Instance {
fn get_export(&self, name: &str) -> Option<Export> {
let export_index = self.module.exports.get(name)?;
@ -236,47 +243,6 @@ impl Namespace for Box<Instance> {
}
}
#[derive(Debug, Clone)]
pub struct FuncRef(*const vm::Func);
impl FuncRef {
/// This needs to be unsafe because there is
/// no way to check whether the passed function
/// is valid and has the right signature.
pub unsafe fn new(f: *const vm::Func) -> Self {
FuncRef(f)
}
pub(crate) fn inner(&self) -> *const vm::Func {
self.0
}
}
pub struct ExportIter<'a> {
instance: &'a Instance,
iter: hash_map::Iter<'a, String, ExportIndex>,
}
impl<'a> ExportIter<'a> {
fn new(instance: &'a Instance) -> Self {
Self {
instance,
iter: instance.module.exports.iter(),
}
}
}
impl<'a> Iterator for ExportIter<'a> {
type Item = (String, Export);
fn next(&mut self) -> Option<(String, Export)> {
let (name, export_index) = self.iter.next()?;
Some((
name.clone(),
self.instance.get_export_from_index(export_index),
))
}
}
// TODO Remove this later, only needed for compilation till emscripten is updated
impl Instance {
pub fn memory_offset_addr(&self, _index: usize, _offset: usize) -> *const usize {

View File

@ -4,24 +4,23 @@ extern crate field_offset;
#[macro_use]
mod macros;
pub mod backend;
mod backing;
pub mod export;
pub mod import;
mod instance;
mod memory;
mod mmap;
pub mod module;
mod recovery;
mod sig_registry;
mod sighandler;
pub mod backend;
pub mod export;
pub mod import;
pub mod module;
pub mod memory;
pub mod table;
pub mod types;
pub mod vm;
pub mod vmcalls;
pub use self::instance::{FuncRef, Instance};
pub use self::memory::LinearMemory;
pub use self::instance::Instance;
/// Compile a webassembly module using the provided compiler.
pub fn compile(wasm: &[u8], compiler: &dyn backend::Compiler) -> Result<module::Module, String> {

View File

@ -1,4 +1,3 @@
#[macro_export]
macro_rules! debug {
($fmt:expr) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt), line!()) });
($fmt:expr, $($arg:tt)*) => (if cfg!(any(debug_assertions, feature="debug")) { println!(concat!("wasmer-runtime(:{})::", $fmt, "\n"), line!(), $($arg)*) });

View File

@ -8,7 +8,7 @@ use std::ops::{Deref, DerefMut};
use crate::{
mmap::{Mmap, Protect},
types::Memory,
vm::LocalMemory,
vm,
};
/// A linear memory instance.
@ -38,16 +38,16 @@ pub struct LinearMemory {
/// It holds the raw bytes of memory accessed by a WebAssembly Instance
impl LinearMemory {
pub const PAGE_SIZE: u32 = 65_536;
pub const MAX_PAGES: u32 = 65_536;
pub(crate) const PAGE_SIZE: u32 = 65_536;
pub(crate) const MAX_PAGES: u32 = 65_536;
pub const DEFAULT_HEAP_SIZE: usize = 1 << 32; // 4 GiB
pub const DEFAULT_GUARD_SIZE: usize = 1 << 31; // 2 GiB
pub const DEFAULT_SIZE: usize = Self::DEFAULT_HEAP_SIZE + Self::DEFAULT_GUARD_SIZE; // 6 GiB
pub(crate) const DEFAULT_SIZE: usize = Self::DEFAULT_HEAP_SIZE + Self::DEFAULT_GUARD_SIZE; // 6 GiB
/// Create a new linear memory instance with specified initial and maximum number of pages.
///
/// `maximum` cannot be set to more than `65536` pages.
pub fn new(mem: &Memory) -> Self {
pub(crate) fn new(mem: &Memory) -> Self {
assert!(mem.min <= Self::MAX_PAGES);
assert!(mem.max.is_none() || mem.max.unwrap() <= Self::MAX_PAGES);
debug!("Instantiate LinearMemory(mem: {:?})", mem);
@ -92,7 +92,7 @@ impl LinearMemory {
}
/// Returns an base address of this linear memory.
fn base(&mut self) -> *mut u8 {
fn base(&self) -> *mut u8 {
self.mmap.as_ptr()
}
@ -110,8 +110,8 @@ impl LinearMemory {
self.max.unwrap_or(Self::MAX_PAGES)
}
pub(crate) fn into_vm_memory(&mut self) -> LocalMemory {
LocalMemory {
pub(crate) fn into_vm_memory(&self) -> vm::LocalMemory {
vm::LocalMemory {
base: self.base(),
size: self.size(),
}

View File

@ -43,7 +43,7 @@ impl Module {
}
/// Instantiate a webassembly module with the provided imports.
pub fn instantiate(&self, imports: Rc<dyn ImportResolver>) -> Result<Box<Instance>, String> {
pub fn instantiate(&self, imports: Rc<dyn ImportResolver>) -> Result<Instance, String> {
Instance::new(Module(Rc::clone(&self.0)), imports)
}
}