Table operation; refactor Callable
This commit is contained in:
committed by
Dan Gohman
parent
e60bf7f7e8
commit
de1c0f63eb
@@ -1,44 +1,61 @@
|
|||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use crate::trap::Trap;
|
use crate::trap::Trap;
|
||||||
|
use crate::types::FuncType;
|
||||||
use crate::values::Val;
|
use crate::values::Val;
|
||||||
use core::any::Any;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::trampoline::generate_func_export;
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
use wasmtime_runtime::{VMContext, VMFunctionBody};
|
use wasmtime_jit::InstanceHandle;
|
||||||
|
use wasmtime_runtime::Export;
|
||||||
|
|
||||||
pub trait Callable: Any {
|
pub trait Callable {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>>;
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) trait WrappedCallable {
|
||||||
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>>;
|
||||||
|
fn signature(&self) -> &ir::Signature {
|
||||||
|
match self.wasmtime_export() {
|
||||||
|
Export::Function { signature, .. } => signature,
|
||||||
|
_ => panic!("unexpected export type in Callable"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn wasmtime_handle(&self) -> &InstanceHandle;
|
||||||
|
fn wasmtime_export(&self) -> &Export;
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct WasmtimeFn {
|
pub(crate) struct WasmtimeFn {
|
||||||
store: Rc<RefCell<Store>>,
|
store: Rc<RefCell<Store>>,
|
||||||
signature: ir::Signature,
|
instance: InstanceHandle,
|
||||||
body: *const VMFunctionBody,
|
export: Export,
|
||||||
vmctx: *mut VMContext,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasmtimeFn {
|
impl WasmtimeFn {
|
||||||
pub fn new(
|
pub fn new(store: Rc<RefCell<Store>>, instance: InstanceHandle, export: Export) -> WasmtimeFn {
|
||||||
store: Rc<RefCell<Store>>,
|
|
||||||
signature: ir::Signature,
|
|
||||||
body: *const VMFunctionBody,
|
|
||||||
vmctx: *mut VMContext,
|
|
||||||
) -> WasmtimeFn {
|
|
||||||
WasmtimeFn {
|
WasmtimeFn {
|
||||||
store,
|
store,
|
||||||
signature,
|
instance,
|
||||||
body,
|
export,
|
||||||
vmctx,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Callable for WasmtimeFn {
|
|
||||||
|
impl WrappedCallable for WasmtimeFn {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
|
||||||
use core::cmp::max;
|
use core::cmp::max;
|
||||||
use core::{mem, ptr};
|
use core::{mem, ptr};
|
||||||
|
|
||||||
|
let (vmctx, body, signature) = match self.wasmtime_export() {
|
||||||
|
Export::Function {
|
||||||
|
vmctx,
|
||||||
|
address,
|
||||||
|
signature,
|
||||||
|
} => (*vmctx, *address, signature.clone()),
|
||||||
|
_ => panic!("unexpected export type in Callable"),
|
||||||
|
};
|
||||||
|
|
||||||
let mut store = self.store.borrow_mut();
|
let mut store = self.store.borrow_mut();
|
||||||
|
|
||||||
let context = store.context();
|
let context = store.context();
|
||||||
@@ -63,13 +80,13 @@ impl Callable for WasmtimeFn {
|
|||||||
// Get the trampoline to call for this function.
|
// Get the trampoline to call for this function.
|
||||||
let exec_code_buf = context
|
let exec_code_buf = context
|
||||||
.compiler()
|
.compiler()
|
||||||
.get_published_trampoline(self.body, &self.signature, value_size)
|
.get_published_trampoline(body, &signature, value_size)
|
||||||
.map_err(|_| Rc::new(RefCell::new(Trap::fake())))?; //was ActionError::Setup)?;
|
.map_err(|_| Rc::new(RefCell::new(Trap::fake())))?; //was ActionError::Setup)?;
|
||||||
|
|
||||||
// Call the trampoline.
|
// Call the trampoline.
|
||||||
if let Err(message) = unsafe {
|
if let Err(message) = unsafe {
|
||||||
wasmtime_runtime::wasmtime_call_trampoline(
|
wasmtime_runtime::wasmtime_call_trampoline(
|
||||||
self.vmctx,
|
vmctx,
|
||||||
exec_code_buf,
|
exec_code_buf,
|
||||||
values_vec.as_mut_ptr() as *mut u8,
|
values_vec.as_mut_ptr() as *mut u8,
|
||||||
)
|
)
|
||||||
@@ -78,7 +95,7 @@ impl Callable for WasmtimeFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load the return values out of `values_vec`.
|
// Load the return values out of `values_vec`.
|
||||||
for (index, abi_param) in self.signature.returns.iter().enumerate() {
|
for (index, abi_param) in signature.returns.iter().enumerate() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = values_vec.as_ptr().add(index);
|
let ptr = values_vec.as_ptr().add(index);
|
||||||
|
|
||||||
@@ -94,4 +111,44 @@ impl Callable for WasmtimeFn {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
fn wasmtime_handle(&self) -> &InstanceHandle {
|
||||||
|
&self.instance
|
||||||
|
}
|
||||||
|
fn wasmtime_export(&self) -> &Export {
|
||||||
|
&self.export
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NativeCallable {
|
||||||
|
callable: Rc<dyn Callable + 'static>,
|
||||||
|
instance: InstanceHandle,
|
||||||
|
export: Export,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeCallable {
|
||||||
|
pub(crate) fn new(
|
||||||
|
callable: Rc<dyn Callable + 'static>,
|
||||||
|
ft: &FuncType,
|
||||||
|
store: &Rc<RefCell<Store>>,
|
||||||
|
) -> Self {
|
||||||
|
let (instance, export) =
|
||||||
|
generate_func_export(ft, &callable, store).expect("generated func");
|
||||||
|
NativeCallable {
|
||||||
|
callable,
|
||||||
|
instance,
|
||||||
|
export,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WrappedCallable for NativeCallable {
|
||||||
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
|
||||||
|
self.callable.call(params, results)
|
||||||
|
}
|
||||||
|
fn wasmtime_handle(&self) -> &InstanceHandle {
|
||||||
|
&self.instance
|
||||||
|
}
|
||||||
|
fn wasmtime_export(&self) -> &Export {
|
||||||
|
&self.export
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
use crate::callable::{Callable, WasmtimeFn};
|
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
|
||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
|
use crate::table_utils;
|
||||||
|
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
|
||||||
use crate::trap::Trap;
|
use crate::trap::Trap;
|
||||||
use crate::types::{ExternType, FuncType, GlobalType, MemoryType, TableType, ValType};
|
use crate::types::{ExternType, FuncType, GlobalType, MemoryType, TableType, ValType};
|
||||||
use crate::values::Val;
|
use crate::values::Val;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
|
||||||
use crate::trampoline::{generate_func_export, generate_global_export, generate_memory_export};
|
|
||||||
use wasmtime_runtime::InstanceHandle;
|
use wasmtime_runtime::InstanceHandle;
|
||||||
|
|
||||||
// Externals
|
// Externals
|
||||||
|
|
||||||
pub enum Extern {
|
pub enum Extern {
|
||||||
@@ -55,15 +56,10 @@ impl Extern {
|
|||||||
|
|
||||||
pub(crate) fn get_wasmtime_export(&mut self) -> wasmtime_runtime::Export {
|
pub(crate) fn get_wasmtime_export(&mut self) -> wasmtime_runtime::Export {
|
||||||
match self {
|
match self {
|
||||||
Extern::Func(f) => {
|
Extern::Func(f) => f.borrow().wasmtime_export().clone(),
|
||||||
if f.borrow().anchor.is_none() {
|
|
||||||
generate_func_export(&f).expect("generate_func_export");
|
|
||||||
}
|
|
||||||
f.borrow().anchor.as_ref().unwrap().1.clone()
|
|
||||||
}
|
|
||||||
Extern::Global(g) => g.borrow().wasmtime_export().clone(),
|
Extern::Global(g) => g.borrow().wasmtime_export().clone(),
|
||||||
Extern::Memory(m) => m.borrow().wasmtime_export().clone(),
|
Extern::Memory(m) => m.borrow().wasmtime_export().clone(),
|
||||||
_ => unimplemented!("get_wasmtime_export"),
|
Extern::Table(t) => t.borrow().wasmtime_export().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,53 +69,47 @@ impl Extern {
|
|||||||
export: wasmtime_runtime::Export,
|
export: wasmtime_runtime::Export,
|
||||||
) -> Extern {
|
) -> Extern {
|
||||||
match export {
|
match export {
|
||||||
wasmtime_runtime::Export::Function {
|
wasmtime_runtime::Export::Function { .. } => Extern::Func(Rc::new(RefCell::new(
|
||||||
address,
|
Func::from_wasmtime_function(export, store, instance_handle),
|
||||||
vmctx,
|
))),
|
||||||
ref signature,
|
|
||||||
} => {
|
|
||||||
let ty = FuncType::from_cranelift_signature(signature.clone());
|
|
||||||
let callable = WasmtimeFn::new(store.clone(), signature.clone(), address, vmctx);
|
|
||||||
let mut f = Func::new(store, ty, Rc::new(callable));
|
|
||||||
f.anchor = Some((instance_handle, export.clone()));
|
|
||||||
Extern::Func(Rc::new(RefCell::new(f)))
|
|
||||||
}
|
|
||||||
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(Rc::new(RefCell::new(
|
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(Rc::new(RefCell::new(
|
||||||
Memory::from_wasmtime_memory(export, store, instance_handle),
|
Memory::from_wasmtime_memory(export, store, instance_handle),
|
||||||
))),
|
))),
|
||||||
wasmtime_runtime::Export::Global { .. } => Extern::Global(Rc::new(RefCell::new(
|
wasmtime_runtime::Export::Global { .. } => Extern::Global(Rc::new(RefCell::new(
|
||||||
Global::from_wasmtime_global(export, store),
|
Global::from_wasmtime_global(export, store),
|
||||||
))),
|
))),
|
||||||
wasmtime_runtime::Export::Table {
|
wasmtime_runtime::Export::Table { .. } => Extern::Table(Rc::new(RefCell::new(
|
||||||
definition: _,
|
Table::from_wasmtime_table(export, store, instance_handle),
|
||||||
vmctx: _,
|
))),
|
||||||
table,
|
|
||||||
} => {
|
|
||||||
let ty = TableType::from_cranelift_table(table.table.clone());
|
|
||||||
Extern::Table(Rc::new(RefCell::new(Table::new(store, ty))))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
_store: Rc<RefCell<Store>>,
|
_store: Rc<RefCell<Store>>,
|
||||||
callable: Rc<dyn Callable + 'static>,
|
callable: Rc<dyn WrappedCallable + 'static>,
|
||||||
r#type: FuncType,
|
r#type: FuncType,
|
||||||
pub(crate) anchor: Option<(InstanceHandle, wasmtime_runtime::Export)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Func {
|
impl Func {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
store: Rc<RefCell<Store>>,
|
store: Rc<RefCell<Store>>,
|
||||||
r#type: FuncType,
|
ty: FuncType,
|
||||||
callable: Rc<dyn Callable + 'static>,
|
callable: Rc<dyn Callable + 'static>,
|
||||||
|
) -> Self {
|
||||||
|
let callable = Rc::new(NativeCallable::new(callable, &ty, &store));
|
||||||
|
Func::from_wrapped(store, ty, callable)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_wrapped(
|
||||||
|
store: Rc<RefCell<Store>>,
|
||||||
|
r#type: FuncType,
|
||||||
|
callable: Rc<dyn WrappedCallable + 'static>,
|
||||||
) -> Func {
|
) -> Func {
|
||||||
Func {
|
Func {
|
||||||
_store: store,
|
_store: store,
|
||||||
callable,
|
callable,
|
||||||
r#type,
|
r#type,
|
||||||
anchor: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +117,10 @@ impl Func {
|
|||||||
&self.r#type
|
&self.r#type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn callable(&self) -> &Rc<dyn WrappedCallable + 'static> {
|
||||||
|
&self.callable
|
||||||
|
}
|
||||||
|
|
||||||
pub fn param_arity(&self) -> usize {
|
pub fn param_arity(&self) -> usize {
|
||||||
self.r#type.params().len()
|
self.r#type.params().len()
|
||||||
}
|
}
|
||||||
@@ -135,15 +129,29 @@ impl Func {
|
|||||||
self.r#type.results().len()
|
self.r#type.results().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callable(&self) -> &(dyn Callable + 'static) {
|
|
||||||
self.callable.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Rc<RefCell<Trap>>> {
|
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Rc<RefCell<Trap>>> {
|
||||||
let mut results = vec![Val::default(); self.result_arity()];
|
let mut results = vec![Val::default(); self.result_arity()];
|
||||||
self.callable.call(params, &mut results)?;
|
self.callable.call(params, &mut results)?;
|
||||||
Ok(results.into_boxed_slice())
|
Ok(results.into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
|
||||||
|
self.callable.wasmtime_export()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_wasmtime_function(
|
||||||
|
export: wasmtime_runtime::Export,
|
||||||
|
store: Rc<RefCell<Store>>,
|
||||||
|
instance_handle: InstanceHandle,
|
||||||
|
) -> Self {
|
||||||
|
let ty = if let wasmtime_runtime::Export::Function { signature, .. } = &export {
|
||||||
|
FuncType::from_cranelift_signature(signature.clone())
|
||||||
|
} else {
|
||||||
|
panic!("expected function export")
|
||||||
|
};
|
||||||
|
let callable = WasmtimeFn::new(store.clone(), instance_handle, export.clone());
|
||||||
|
Func::from_wrapped(store, ty, Rc::new(callable))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Global {
|
pub struct Global {
|
||||||
@@ -234,15 +242,27 @@ impl Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
_store: Rc<RefCell<Store>>,
|
store: Rc<RefCell<Store>>,
|
||||||
r#type: TableType,
|
r#type: TableType,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
wasmtime_handle: InstanceHandle,
|
||||||
|
wasmtime_export: wasmtime_runtime::Export,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
pub fn new(store: Rc<RefCell<Store>>, r#type: TableType) -> Table {
|
pub fn new(store: Rc<RefCell<Store>>, r#type: TableType, _init: Val) -> Table {
|
||||||
|
match r#type.element() {
|
||||||
|
ValType::FuncRef => (),
|
||||||
|
_ => panic!("table is not for funcref"),
|
||||||
|
}
|
||||||
|
// TODO implement _init initialization
|
||||||
|
let (wasmtime_handle, wasmtime_export) =
|
||||||
|
generate_table_export(&r#type).expect("generated table");
|
||||||
Table {
|
Table {
|
||||||
_store: store,
|
store,
|
||||||
r#type,
|
r#type,
|
||||||
|
wasmtime_handle,
|
||||||
|
wasmtime_export,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,20 +270,54 @@ impl Table {
|
|||||||
&self.r#type
|
&self.r#type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, _index: u32) -> Val {
|
fn wasmtime_table_definition(&self) -> *mut wasmtime_runtime::VMTableDefinition {
|
||||||
unimplemented!("Table::get")
|
match self.wasmtime_export {
|
||||||
|
wasmtime_runtime::Export::Table { definition, .. } => definition,
|
||||||
|
_ => panic!("global definition not found"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&self, _index: u32, _val: &Val) -> usize {
|
pub fn get(&self, index: u32) -> Val {
|
||||||
unimplemented!("Table::set")
|
let definition = self.wasmtime_table_definition();
|
||||||
|
unsafe { table_utils::get_item(definition, &self.store, index) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&self, index: u32, val: Val) -> bool {
|
||||||
|
let definition = self.wasmtime_table_definition();
|
||||||
|
unsafe { table_utils::set_item(definition, &self.store, index, val) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> u32 {
|
pub fn size(&self) -> u32 {
|
||||||
unimplemented!("Table::size")
|
let definition = self.wasmtime_table_definition();
|
||||||
|
unsafe { table_utils::get_size(definition) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn grow(&mut self, _delta: u32) -> bool {
|
pub fn grow(&mut self, delta: u32, init: Val) -> bool {
|
||||||
unimplemented!("Table::grow")
|
let definition = self.wasmtime_table_definition();
|
||||||
|
unsafe { table_utils::grow_table(definition, &self.r#type, &self.store, delta, init) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
|
||||||
|
&self.wasmtime_export
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_wasmtime_table(
|
||||||
|
export: wasmtime_runtime::Export,
|
||||||
|
store: Rc<RefCell<Store>>,
|
||||||
|
instance_handle: wasmtime_runtime::InstanceHandle,
|
||||||
|
) -> Table {
|
||||||
|
let table = if let wasmtime_runtime::Export::Table { ref table, .. } = export {
|
||||||
|
table
|
||||||
|
} else {
|
||||||
|
panic!("wasmtime export is not table")
|
||||||
|
};
|
||||||
|
let ty = TableType::from_cranelift_table(table.table.clone());
|
||||||
|
Table {
|
||||||
|
store,
|
||||||
|
r#type: ty,
|
||||||
|
wasmtime_handle: instance_handle,
|
||||||
|
wasmtime_export: export,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ impl Instance {
|
|||||||
let mut mutable = instance_handle.clone();
|
let mut mutable = instance_handle.clone();
|
||||||
for (name, _) in instance_handle.clone().exports() {
|
for (name, _) in instance_handle.clone().exports() {
|
||||||
let export = mutable.lookup(name).expect("export");
|
let export = mutable.lookup(name).expect("export");
|
||||||
|
if let wasmtime_runtime::Export::Function { signature, .. } = &export {
|
||||||
|
// HACK ensure all handles, instantiated outside Store, present in
|
||||||
|
// the store's SignatureRegistry.
|
||||||
|
use crate::runtime::SignatureRegistry;
|
||||||
|
let _ = store.borrow_mut().register_cranelift_signature(signature);
|
||||||
|
}
|
||||||
export_names_map.insert(name.to_owned(), exports.len());
|
export_names_map.insert(name.to_owned(), exports.len());
|
||||||
exports.push(Rc::new(RefCell::new(Extern::from_wasmtime_export(
|
exports.push(Rc::new(RefCell::new(Extern::from_wasmtime_export(
|
||||||
store.clone(),
|
store.clone(),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ mod externals;
|
|||||||
mod instance;
|
mod instance;
|
||||||
mod module;
|
mod module;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
|
mod table_utils;
|
||||||
mod trampoline;
|
mod trampoline;
|
||||||
mod trap;
|
mod trap;
|
||||||
mod types;
|
mod types;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use crate::context::{create_compiler, Context};
|
use crate::context::{create_compiler, Context};
|
||||||
|
|
||||||
use cranelift_codegen::settings;
|
use cranelift_codegen::{ir, settings};
|
||||||
use wasmtime_jit::Features;
|
use wasmtime_jit::Features;
|
||||||
|
|
||||||
// Runtime Environment
|
// Runtime Environment
|
||||||
@@ -79,10 +79,22 @@ impl Engine {
|
|||||||
|
|
||||||
// Store
|
// Store
|
||||||
|
|
||||||
|
pub(crate) trait SignatureRegistry {
|
||||||
|
fn register_cranelift_signature(
|
||||||
|
&mut self,
|
||||||
|
signature: &ir::Signature,
|
||||||
|
) -> wasmtime_runtime::VMSharedSignatureIndex;
|
||||||
|
fn lookup_cranelift_signature(
|
||||||
|
&self,
|
||||||
|
type_index: wasmtime_runtime::VMSharedSignatureIndex,
|
||||||
|
) -> Option<&ir::Signature>;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Store {
|
pub struct Store {
|
||||||
engine: Rc<RefCell<Engine>>,
|
engine: Rc<RefCell<Engine>>,
|
||||||
context: Context,
|
context: Context,
|
||||||
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||||
|
signature_cache: HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Store {
|
impl Store {
|
||||||
@@ -94,6 +106,7 @@ impl Store {
|
|||||||
engine,
|
engine,
|
||||||
context: Context::create(flags, features, debug_info),
|
context: Context::create(flags, features, debug_info),
|
||||||
global_exports: Rc::new(RefCell::new(HashMap::new())),
|
global_exports: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
signature_cache: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,3 +125,26 @@ impl Store {
|
|||||||
&self.global_exports
|
&self.global_exports
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SignatureRegistry for Store {
|
||||||
|
fn register_cranelift_signature(
|
||||||
|
&mut self,
|
||||||
|
signature: &ir::Signature,
|
||||||
|
) -> wasmtime_runtime::VMSharedSignatureIndex {
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
let index = self.context().compiler().signatures().register(signature);
|
||||||
|
match self.signature_cache.entry(index) {
|
||||||
|
Entry::Vacant(v) => {
|
||||||
|
v.insert(signature.clone());
|
||||||
|
}
|
||||||
|
Entry::Occupied(_) => (),
|
||||||
|
}
|
||||||
|
index
|
||||||
|
}
|
||||||
|
fn lookup_cranelift_signature(
|
||||||
|
&self,
|
||||||
|
type_index: wasmtime_runtime::VMSharedSignatureIndex,
|
||||||
|
) -> Option<&ir::Signature> {
|
||||||
|
self.signature_cache.get(&type_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
123
wasmtime-api/src/table_utils.rs
Normal file
123
wasmtime-api/src/table_utils.rs
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::slice;
|
||||||
|
use wasmtime_runtime::{
|
||||||
|
InstanceHandle, VMCallerCheckedAnyfunc, VMSharedSignatureIndex, VMTableDefinition,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::callable::WasmtimeFn;
|
||||||
|
use crate::runtime::SignatureRegistry;
|
||||||
|
use crate::runtime::Store;
|
||||||
|
use crate::types::TableType;
|
||||||
|
use crate::values::{AnyRef, FuncRef, Val};
|
||||||
|
|
||||||
|
fn into_checked_anyfunc(val: Val, store: &Rc<RefCell<Store>>) -> VMCallerCheckedAnyfunc {
|
||||||
|
match val {
|
||||||
|
Val::AnyRef(AnyRef::Null) => VMCallerCheckedAnyfunc {
|
||||||
|
func_ptr: ptr::null(),
|
||||||
|
type_index: VMSharedSignatureIndex::default(),
|
||||||
|
vmctx: ptr::null_mut(),
|
||||||
|
},
|
||||||
|
Val::AnyRef(AnyRef::Func(f)) | Val::FuncRef(f) => {
|
||||||
|
let (vmctx, func_ptr, signature) = match f.0.wasmtime_export() {
|
||||||
|
wasmtime_runtime::Export::Function {
|
||||||
|
vmctx,
|
||||||
|
address,
|
||||||
|
signature,
|
||||||
|
} => (*vmctx, *address, signature),
|
||||||
|
_ => panic!("expected function export"),
|
||||||
|
};
|
||||||
|
let type_index = store.borrow_mut().register_cranelift_signature(signature);
|
||||||
|
VMCallerCheckedAnyfunc {
|
||||||
|
func_ptr,
|
||||||
|
type_index,
|
||||||
|
vmctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("val is not funcref"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn from_checked_anyfunc(item: &VMCallerCheckedAnyfunc, store: &Rc<RefCell<Store>>) -> Val {
|
||||||
|
if item.type_index == VMSharedSignatureIndex::default() {
|
||||||
|
return Val::AnyRef(AnyRef::Null);
|
||||||
|
}
|
||||||
|
let signature = store
|
||||||
|
.borrow()
|
||||||
|
.lookup_cranelift_signature(item.type_index)
|
||||||
|
.expect("signature")
|
||||||
|
.clone();
|
||||||
|
let instance_handle = InstanceHandle::from_vmctx(item.vmctx);
|
||||||
|
let export = wasmtime_runtime::Export::Function {
|
||||||
|
address: item.func_ptr,
|
||||||
|
signature,
|
||||||
|
vmctx: item.vmctx,
|
||||||
|
};
|
||||||
|
let f = WasmtimeFn::new(store.clone(), instance_handle, export);
|
||||||
|
Val::FuncRef(FuncRef(Rc::new(f)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get_item(
|
||||||
|
table: *mut VMTableDefinition,
|
||||||
|
store: &Rc<RefCell<Store>>,
|
||||||
|
index: u32,
|
||||||
|
) -> Val {
|
||||||
|
let base = slice::from_raw_parts(
|
||||||
|
(*table).base as *const VMCallerCheckedAnyfunc,
|
||||||
|
(*table).current_elements,
|
||||||
|
);
|
||||||
|
|
||||||
|
from_checked_anyfunc(&base[index as usize], store)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn set_item(
|
||||||
|
table: *mut VMTableDefinition,
|
||||||
|
store: &Rc<RefCell<Store>>,
|
||||||
|
index: u32,
|
||||||
|
val: Val,
|
||||||
|
) -> bool {
|
||||||
|
let base = slice::from_raw_parts_mut(
|
||||||
|
(*table).base as *mut VMCallerCheckedAnyfunc,
|
||||||
|
(*table).current_elements,
|
||||||
|
);
|
||||||
|
if index as usize >= base.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
base[index as usize] = into_checked_anyfunc(val, store);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get_size(table: *mut VMTableDefinition) -> u32 {
|
||||||
|
(*table).current_elements as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn grow_table(
|
||||||
|
table: *mut VMTableDefinition,
|
||||||
|
table_type: &TableType,
|
||||||
|
store: &Rc<RefCell<Store>>,
|
||||||
|
delta: u32,
|
||||||
|
init: Val,
|
||||||
|
) -> bool {
|
||||||
|
let new_len = (*table).current_elements + delta as usize;
|
||||||
|
if (table_type.limits().max() as usize) < new_len {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer = Vec::from_raw_parts(
|
||||||
|
(*table).base as *mut VMCallerCheckedAnyfunc,
|
||||||
|
(*table).current_elements,
|
||||||
|
(*table).current_elements,
|
||||||
|
);
|
||||||
|
buffer.resize(new_len, into_checked_anyfunc(init, store));
|
||||||
|
buffer.shrink_to_fit();
|
||||||
|
assert!(buffer.capacity() == new_len);
|
||||||
|
|
||||||
|
(*table).base = buffer.as_mut_ptr() as *mut u8;
|
||||||
|
(*table).current_elements = new_len;
|
||||||
|
mem::forget(buffer);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
@@ -8,12 +8,15 @@ use wasmtime_environ::Module;
|
|||||||
use wasmtime_runtime::{Imports, InstanceHandle, VMFunctionBody};
|
use wasmtime_runtime::{Imports, InstanceHandle, VMFunctionBody};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::RefCell;
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn create_handle(
|
use crate::runtime::SignatureRegistry;
|
||||||
|
|
||||||
|
pub(crate) fn create_handle(
|
||||||
module: Module,
|
module: Module,
|
||||||
|
signature_registry: Option<RefMut<dyn SignatureRegistry>>,
|
||||||
finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody>,
|
finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody>,
|
||||||
state: Box<dyn Any>,
|
state: Box<dyn Any>,
|
||||||
) -> Result<InstanceHandle, Error> {
|
) -> Result<InstanceHandle, Error> {
|
||||||
@@ -28,7 +31,19 @@ pub fn create_handle(
|
|||||||
PrimaryMap::new(),
|
PrimaryMap::new(),
|
||||||
);
|
);
|
||||||
let data_initializers = Vec::new();
|
let data_initializers = Vec::new();
|
||||||
let signatures = PrimaryMap::new();
|
|
||||||
|
// Compute indices into the shared signature table.
|
||||||
|
let signatures = signature_registry
|
||||||
|
.and_then(|mut signature_registry| {
|
||||||
|
Some(
|
||||||
|
module
|
||||||
|
.signatures
|
||||||
|
.values()
|
||||||
|
.map(|sig| signature_registry.register_cranelift_signature(sig))
|
||||||
|
.collect::<PrimaryMap<_, _>>(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| PrimaryMap::new());
|
||||||
|
|
||||||
Ok(InstanceHandle::new(
|
Ok(InstanceHandle::new(
|
||||||
Rc::new(module),
|
Rc::new(module),
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ use core::cmp;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::{Func, Trap, Val};
|
use crate::{Callable, FuncType, Store, Trap, Val};
|
||||||
|
|
||||||
use super::create_handle::create_handle;
|
use super::create_handle::create_handle;
|
||||||
|
|
||||||
struct TrampolineState {
|
struct TrampolineState {
|
||||||
func: Rc<RefCell<Func>>,
|
func: Rc<dyn Callable + 'static>,
|
||||||
trap: Option<Rc<RefCell<Trap>>>,
|
trap: Option<Rc<RefCell<Trap>>>,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
code_memory: CodeMemory,
|
code_memory: CodeMemory,
|
||||||
@@ -45,15 +45,15 @@ unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, call_id: u32, values_vec: *m
|
|||||||
(args, signature.returns.len())
|
(args, signature.returns.len())
|
||||||
};
|
};
|
||||||
|
|
||||||
let func = instance
|
let mut returns = vec![Val::default(); returns_len];
|
||||||
|
let func = &instance
|
||||||
.host_state()
|
.host_state()
|
||||||
.downcast_mut::<TrampolineState>()
|
.downcast_mut::<TrampolineState>()
|
||||||
.expect("state")
|
.expect("state")
|
||||||
.func
|
.func;
|
||||||
.borrow();
|
|
||||||
|
|
||||||
match func.call(&args) {
|
match func.call(&args, &mut returns) {
|
||||||
Ok(returns) => {
|
Ok(()) => {
|
||||||
for i in 0..returns_len {
|
for i in 0..returns_len {
|
||||||
// TODO check signature.returns[i].value_type ?
|
// TODO check signature.returns[i].value_type ?
|
||||||
returns[i].write_value_to(values_vec.offset(i as isize));
|
returns[i].write_value_to(values_vec.offset(i as isize));
|
||||||
@@ -188,8 +188,12 @@ fn make_trampoline(
|
|||||||
.as_ptr()
|
.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_handle_with_function(func: &Rc<RefCell<Func>>) -> Result<InstanceHandle, Error> {
|
pub fn create_handle_with_function(
|
||||||
let sig = func.borrow().r#type().get_cranelift_signature().clone();
|
ft: &FuncType,
|
||||||
|
func: &Rc<dyn Callable + 'static>,
|
||||||
|
store: &Rc<RefCell<Store>>,
|
||||||
|
) -> Result<InstanceHandle, Error> {
|
||||||
|
let sig = ft.get_cranelift_signature().clone();
|
||||||
|
|
||||||
let isa = {
|
let isa = {
|
||||||
let isa_builder =
|
let isa_builder =
|
||||||
@@ -229,7 +233,12 @@ pub fn create_handle_with_function(func: &Rc<RefCell<Func>>) -> Result<InstanceH
|
|||||||
code_memory,
|
code_memory,
|
||||||
};
|
};
|
||||||
|
|
||||||
create_handle(module, finished_functions, Box::new(trampoline_state))
|
create_handle(
|
||||||
|
module,
|
||||||
|
Some(store.borrow_mut()),
|
||||||
|
finished_functions,
|
||||||
|
Box::new(trampoline_state),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We don't expect trampoline compilation to produce any relocations, so
|
/// We don't expect trampoline compilation to produce any relocations, so
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ pub fn create_global(
|
|||||||
},
|
},
|
||||||
initializer: cranelift_wasm::GlobalInit::Import, // TODO is it right?
|
initializer: cranelift_wasm::GlobalInit::Import, // TODO is it right?
|
||||||
};
|
};
|
||||||
let mut handle = create_handle(Module::new(), PrimaryMap::new(), Box::new(())).expect("handle");
|
let mut handle =
|
||||||
|
create_handle(Module::new(), None, PrimaryMap::new(), Box::new(())).expect("handle");
|
||||||
Ok((
|
Ok((
|
||||||
wasmtime_runtime::Export::Global {
|
wasmtime_runtime::Export::Global {
|
||||||
definition: definition.as_mut(),
|
definition: definition.as_mut(),
|
||||||
|
|||||||
@@ -29,5 +29,5 @@ pub fn create_handle_with_memory(memory: &MemoryType) -> Result<InstanceHandle,
|
|||||||
wasmtime_environ::Export::Memory(memory_id),
|
wasmtime_environ::Export::Memory(memory_id),
|
||||||
);
|
);
|
||||||
|
|
||||||
create_handle(module, PrimaryMap::new(), Box::new(()))
|
create_handle(module, None, PrimaryMap::new(), Box::new(()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ mod create_handle;
|
|||||||
mod func;
|
mod func;
|
||||||
mod global;
|
mod global;
|
||||||
mod memory;
|
mod memory;
|
||||||
|
mod table;
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@@ -13,16 +14,19 @@ use std::rc::Rc;
|
|||||||
use self::func::create_handle_with_function;
|
use self::func::create_handle_with_function;
|
||||||
use self::global::create_global;
|
use self::global::create_global;
|
||||||
use self::memory::create_handle_with_memory;
|
use self::memory::create_handle_with_memory;
|
||||||
use super::{Func, GlobalType, MemoryType, Val};
|
use self::table::create_handle_with_table;
|
||||||
|
use super::{Callable, FuncType, GlobalType, MemoryType, Store, TableType, Val};
|
||||||
|
|
||||||
pub use self::global::GlobalState;
|
pub use self::global::GlobalState;
|
||||||
|
|
||||||
pub fn generate_func_export(f: &Rc<RefCell<Func>>) -> Result<(), Error> {
|
pub fn generate_func_export(
|
||||||
let mut instance = create_handle_with_function(f)?;
|
ft: &FuncType,
|
||||||
|
func: &Rc<dyn Callable + 'static>,
|
||||||
|
store: &Rc<RefCell<Store>>,
|
||||||
|
) -> Result<(wasmtime_runtime::InstanceHandle, wasmtime_runtime::Export), Error> {
|
||||||
|
let mut instance = create_handle_with_function(ft, func, store)?;
|
||||||
let export = instance.lookup("trampoline").expect("trampoline export");
|
let export = instance.lookup("trampoline").expect("trampoline export");
|
||||||
|
Ok((instance, export))
|
||||||
f.borrow_mut().anchor = Some((instance, export));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_global_export(
|
pub fn generate_global_export(
|
||||||
@@ -39,3 +43,11 @@ pub fn generate_memory_export(
|
|||||||
let export = instance.lookup("memory").expect("memory export");
|
let export = instance.lookup("memory").expect("memory export");
|
||||||
Ok((instance, export))
|
Ok((instance, export))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn generate_table_export(
|
||||||
|
t: &TableType,
|
||||||
|
) -> Result<(wasmtime_runtime::InstanceHandle, wasmtime_runtime::Export), Error> {
|
||||||
|
let mut instance = create_handle_with_table(t)?;
|
||||||
|
let export = instance.lookup("table").expect("table export");
|
||||||
|
Ok((instance, export))
|
||||||
|
}
|
||||||
|
|||||||
35
wasmtime-api/src/trampoline/table.rs
Normal file
35
wasmtime-api/src/trampoline/table.rs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
use cranelift_entity::PrimaryMap;
|
||||||
|
use cranelift_wasm::TableElementType;
|
||||||
|
use failure::Error;
|
||||||
|
use wasmtime_environ::Module;
|
||||||
|
use wasmtime_runtime::InstanceHandle;
|
||||||
|
|
||||||
|
use super::create_handle::create_handle;
|
||||||
|
use crate::{TableType, ValType};
|
||||||
|
|
||||||
|
pub fn create_handle_with_table(table: &TableType) -> Result<InstanceHandle, Error> {
|
||||||
|
let mut module = Module::new();
|
||||||
|
|
||||||
|
let table = cranelift_wasm::Table {
|
||||||
|
minimum: table.limits().min(),
|
||||||
|
maximum: if table.limits().max() == std::u32::MAX {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(table.limits().max())
|
||||||
|
},
|
||||||
|
ty: match table.element() {
|
||||||
|
ValType::FuncRef => TableElementType::Func,
|
||||||
|
_ => TableElementType::Val(table.element().get_cranelift_type()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let tunable = Default::default();
|
||||||
|
|
||||||
|
let table_plan = wasmtime_environ::TablePlan::for_table(table, &tunable);
|
||||||
|
let table_id = module.table_plans.push(table_plan);
|
||||||
|
module.exports.insert(
|
||||||
|
"table".to_string(),
|
||||||
|
wasmtime_environ::Export::Table(table_id),
|
||||||
|
);
|
||||||
|
|
||||||
|
create_handle(module, None, PrimaryMap::new(), Box::new(()))
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::callable::Callable;
|
use crate::callable::WrappedCallable;
|
||||||
use crate::types::ValType;
|
use crate::types::ValType;
|
||||||
use std::cell::RefCell;
|
use std::any::Any;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -9,22 +9,30 @@ use cranelift_codegen::ir;
|
|||||||
use wasmtime_jit::RuntimeValue;
|
use wasmtime_jit::RuntimeValue;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AnyRef;
|
pub enum AnyRef {
|
||||||
|
Null,
|
||||||
|
Rc(Rc<dyn Any>),
|
||||||
|
Func(FuncRef),
|
||||||
|
}
|
||||||
|
|
||||||
impl AnyRef {
|
impl AnyRef {
|
||||||
pub fn null() -> AnyRef {
|
pub fn null() -> AnyRef {
|
||||||
AnyRef
|
AnyRef::Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for AnyRef {
|
impl fmt::Debug for AnyRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "anyref")
|
match self {
|
||||||
|
AnyRef::Null => write!(f, "null"),
|
||||||
|
AnyRef::Rc(_) => write!(f, "anyref"),
|
||||||
|
AnyRef::Func(func) => func.fmt(f),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FuncRef {
|
#[derive(Clone)]
|
||||||
pub callable: Box<dyn Callable + 'static>,
|
pub struct FuncRef(pub(crate) Rc<dyn WrappedCallable + 'static>);
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for FuncRef {
|
impl fmt::Debug for FuncRef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
@@ -32,19 +40,35 @@ impl fmt::Debug for FuncRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<AnyRef> for FuncRef {
|
||||||
|
fn from(anyref: AnyRef) -> FuncRef {
|
||||||
|
match anyref {
|
||||||
|
AnyRef::Func(f) => f,
|
||||||
|
AnyRef::Rc(_) => unimplemented!("try to unwrap?"),
|
||||||
|
AnyRef::Null => panic!("null anyref"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<AnyRef> for FuncRef {
|
||||||
|
fn into(self) -> AnyRef {
|
||||||
|
AnyRef::Func(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Val {
|
pub enum Val {
|
||||||
I32(i32),
|
I32(i32),
|
||||||
I64(i64),
|
I64(i64),
|
||||||
F32(u32),
|
F32(u32),
|
||||||
F64(u64),
|
F64(u64),
|
||||||
AnyRef(Rc<RefCell<AnyRef>>),
|
AnyRef(AnyRef),
|
||||||
FuncRef(Rc<RefCell<FuncRef>>),
|
FuncRef(FuncRef),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Val {
|
impl Val {
|
||||||
pub fn default() -> Val {
|
pub fn default() -> Val {
|
||||||
Val::AnyRef(Rc::new(RefCell::new(AnyRef::null())))
|
Val::AnyRef(AnyRef::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#type(&self) -> ValType {
|
pub fn r#type(&self) -> ValType {
|
||||||
@@ -151,14 +175,27 @@ impl Into<f64> for Val {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<RefCell<AnyRef>>> for Val {
|
impl From<AnyRef> for Val {
|
||||||
fn from(val: Rc<RefCell<AnyRef>>) -> Val {
|
fn from(val: AnyRef) -> Val {
|
||||||
Val::AnyRef(val)
|
match val {
|
||||||
|
AnyRef::Func(f) => Val::FuncRef(f),
|
||||||
|
_ => Val::AnyRef(val),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Rc<RefCell<FuncRef>>> for Val {
|
impl From<FuncRef> for Val {
|
||||||
fn from(val: Rc<RefCell<FuncRef>>) -> Val {
|
fn from(val: FuncRef) -> Val {
|
||||||
Val::FuncRef(val)
|
Val::FuncRef(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<AnyRef> for Val {
|
||||||
|
fn into(self) -> AnyRef {
|
||||||
|
match self {
|
||||||
|
Val::AnyRef(r) => r,
|
||||||
|
Val::FuncRef(f) => AnyRef::Func(f),
|
||||||
|
_ => panic!("Invalid conversion of {:?} to anyref.", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
// TODO complete the C API
|
// TODO complete the C API
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncRef, FuncType, Global,
|
||||||
ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store, TableType, Trap, Val,
|
GlobalType, ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store, Table,
|
||||||
ValType,
|
TableType, Trap, Val, ValType,
|
||||||
};
|
};
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@@ -268,7 +268,7 @@ declare_vec!(wasm_exporttype_vec_t, *mut wasm_exporttype_t);
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_ref_t {
|
pub struct wasm_ref_t {
|
||||||
_unused: [u8; 0],
|
r: AnyRef,
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@@ -360,7 +360,7 @@ pub struct wasm_global_t {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_table_t {
|
pub struct wasm_table_t {
|
||||||
_unused: [u8; 0],
|
table: Rc<RefCell<Table>>,
|
||||||
}
|
}
|
||||||
pub type wasm_table_size_t = u32;
|
pub type wasm_table_size_t = u32;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@@ -1334,3 +1334,133 @@ pub unsafe extern "C" fn wasm_memorytype_new(
|
|||||||
});
|
});
|
||||||
Box::into_raw(mt)
|
Box::into_raw(mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_extern_as_table(e: *mut wasm_extern_t) -> *mut wasm_table_t {
|
||||||
|
let t = Box::new(wasm_table_t {
|
||||||
|
table: (*e).ext.borrow().table().clone(),
|
||||||
|
});
|
||||||
|
Box::into_raw(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_func_as_ref(f: *mut wasm_func_t) -> *mut wasm_ref_t {
|
||||||
|
let callable = (*f).func.borrow().callable().clone();
|
||||||
|
let f = Box::new(wasm_ref_t {
|
||||||
|
r: AnyRef::Func(FuncRef(callable)),
|
||||||
|
});
|
||||||
|
Box::into_raw(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_ref_delete(r: *mut wasm_ref_t) {
|
||||||
|
if !r.is_null() {
|
||||||
|
let _ = Box::from_raw(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_delete(t: *mut wasm_table_t) {
|
||||||
|
let _ = Box::from_raw(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_copy(t: *const wasm_table_t) -> *mut wasm_table_t {
|
||||||
|
Box::into_raw(Box::new((*t).clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_new(
|
||||||
|
store: *mut wasm_store_t,
|
||||||
|
tt: *const wasm_tabletype_t,
|
||||||
|
init: *mut wasm_ref_t,
|
||||||
|
) -> *mut wasm_table_t {
|
||||||
|
let init: Val = if !init.is_null() {
|
||||||
|
Box::from_raw(init).r.into()
|
||||||
|
} else {
|
||||||
|
Val::AnyRef(AnyRef::Null)
|
||||||
|
};
|
||||||
|
let t = Box::new(wasm_table_t {
|
||||||
|
table: Rc::new(RefCell::new(Table::new(
|
||||||
|
(*store).store.clone(),
|
||||||
|
(*tt).tabletype.clone(),
|
||||||
|
init,
|
||||||
|
))),
|
||||||
|
});
|
||||||
|
Box::into_raw(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn into_funcref(val: Val) -> *mut wasm_ref_t {
|
||||||
|
if let Val::AnyRef(AnyRef::Null) = val {
|
||||||
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
|
let r = Box::new(wasm_ref_t { r: val.into() });
|
||||||
|
Box::into_raw(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn from_funcref(r: *mut wasm_ref_t) -> Val {
|
||||||
|
if !r.is_null() {
|
||||||
|
Box::from_raw(r).r.into()
|
||||||
|
} else {
|
||||||
|
Val::AnyRef(AnyRef::Null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_get(
|
||||||
|
t: *const wasm_table_t,
|
||||||
|
index: wasm_table_size_t,
|
||||||
|
) -> *mut wasm_ref_t {
|
||||||
|
let val = (*t).table.borrow().get(index);
|
||||||
|
into_funcref(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_set(
|
||||||
|
t: *mut wasm_table_t,
|
||||||
|
index: wasm_table_size_t,
|
||||||
|
r: *mut wasm_ref_t,
|
||||||
|
) -> bool {
|
||||||
|
let val = from_funcref(r);
|
||||||
|
(*t).table.borrow().set(index, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_size(t: *const wasm_table_t) -> wasm_table_size_t {
|
||||||
|
(*t).table.borrow().size()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_grow(
|
||||||
|
t: *mut wasm_table_t,
|
||||||
|
delta: wasm_table_size_t,
|
||||||
|
init: *mut wasm_ref_t,
|
||||||
|
) -> bool {
|
||||||
|
let init = from_funcref(init);
|
||||||
|
(*t).table.borrow_mut().grow(delta, init)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_table_same(t1: *const wasm_table_t, t2: *const wasm_table_t) -> bool {
|
||||||
|
(*t1).table.as_ptr() == (*t2).table.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_tabletype_delete(tt: *mut wasm_tabletype_t) {
|
||||||
|
let _ = Box::from_raw(tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn wasm_tabletype_new(
|
||||||
|
ty: *mut wasm_valtype_t,
|
||||||
|
limits: *const wasm_limits_t,
|
||||||
|
) -> *mut wasm_tabletype_t {
|
||||||
|
let ty = Box::from_raw(ty).ty;
|
||||||
|
let limits = Limits::new((*limits).min, (*limits).max);
|
||||||
|
let tt = Box::new(wasm_tabletype_t {
|
||||||
|
tabletype: TableType::new(ty, limits),
|
||||||
|
element_cache: None,
|
||||||
|
limits_cache: None,
|
||||||
|
});
|
||||||
|
Box::into_raw(tt)
|
||||||
|
}
|
||||||
|
|||||||
@@ -181,7 +181,8 @@ impl Compiler {
|
|||||||
self.code_memory.publish();
|
self.code_memory.publish();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn signatures(&mut self) -> &mut SignatureRegistry {
|
/// Shared signature registry.
|
||||||
|
pub fn signatures(&mut self) -> &mut SignatureRegistry {
|
||||||
&mut self.signatures
|
&mut self.signatures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,9 @@ pub use crate::sig_registry::SignatureRegistry;
|
|||||||
pub use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
|
pub use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
|
||||||
pub use crate::traphandlers::{wasmtime_call, wasmtime_call_trampoline};
|
pub use crate::traphandlers::{wasmtime_call, wasmtime_call_trampoline};
|
||||||
pub use crate::vmcontext::{
|
pub use crate::vmcontext::{
|
||||||
VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition, VMGlobalImport,
|
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition,
|
||||||
VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport,
|
VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition,
|
||||||
|
VMTableImport,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Version number of this crate.
|
/// Version number of this crate.
|
||||||
|
|||||||
@@ -387,7 +387,7 @@ impl VMGlobalDefinition {
|
|||||||
/// An index into the shared signature registry, usable for checking signatures
|
/// An index into the shared signature registry, usable for checking signatures
|
||||||
/// at indirect calls.
|
/// at indirect calls.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||||
pub struct VMSharedSignatureIndex(u32);
|
pub struct VMSharedSignatureIndex(u32);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -422,14 +422,23 @@ impl VMSharedSignatureIndex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for VMSharedSignatureIndex {
|
||||||
|
fn default() -> Self {
|
||||||
|
VMSharedSignatureIndex::new(u32::MAX)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The VM caller-checked "anyfunc" record, for caller-side signature checking.
|
/// The VM caller-checked "anyfunc" record, for caller-side signature checking.
|
||||||
/// It consists of the actual function pointer and a signature id to be checked
|
/// It consists of the actual function pointer and a signature id to be checked
|
||||||
/// by the caller.
|
/// by the caller.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VMCallerCheckedAnyfunc {
|
pub struct VMCallerCheckedAnyfunc {
|
||||||
|
/// Function body.
|
||||||
pub func_ptr: *const VMFunctionBody,
|
pub func_ptr: *const VMFunctionBody,
|
||||||
|
/// Function signature id.
|
||||||
pub type_index: VMSharedSignatureIndex,
|
pub type_index: VMSharedSignatureIndex,
|
||||||
|
/// Function `VMContext`.
|
||||||
pub vmctx: *mut VMContext,
|
pub vmctx: *mut VMContext,
|
||||||
// If more elements are added here, remember to add offset_of tests below!
|
// If more elements are added here, remember to add offset_of tests below!
|
||||||
}
|
}
|
||||||
@@ -467,7 +476,7 @@ impl Default for VMCallerCheckedAnyfunc {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
func_ptr: ptr::null_mut(),
|
func_ptr: ptr::null_mut(),
|
||||||
type_index: VMSharedSignatureIndex::new(u32::MAX),
|
type_index: Default::default(),
|
||||||
vmctx: ptr::null_mut(),
|
vmctx: ptr::null_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user