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::trap::Trap;
|
||||
use crate::types::FuncType;
|
||||
use crate::values::Val;
|
||||
use core::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::trampoline::generate_func_export;
|
||||
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>>>;
|
||||
}
|
||||
|
||||
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 {
|
||||
store: Rc<RefCell<Store>>,
|
||||
signature: ir::Signature,
|
||||
body: *const VMFunctionBody,
|
||||
vmctx: *mut VMContext,
|
||||
instance: InstanceHandle,
|
||||
export: Export,
|
||||
}
|
||||
|
||||
impl WasmtimeFn {
|
||||
pub fn new(
|
||||
store: Rc<RefCell<Store>>,
|
||||
signature: ir::Signature,
|
||||
body: *const VMFunctionBody,
|
||||
vmctx: *mut VMContext,
|
||||
) -> WasmtimeFn {
|
||||
pub fn new(store: Rc<RefCell<Store>>, instance: InstanceHandle, export: Export) -> WasmtimeFn {
|
||||
WasmtimeFn {
|
||||
store,
|
||||
signature,
|
||||
body,
|
||||
vmctx,
|
||||
instance,
|
||||
export,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Callable for WasmtimeFn {
|
||||
|
||||
impl WrappedCallable for WasmtimeFn {
|
||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Rc<RefCell<Trap>>> {
|
||||
use core::cmp::max;
|
||||
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 context = store.context();
|
||||
@@ -63,13 +80,13 @@ impl Callable for WasmtimeFn {
|
||||
// Get the trampoline to call for this function.
|
||||
let exec_code_buf = context
|
||||
.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)?;
|
||||
|
||||
// Call the trampoline.
|
||||
if let Err(message) = unsafe {
|
||||
wasmtime_runtime::wasmtime_call_trampoline(
|
||||
self.vmctx,
|
||||
vmctx,
|
||||
exec_code_buf,
|
||||
values_vec.as_mut_ptr() as *mut u8,
|
||||
)
|
||||
@@ -78,7 +95,7 @@ impl Callable for WasmtimeFn {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
let ptr = values_vec.as_ptr().add(index);
|
||||
|
||||
@@ -94,4 +111,44 @@ impl Callable for WasmtimeFn {
|
||||
|
||||
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::table_utils;
|
||||
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
|
||||
use crate::trap::Trap;
|
||||
use crate::types::{ExternType, FuncType, GlobalType, MemoryType, TableType, ValType};
|
||||
use crate::values::Val;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::result::Result;
|
||||
|
||||
use crate::trampoline::{generate_func_export, generate_global_export, generate_memory_export};
|
||||
use wasmtime_runtime::InstanceHandle;
|
||||
|
||||
// Externals
|
||||
|
||||
pub enum Extern {
|
||||
@@ -55,15 +56,10 @@ impl Extern {
|
||||
|
||||
pub(crate) fn get_wasmtime_export(&mut self) -> wasmtime_runtime::Export {
|
||||
match self {
|
||||
Extern::Func(f) => {
|
||||
if f.borrow().anchor.is_none() {
|
||||
generate_func_export(&f).expect("generate_func_export");
|
||||
}
|
||||
f.borrow().anchor.as_ref().unwrap().1.clone()
|
||||
}
|
||||
Extern::Func(f) => f.borrow().wasmtime_export().clone(),
|
||||
Extern::Global(g) => g.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,
|
||||
) -> Extern {
|
||||
match export {
|
||||
wasmtime_runtime::Export::Function {
|
||||
address,
|
||||
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::Function { .. } => Extern::Func(Rc::new(RefCell::new(
|
||||
Func::from_wasmtime_function(export, store, instance_handle),
|
||||
))),
|
||||
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(Rc::new(RefCell::new(
|
||||
Memory::from_wasmtime_memory(export, store, instance_handle),
|
||||
))),
|
||||
wasmtime_runtime::Export::Global { .. } => Extern::Global(Rc::new(RefCell::new(
|
||||
Global::from_wasmtime_global(export, store),
|
||||
))),
|
||||
wasmtime_runtime::Export::Table {
|
||||
definition: _,
|
||||
vmctx: _,
|
||||
table,
|
||||
} => {
|
||||
let ty = TableType::from_cranelift_table(table.table.clone());
|
||||
Extern::Table(Rc::new(RefCell::new(Table::new(store, ty))))
|
||||
}
|
||||
wasmtime_runtime::Export::Table { .. } => Extern::Table(Rc::new(RefCell::new(
|
||||
Table::from_wasmtime_table(export, store, instance_handle),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Func {
|
||||
_store: Rc<RefCell<Store>>,
|
||||
callable: Rc<dyn Callable + 'static>,
|
||||
callable: Rc<dyn WrappedCallable + 'static>,
|
||||
r#type: FuncType,
|
||||
pub(crate) anchor: Option<(InstanceHandle, wasmtime_runtime::Export)>,
|
||||
}
|
||||
|
||||
impl Func {
|
||||
pub fn new(
|
||||
store: Rc<RefCell<Store>>,
|
||||
r#type: FuncType,
|
||||
ty: FuncType,
|
||||
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 {
|
||||
_store: store,
|
||||
callable,
|
||||
r#type,
|
||||
anchor: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +117,10 @@ impl Func {
|
||||
&self.r#type
|
||||
}
|
||||
|
||||
pub(crate) fn callable(&self) -> &Rc<dyn WrappedCallable + 'static> {
|
||||
&self.callable
|
||||
}
|
||||
|
||||
pub fn param_arity(&self) -> usize {
|
||||
self.r#type.params().len()
|
||||
}
|
||||
@@ -135,15 +129,29 @@ impl Func {
|
||||
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>>> {
|
||||
let mut results = vec![Val::default(); self.result_arity()];
|
||||
self.callable.call(params, &mut results)?;
|
||||
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 {
|
||||
@@ -234,15 +242,27 @@ impl Global {
|
||||
}
|
||||
|
||||
pub struct Table {
|
||||
_store: Rc<RefCell<Store>>,
|
||||
store: Rc<RefCell<Store>>,
|
||||
r#type: TableType,
|
||||
#[allow(dead_code)]
|
||||
wasmtime_handle: InstanceHandle,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
}
|
||||
|
||||
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 {
|
||||
_store: store,
|
||||
store,
|
||||
r#type,
|
||||
wasmtime_handle,
|
||||
wasmtime_export,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,20 +270,54 @@ impl Table {
|
||||
&self.r#type
|
||||
}
|
||||
|
||||
pub fn get(&self, _index: u32) -> Val {
|
||||
unimplemented!("Table::get")
|
||||
fn wasmtime_table_definition(&self) -> *mut wasmtime_runtime::VMTableDefinition {
|
||||
match self.wasmtime_export {
|
||||
wasmtime_runtime::Export::Table { definition, .. } => definition,
|
||||
_ => panic!("global definition not found"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&self, _index: u32, _val: &Val) -> usize {
|
||||
unimplemented!("Table::set")
|
||||
pub fn get(&self, index: u32) -> Val {
|
||||
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 {
|
||||
unimplemented!("Table::size")
|
||||
let definition = self.wasmtime_table_definition();
|
||||
unsafe { table_utils::get_size(definition) }
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, _delta: u32) -> bool {
|
||||
unimplemented!("Table::grow")
|
||||
pub fn grow(&mut self, delta: u32, init: Val) -> bool {
|
||||
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();
|
||||
for (name, _) in instance_handle.clone().exports() {
|
||||
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());
|
||||
exports.push(Rc::new(RefCell::new(Extern::from_wasmtime_export(
|
||||
store.clone(),
|
||||
|
||||
@@ -6,6 +6,7 @@ mod externals;
|
||||
mod instance;
|
||||
mod module;
|
||||
mod runtime;
|
||||
mod table_utils;
|
||||
mod trampoline;
|
||||
mod trap;
|
||||
mod types;
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::rc::Rc;
|
||||
|
||||
use crate::context::{create_compiler, Context};
|
||||
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_codegen::{ir, settings};
|
||||
use wasmtime_jit::Features;
|
||||
|
||||
// Runtime Environment
|
||||
@@ -79,10 +79,22 @@ impl Engine {
|
||||
|
||||
// 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 {
|
||||
engine: Rc<RefCell<Engine>>,
|
||||
context: Context,
|
||||
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||
signature_cache: HashMap<wasmtime_runtime::VMSharedSignatureIndex, ir::Signature>,
|
||||
}
|
||||
|
||||
impl Store {
|
||||
@@ -94,6 +106,7 @@ impl Store {
|
||||
engine,
|
||||
context: Context::create(flags, features, debug_info),
|
||||
global_exports: Rc::new(RefCell::new(HashMap::new())),
|
||||
signature_cache: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,3 +125,26 @@ impl Store {
|
||||
&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 std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn create_handle(
|
||||
use crate::runtime::SignatureRegistry;
|
||||
|
||||
pub(crate) fn create_handle(
|
||||
module: Module,
|
||||
signature_registry: Option<RefMut<dyn SignatureRegistry>>,
|
||||
finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody>,
|
||||
state: Box<dyn Any>,
|
||||
) -> Result<InstanceHandle, Error> {
|
||||
@@ -28,7 +31,19 @@ pub fn create_handle(
|
||||
PrimaryMap::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(
|
||||
Rc::new(module),
|
||||
|
||||
@@ -17,12 +17,12 @@ use core::cmp;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{Func, Trap, Val};
|
||||
use crate::{Callable, FuncType, Store, Trap, Val};
|
||||
|
||||
use super::create_handle::create_handle;
|
||||
|
||||
struct TrampolineState {
|
||||
func: Rc<RefCell<Func>>,
|
||||
func: Rc<dyn Callable + 'static>,
|
||||
trap: Option<Rc<RefCell<Trap>>>,
|
||||
#[allow(dead_code)]
|
||||
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())
|
||||
};
|
||||
|
||||
let func = instance
|
||||
let mut returns = vec![Val::default(); returns_len];
|
||||
let func = &instance
|
||||
.host_state()
|
||||
.downcast_mut::<TrampolineState>()
|
||||
.expect("state")
|
||||
.func
|
||||
.borrow();
|
||||
.func;
|
||||
|
||||
match func.call(&args) {
|
||||
Ok(returns) => {
|
||||
match func.call(&args, &mut returns) {
|
||||
Ok(()) => {
|
||||
for i in 0..returns_len {
|
||||
// TODO check signature.returns[i].value_type ?
|
||||
returns[i].write_value_to(values_vec.offset(i as isize));
|
||||
@@ -188,8 +188,12 @@ fn make_trampoline(
|
||||
.as_ptr()
|
||||
}
|
||||
|
||||
pub fn create_handle_with_function(func: &Rc<RefCell<Func>>) -> Result<InstanceHandle, Error> {
|
||||
let sig = func.borrow().r#type().get_cranelift_signature().clone();
|
||||
pub fn create_handle_with_function(
|
||||
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_builder =
|
||||
@@ -229,7 +233,12 @@ pub fn create_handle_with_function(func: &Rc<RefCell<Func>>) -> Result<InstanceH
|
||||
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
|
||||
|
||||
@@ -35,7 +35,8 @@ pub fn create_global(
|
||||
},
|
||||
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((
|
||||
wasmtime_runtime::Export::Global {
|
||||
definition: definition.as_mut(),
|
||||
|
||||
@@ -29,5 +29,5 @@ pub fn create_handle_with_memory(memory: &MemoryType) -> Result<InstanceHandle,
|
||||
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 global;
|
||||
mod memory;
|
||||
mod table;
|
||||
|
||||
use failure::Error;
|
||||
use std::cell::RefCell;
|
||||
@@ -13,16 +14,19 @@ use std::rc::Rc;
|
||||
use self::func::create_handle_with_function;
|
||||
use self::global::create_global;
|
||||
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 fn generate_func_export(f: &Rc<RefCell<Func>>) -> Result<(), Error> {
|
||||
let mut instance = create_handle_with_function(f)?;
|
||||
pub fn generate_func_export(
|
||||
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");
|
||||
|
||||
f.borrow_mut().anchor = Some((instance, export));
|
||||
Ok(())
|
||||
Ok((instance, export))
|
||||
}
|
||||
|
||||
pub fn generate_global_export(
|
||||
@@ -39,3 +43,11 @@ pub fn generate_memory_export(
|
||||
let export = instance.lookup("memory").expect("memory 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 std::cell::RefCell;
|
||||
use std::any::Any;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
@@ -9,22 +9,30 @@ use cranelift_codegen::ir;
|
||||
use wasmtime_jit::RuntimeValue;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AnyRef;
|
||||
pub enum AnyRef {
|
||||
Null,
|
||||
Rc(Rc<dyn Any>),
|
||||
Func(FuncRef),
|
||||
}
|
||||
|
||||
impl AnyRef {
|
||||
pub fn null() -> AnyRef {
|
||||
AnyRef
|
||||
AnyRef::Null
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AnyRef {
|
||||
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 {
|
||||
pub callable: Box<dyn Callable + 'static>,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct FuncRef(pub(crate) Rc<dyn WrappedCallable + 'static>);
|
||||
|
||||
impl fmt::Debug for FuncRef {
|
||||
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)]
|
||||
pub enum Val {
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
F32(u32),
|
||||
F64(u64),
|
||||
AnyRef(Rc<RefCell<AnyRef>>),
|
||||
FuncRef(Rc<RefCell<FuncRef>>),
|
||||
AnyRef(AnyRef),
|
||||
FuncRef(FuncRef),
|
||||
}
|
||||
|
||||
impl Val {
|
||||
pub fn default() -> Val {
|
||||
Val::AnyRef(Rc::new(RefCell::new(AnyRef::null())))
|
||||
Val::AnyRef(AnyRef::null())
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> ValType {
|
||||
@@ -151,14 +175,27 @@ impl Into<f64> for Val {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<RefCell<AnyRef>>> for Val {
|
||||
fn from(val: Rc<RefCell<AnyRef>>) -> Val {
|
||||
Val::AnyRef(val)
|
||||
impl From<AnyRef> for Val {
|
||||
fn from(val: AnyRef) -> Val {
|
||||
match val {
|
||||
AnyRef::Func(f) => Val::FuncRef(f),
|
||||
_ => Val::AnyRef(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<RefCell<FuncRef>>> for Val {
|
||||
fn from(val: Rc<RefCell<FuncRef>>) -> Val {
|
||||
impl From<FuncRef> for Val {
|
||||
fn from(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
|
||||
|
||||
use super::{
|
||||
Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
||||
ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store, TableType, Trap, Val,
|
||||
ValType,
|
||||
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncRef, FuncType, Global,
|
||||
GlobalType, ImportType, Instance, Limits, Memory, MemoryType, Module, Name, Store, Table,
|
||||
TableType, Trap, Val, ValType,
|
||||
};
|
||||
use std::boxed::Box;
|
||||
use std::cell::RefCell;
|
||||
@@ -268,7 +268,7 @@ declare_vec!(wasm_exporttype_vec_t, *mut wasm_exporttype_t);
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_ref_t {
|
||||
_unused: [u8; 0],
|
||||
r: AnyRef,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -360,7 +360,7 @@ pub struct wasm_global_t {
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct wasm_table_t {
|
||||
_unused: [u8; 0],
|
||||
table: Rc<RefCell<Table>>,
|
||||
}
|
||||
pub type wasm_table_size_t = u32;
|
||||
#[repr(C)]
|
||||
@@ -1334,3 +1334,133 @@ pub unsafe extern "C" fn wasm_memorytype_new(
|
||||
});
|
||||
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();
|
||||
}
|
||||
|
||||
pub(crate) fn signatures(&mut self) -> &mut SignatureRegistry {
|
||||
/// Shared signature registry.
|
||||
pub fn signatures(&mut self) -> &mut SignatureRegistry {
|
||||
&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::traphandlers::{wasmtime_call, wasmtime_call_trampoline};
|
||||
pub use crate::vmcontext::{
|
||||
VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition, VMGlobalImport,
|
||||
VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport,
|
||||
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition,
|
||||
VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition,
|
||||
VMTableImport,
|
||||
};
|
||||
|
||||
/// Version number of this crate.
|
||||
|
||||
@@ -387,7 +387,7 @@ impl VMGlobalDefinition {
|
||||
/// An index into the shared signature registry, usable for checking signatures
|
||||
/// at indirect calls.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||
pub struct VMSharedSignatureIndex(u32);
|
||||
|
||||
#[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.
|
||||
/// It consists of the actual function pointer and a signature id to be checked
|
||||
/// by the caller.
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct VMCallerCheckedAnyfunc {
|
||||
/// Function body.
|
||||
pub func_ptr: *const VMFunctionBody,
|
||||
/// Function signature id.
|
||||
pub type_index: VMSharedSignatureIndex,
|
||||
/// Function `VMContext`.
|
||||
pub vmctx: *mut VMContext,
|
||||
// If more elements are added here, remember to add offset_of tests below!
|
||||
}
|
||||
@@ -467,7 +476,7 @@ impl Default for VMCallerCheckedAnyfunc {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
func_ptr: ptr::null_mut(),
|
||||
type_index: VMSharedSignatureIndex::new(u32::MAX),
|
||||
type_index: Default::default(),
|
||||
vmctx: ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user