Add wip solution to wasm_extern_as_ no allocation

This commit is contained in:
Mark McCaskey
2021-03-23 09:01:01 -07:00
parent 4026b3ab99
commit 9868c0f297
9 changed files with 148 additions and 39 deletions

View File

@@ -2,17 +2,27 @@ use super::super::store::wasm_store_t;
use super::super::trap::wasm_trap_t;
use super::super::types::{wasm_functype_t, wasm_valkind_enum};
use super::super::value::{wasm_val_inner, wasm_val_t, wasm_val_vec_t};
use super::CApiExternTag;
use std::convert::TryInto;
use std::ffi::c_void;
use std::sync::Arc;
use wasmer::{Function, Instance, RuntimeError, Val};
use wasmer::{Function, RuntimeError, Val};
#[derive(Debug)]
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct wasm_func_t {
pub(crate) inner: Function,
// this is how we ensure the instance stays alive
pub(crate) instance: Option<Arc<Instance>>,
pub(crate) tag: CApiExternTag,
pub(crate) inner: Box<Function>,
}
impl wasm_func_t {
pub(crate) fn new(function: Function) -> Self {
Self {
tag: CApiExternTag::Function,
inner: Box::new(function),
}
}
}
#[allow(non_camel_case_types)]
@@ -80,10 +90,7 @@ pub unsafe extern "C" fn wasm_func_new(
};
let function = Function::new(&store.inner, func_sig, inner_callback);
Some(Box::new(wasm_func_t {
instance: None,
inner: function,
}))
Some(Box::new(wasm_func_t { inner: function }))
}
#[no_mangle]
@@ -172,10 +179,7 @@ pub unsafe extern "C" fn wasm_func_new_with_env(
trampoline,
);
Some(Box::new(wasm_func_t {
instance: None,
inner: function,
}))
Some(Box::new(wasm_func_t { inner: function }))
}
#[no_mangle]

View File

@@ -1,14 +1,25 @@
use super::super::store::wasm_store_t;
use super::super::types::wasm_globaltype_t;
use super::super::value::wasm_val_t;
use super::CApiExternTag;
use crate::error::update_last_error;
use std::convert::TryInto;
use wasmer::{Global, Val};
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct wasm_global_t {
// maybe needs to hold onto instance
pub(crate) inner: Global,
pub(crate) tag: CApiExternTag,
pub(crate) inner: Box<Global>,
}
impl wasm_global_t {
pub(crate) fn new(global: Global) -> Self {
Self {
tag: CApiExternTag::Global,
inner: Box::new(global),
}
}
}
#[no_mangle]

View File

@@ -1,12 +1,23 @@
use super::super::store::wasm_store_t;
use super::super::types::wasm_memorytype_t;
use super::CApiExternTag;
use std::mem;
use wasmer::{Memory, Pages};
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct wasm_memory_t {
// maybe needs to hold onto instance
pub(crate) inner: Memory,
pub(crate) tag: CApiExternTag,
pub(crate) inner: Box<Memory>,
}
impl wasm_memory_t {
pub(crate) fn new(memory: Memory) -> Self {
Self {
tag: CApiExternTag::Memory,
inner: Box::new(memory),
}
}
}
#[no_mangle]

View File

