mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 13:41:32 +00:00
Get table imports working
This commit is contained in:
137
lib/runtime-core/src/table/anyfunc.rs
Normal file
137
lib/runtime-core/src/table/anyfunc.rs
Normal file
@ -0,0 +1,137 @@
|
||||
use crate::{
|
||||
instance::Function,
|
||||
sig_registry::SigRegistry,
|
||||
structures::TypedIndex,
|
||||
types::{FuncSig, TableDesc},
|
||||
vm,
|
||||
};
|
||||
|
||||
use std::{ptr, sync::Arc};
|
||||
|
||||
enum AnyfuncInner<'a> {
|
||||
Host {
|
||||
ptr: *const vm::Func,
|
||||
signature: Arc<FuncSig>,
|
||||
},
|
||||
Managed(Function<'a>),
|
||||
}
|
||||
|
||||
pub struct Anyfunc<'a> {
|
||||
inner: AnyfuncInner<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Anyfunc<'a> {
|
||||
pub unsafe fn new<Sig>(func: *const vm::Func, signature: Sig) -> Self
|
||||
where
|
||||
Sig: Into<Arc<FuncSig>>,
|
||||
{
|
||||
Self {
|
||||
inner: AnyfuncInner::Host {
|
||||
ptr: func as _,
|
||||
signature: signature.into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn raw(&self) -> *const vm::Func {
|
||||
match self.inner {
|
||||
AnyfuncInner::Host { ptr, .. } => ptr,
|
||||
AnyfuncInner::Managed(ref func) => func.raw(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Function<'a>> for Anyfunc<'a> {
|
||||
fn from(function: Function<'a>) -> Self {
|
||||
Anyfunc {
|
||||
inner: AnyfuncInner::Managed(function),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AnyfuncTable {
|
||||
backing: Vec<vm::Anyfunc>,
|
||||
max: Option<u32>,
|
||||
}
|
||||
|
||||
impl AnyfuncTable {
|
||||
pub fn new(desc: TableDesc, local: &mut vm::LocalTable) -> Result<Box<Self>, ()> {
|
||||
let initial_table_backing_len = match desc.max {
|
||||
Some(max) => max,
|
||||
None => desc.min,
|
||||
} as usize;
|
||||
|
||||
let mut storage = Box::new(AnyfuncTable {
|
||||
backing: vec![vm::Anyfunc::null(); initial_table_backing_len],
|
||||
max: desc.max,
|
||||
});
|
||||
|
||||
let storage_ptr: *mut AnyfuncTable = &mut *storage;
|
||||
|
||||
local.base = storage.backing.as_mut_ptr() as *mut u8;
|
||||
local.count = storage.backing.len();
|
||||
local.table = storage_ptr as *mut ();
|
||||
|
||||
Ok(storage)
|
||||
}
|
||||
|
||||
pub fn current_size(&self) -> u32 {
|
||||
self.backing.len() as u32
|
||||
}
|
||||
|
||||
pub fn internal_buffer(&mut self) -> &mut [vm::Anyfunc] {
|
||||
&mut self.backing
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, delta: u32, local: &mut vm::LocalTable) -> Option<u32> {
|
||||
let starting_len = self.backing.len() as u32;
|
||||
|
||||
let new_len = starting_len.checked_add(delta)?;
|
||||
|
||||
if let Some(max) = self.max {
|
||||
if new_len > max {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
self.backing.resize(new_len as usize, vm::Anyfunc::null());
|
||||
|
||||
local.base = self.backing.as_mut_ptr() as *mut u8;
|
||||
local.count = self.backing.len();
|
||||
|
||||
Some(starting_len)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, index: u32, element: Anyfunc) -> Result<(), ()> {
|
||||
if let Some(slot) = self.backing.get_mut(index as usize) {
|
||||
let anyfunc = match element.inner {
|
||||
AnyfuncInner::Host { ptr, signature } => {
|
||||
let sig_index = SigRegistry.lookup_sigindex(signature);
|
||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||
|
||||
vm::Anyfunc {
|
||||
func: ptr,
|
||||
ctx: ptr::null_mut(),
|
||||
sig_id,
|
||||
}
|
||||
}
|
||||
AnyfuncInner::Managed(ref func) => {
|
||||
let sig_index = SigRegistry.lookup_sigindex(Arc::clone(&func.signature));
|
||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||
|
||||
vm::Anyfunc {
|
||||
func: func.raw(),
|
||||
ctx: func.instance_inner.vmctx,
|
||||
sig_id,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
*slot = anyfunc;
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
113
lib/runtime-core/src/table/mod.rs
Normal file
113
lib/runtime-core/src/table/mod.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use crate::{
|
||||
export::Export,
|
||||
import::IsExport,
|
||||
types::{ElementType, TableDesc},
|
||||
vm,
|
||||
};
|
||||
use std::{cell::RefCell, fmt, ptr, rc::Rc};
|
||||
|
||||
mod anyfunc;
|
||||
|
||||
pub use self::anyfunc::Anyfunc;
|
||||
use self::anyfunc::AnyfuncTable;
|
||||
|
||||
pub enum Element<'a> {
|
||||
Anyfunc(Anyfunc<'a>),
|
||||
}
|
||||
|
||||
// #[derive(Debug)]
|
||||
pub enum TableStorage {
|
||||
/// This is intended to be a caller-checked Anyfunc.
|
||||
Anyfunc(Box<AnyfuncTable>),
|
||||
}
|
||||
|
||||
pub struct Table {
|
||||
desc: TableDesc,
|
||||
storage: Rc<RefCell<(TableStorage, vm::LocalTable)>>,
|
||||
}
|
||||
|
||||
impl Table {
|
||||
pub fn new(desc: TableDesc) -> Result<Self, ()> {
|
||||
let mut local = vm::LocalTable {
|
||||
base: ptr::null_mut(),
|
||||
count: 0,
|
||||
table: ptr::null_mut(),
|
||||
};
|
||||
|
||||
let storage = match desc.ty {
|
||||
ElementType::Anyfunc => TableStorage::Anyfunc(AnyfuncTable::new(desc, &mut local)?),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
desc,
|
||||
storage: Rc::new(RefCell::new((storage, local))),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn description(&self) -> TableDesc {
|
||||
self.desc
|
||||
}
|
||||
|
||||
pub fn set(&self, index: u32, element: Element) -> Result<(), ()> {
|
||||
match &mut *self.storage.borrow_mut() {
|
||||
(TableStorage::Anyfunc(ref mut anyfunc_table), _) => {
|
||||
match element {
|
||||
Element::Anyfunc(anyfunc) => anyfunc_table.set(index, anyfunc),
|
||||
// _ => panic!("wrong element type for anyfunc table"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn anyfunc_direct_access_mut<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [vm::Anyfunc]) -> R,
|
||||
{
|
||||
match &mut *self.storage.borrow_mut() {
|
||||
(TableStorage::Anyfunc(ref mut anyfunc_table), _) => f(anyfunc_table.internal_buffer()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_size(&self) -> u32 {
|
||||
match &*self.storage.borrow() {
|
||||
(TableStorage::Anyfunc(ref anyfunc_table), _) => anyfunc_table.current_size(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn grow(&self, delta: u32) -> Option<u32> {
|
||||
if delta == 0 {
|
||||
return Some(self.current_size());
|
||||
}
|
||||
|
||||
match &mut *self.storage.borrow_mut() {
|
||||
(TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => {
|
||||
anyfunc_table.grow(delta, local)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn vm_local_table(&mut self) -> *mut vm::LocalTable {
|
||||
&mut self.storage.borrow_mut().1
|
||||
}
|
||||
}
|
||||
|
||||
impl IsExport for Table {
|
||||
fn to_export(&mut self) -> Export {
|
||||
Export::Table(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Table {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
desc: self.desc,
|
||||
storage: Rc::clone(&self.storage),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Table {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Table").field("desc", &self.desc).finish()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user