@@ -12,10 +12,94 @@ use wasmer::{Extern, Instance};
#[allow(non_camel_case_types)]
#[derive(Clone)]
#[repr(transparent)]
pub struct wasm_extern_t {
// this is how we ensure the instance stays alive
pub(crate) instance: Option<Arc<Instance>>,
pub(crate) inner: Extern,
pub(crate) inner: wasm_extern_inner,
}
/// All elements in this union must be `repr(C)` and have a
/// `CApiExternTag` as their first element.
pub(crate) union wasm_extern_inner {
function: wasm_func_t,
memory: wasm_memory_t,
global: wasm_global_t,
table: wasm_table_t,
}
#[cfg(test)]
mod extern_tests {
use super::*;
#[test]
fn externs_are_the_same_size() {
use std::mem::size_of;
assert_eq!(size_of::<wasm_extern_t>(), size_of::<wasm_func_t>());
assert_eq!(size_of::<wasm_extern_t>(), size_of::<wasm_memory_t>());
assert_eq!(size_of::<wasm_extern_t>(), size_of::<wasm_global_t>());
assert_eq!(size_of::<wasm_extern_t>(), size_of::<wasm_table_t>());
}
}
impl wasm_extern_t {
pub(crate) fn get_tag(&self) -> CApiExternTag {
unsafe { self.inner.function.tag }
}
pub(crate) fn ty(&self) -> ExternType {
match self.get_tag() {
CApiExternTag::Function => unsafe { self.inner.function.inner.ty() },
CApiExternTag::Memory => unsafe { self.inner.memory.inner.ty() },
CApiExternTag::Global => unsafe { self.inner.global.inner.ty() },
CApiExternTag::Table => unsafe { self.inner.table.inner.ty() },
}
}
}
impl From<Extern> for wasm_extern_t {
fn from(other: Extern) -> Self {
match other {
Extern::Function(function) => Self {
inner: wasm_extern_inner {
function: wasm_func_t::new(function),
},
},
Extern::Memory(memory) => Self {
inner: wasm_extern_inner {
memory: wasm_memory_t::new(memory),
},
},
Extern::Table(table) => Self {
inner: wasm_extern_inner {
table: wasm_table_t::new(table),
},
},
Extern::Global(global) => Self {
inner: wasm_extern_inner {
global: wasm_global_t::new(global),
},
},
}
}
}
impl From<wasm_extern_t> for Extern {
fn from(other: wasm_extern_t) -> Self {
match other.get_tag() {
CApiExternTag::Function => unsafe { self.inner.function.inner.clone().into() },
CApiExternTag::Memory => unsafe { self.inner.memory.inner.clone().into() },
CApiExternTag::Table => unsafe { self.inner.table.inner.clone().into() },
CApiExternTag::Global => unsafe { self.inner.global.inner.clone().into() },
}
}
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub(crate) enum CApiExternTag {
Function,
Global,
Table,
Memory,
}
wasm_declare_boxed_vec!(extern);

View File

@@ -1,11 +1,22 @@
use super::super::store::wasm_store_t;
use super::super::types::{wasm_ref_t, wasm_table_size_t, wasm_tabletype_t};
use super::CApiExternTag;
use wasmer::Table;
#[allow(non_camel_case_types)]
#[repr(C)]
pub struct wasm_table_t {
// maybe needs to hold onto instance
pub(crate) inner: Table,
pub(crate) tag: CApiExternTag,
pub(crate) inner: Box<Table>,
}
impl wasm_table_t {
pub(crate) fn new(table: Table) -> Self {
Self {
tag: CApiExternTag::Table,
inner: Box::new(table),
}
}
}
#[no_mangle]

View File

@@ -192,10 +192,7 @@ pub unsafe extern "C" fn wasm_instance_exports(
None
};
Box::into_raw(Box::new(wasm_extern_t {
instance: Some(Arc::clone(instance)),
inner: r#extern.clone(),
}))
Box::into_raw(Box::new(r#extern.clone().into()))
})
.collect::<Vec<*mut wasm_extern_t>>();
extern_vec.shrink_to_fit();

View File

@@ -85,12 +85,12 @@ impl From<&ExternType> for wasm_externtype_t {
#[no_mangle]
pub unsafe extern "C" fn wasm_extern_type(r#extern: &wasm_extern_t) -> Box<wasm_externtype_t> {
Box::new(wasm_externtype_t::new(r#extern.inner.ty()))
Box::new(wasm_externtype_t::new(r#extern.ty()))
}
#[no_mangle]
pub unsafe extern "C" fn wasm_extern_kind(r#extern: &wasm_extern_t) -> wasm_externkind_t {
wasm_externkind_enum::from(r#extern.inner.ty()) as wasm_externkind_t
wasm_externkind_enum::from(r#extern.ty()) as wasm_externkind_t
}
#[no_mangle]

View File

@@ -186,10 +186,7 @@ fn wasi_get_unordered_imports_inner(
Box::new(wasmer_named_extern_t {
module,
name,
r#extern: Box::new(wasm_extern_t {
instance: None,
inner: extern_inner,
}),
r#extern: Box::new(extern_inner.into()),
})
})
.collect::<Vec<_>>()

View File

@@ -390,10 +390,7 @@ fn wasi_get_imports_inner(
}));
let inner = Extern::from_vm_export(store, export);
Some(Box::new(wasm_extern_t {
instance: None,
inner,
}))
Some(Box::new(inner.into()))
})
.collect::<Option<Vec<_>>>()?
.into();
@@ -407,10 +404,7 @@ pub unsafe extern "C" fn wasi_get_start_function(
) -> Option<Box<wasm_func_t>> {
let start = c_try!(instance.inner.exports.get_function("_start"));
Some(Box::new(wasm_func_t {
inner: start.clone(),
instance: Some(instance.inner.clone()),
}))
Some(Box::new(wasm_func_t::new(start.clone())))
}
#[cfg(test)]