Remove HostRef from the wasmtime public API (#788)
* Remove `HostRef` from the `wasmtime` public API
This commit removes all remaining usages of `HostRef` in the public API
of the `wasmtime` crate. This involved a number of API decisions such
as:
* None of `Func`, `Global`, `Table`, or `Memory` are wrapped in `HostRef`
* All of `Func`, `Global`, `Table`, and `Memory` implement `Clone` now.
* Methods called `type` are renamed to `ty` to avoid typing `r#type`.
* Methods requiring mutability for external items now no longer require
mutability. The mutable reference here is sort of a lie anyway since
the internals are aliased by the underlying module anyway. This
affects:
* `Table::set`
* `Table::grow`
* `Memory::grow`
* `Instance::set_signal_handler`
* The `Val::FuncRef` type is now no longer automatically coerced to
`AnyRef`. This is technically a breaking change which is pretty bad,
but I'm hoping that we can live with this interim state while we sort
out the `AnyRef` story in general.
* The implementation of the C API was refactored and updated in a few
locations to account for these changes:
* Accessing the exports of an instance are now cached to ensure we
always hand out the same `HostRef` values.
* `wasm_*_t` for external values no longer have internal cache,
instead they all wrap `wasm_external_t` and have an unchecked
accessor for the underlying variant (since the type is proof that
it's there). This makes casting back and forth much more trivial.
This is all related to #708 and while there's still more work to be done
in terms of documentation, this is the major bulk of the rest of the
implementation work on #708 I believe.
* More API updates
* Run rustfmt
* Fix a doc test
* More test updates
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::callable::{Callable, NativeCallable, WasmtimeFn, WrappedCallable};
|
||||
use crate::r#ref::{AnyRef, HostRef};
|
||||
use crate::r#ref::AnyRef;
|
||||
use crate::runtime::Store;
|
||||
use crate::trampoline::{generate_global_export, generate_memory_export, generate_table_export};
|
||||
use crate::trap::Trap;
|
||||
@@ -15,53 +15,53 @@ use wasmtime_runtime::InstanceHandle;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Extern {
|
||||
Func(HostRef<Func>),
|
||||
Global(HostRef<Global>),
|
||||
Table(HostRef<Table>),
|
||||
Memory(HostRef<Memory>),
|
||||
Func(Func),
|
||||
Global(Global),
|
||||
Table(Table),
|
||||
Memory(Memory),
|
||||
}
|
||||
|
||||
impl Extern {
|
||||
pub fn func(&self) -> Option<&HostRef<Func>> {
|
||||
pub fn func(&self) -> Option<&Func> {
|
||||
match self {
|
||||
Extern::Func(func) => Some(func),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn global(&self) -> Option<&HostRef<Global>> {
|
||||
pub fn global(&self) -> Option<&Global> {
|
||||
match self {
|
||||
Extern::Global(global) => Some(global),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn table(&self) -> Option<&HostRef<Table>> {
|
||||
pub fn table(&self) -> Option<&Table> {
|
||||
match self {
|
||||
Extern::Table(table) => Some(table),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn memory(&self) -> Option<&HostRef<Memory>> {
|
||||
pub fn memory(&self) -> Option<&Memory> {
|
||||
match self {
|
||||
Extern::Memory(memory) => Some(memory),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> ExternType {
|
||||
pub fn ty(&self) -> ExternType {
|
||||
match self {
|
||||
Extern::Func(ft) => ExternType::Func(ft.borrow().r#type().clone()),
|
||||
Extern::Memory(ft) => ExternType::Memory(ft.borrow().r#type().clone()),
|
||||
Extern::Table(tt) => ExternType::Table(tt.borrow().r#type().clone()),
|
||||
Extern::Global(gt) => ExternType::Global(gt.borrow().r#type().clone()),
|
||||
Extern::Func(ft) => ExternType::Func(ft.ty().clone()),
|
||||
Extern::Memory(ft) => ExternType::Memory(ft.ty().clone()),
|
||||
Extern::Table(tt) => ExternType::Table(tt.ty().clone()),
|
||||
Extern::Global(gt) => ExternType::Global(gt.ty().clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export {
|
||||
match self {
|
||||
Extern::Func(f) => f.borrow().wasmtime_export().clone(),
|
||||
Extern::Global(g) => g.borrow().wasmtime_export().clone(),
|
||||
Extern::Memory(m) => m.borrow().wasmtime_export().clone(),
|
||||
Extern::Table(t) => t.borrow().wasmtime_export().clone(),
|
||||
Extern::Func(f) => f.wasmtime_export().clone(),
|
||||
Extern::Global(g) => g.wasmtime_export().clone(),
|
||||
Extern::Memory(m) => m.wasmtime_export().clone(),
|
||||
Extern::Table(t) => t.wasmtime_export().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,50 +71,51 @@ impl Extern {
|
||||
export: wasmtime_runtime::Export,
|
||||
) -> Extern {
|
||||
match export {
|
||||
wasmtime_runtime::Export::Function { .. } => Extern::Func(HostRef::new(
|
||||
Func::from_wasmtime_function(export, store, instance_handle),
|
||||
)),
|
||||
wasmtime_runtime::Export::Memory { .. } => Extern::Memory(HostRef::new(
|
||||
Memory::from_wasmtime_memory(export, store, instance_handle),
|
||||
)),
|
||||
wasmtime_runtime::Export::Global { .. } => {
|
||||
Extern::Global(HostRef::new(Global::from_wasmtime_global(export, store)))
|
||||
wasmtime_runtime::Export::Function { .. } => {
|
||||
Extern::Func(Func::from_wasmtime_function(export, store, instance_handle))
|
||||
}
|
||||
wasmtime_runtime::Export::Memory { .. } => {
|
||||
Extern::Memory(Memory::from_wasmtime_memory(export, store, instance_handle))
|
||||
}
|
||||
wasmtime_runtime::Export::Global { .. } => {
|
||||
Extern::Global(Global::from_wasmtime_global(export, store))
|
||||
}
|
||||
wasmtime_runtime::Export::Table { .. } => {
|
||||
Extern::Table(Table::from_wasmtime_table(export, store, instance_handle))
|
||||
}
|
||||
wasmtime_runtime::Export::Table { .. } => Extern::Table(HostRef::new(
|
||||
Table::from_wasmtime_table(export, store, instance_handle),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Func>> for Extern {
|
||||
fn from(r: HostRef<Func>) -> Self {
|
||||
impl From<Func> for Extern {
|
||||
fn from(r: Func) -> Self {
|
||||
Extern::Func(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Global>> for Extern {
|
||||
fn from(r: HostRef<Global>) -> Self {
|
||||
impl From<Global> for Extern {
|
||||
fn from(r: Global) -> Self {
|
||||
Extern::Global(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Memory>> for Extern {
|
||||
fn from(r: HostRef<Memory>) -> Self {
|
||||
impl From<Memory> for Extern {
|
||||
fn from(r: Memory) -> Self {
|
||||
Extern::Memory(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HostRef<Table>> for Extern {
|
||||
fn from(r: HostRef<Table>) -> Self {
|
||||
impl From<Table> for Extern {
|
||||
fn from(r: Table) -> Self {
|
||||
Extern::Table(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Func {
|
||||
_store: Store,
|
||||
callable: Rc<dyn WrappedCallable + 'static>,
|
||||
r#type: FuncType,
|
||||
ty: FuncType,
|
||||
}
|
||||
|
||||
impl Func {
|
||||
@@ -125,26 +126,26 @@ impl Func {
|
||||
|
||||
fn from_wrapped(
|
||||
store: &Store,
|
||||
r#type: FuncType,
|
||||
ty: FuncType,
|
||||
callable: Rc<dyn WrappedCallable + 'static>,
|
||||
) -> Func {
|
||||
Func {
|
||||
_store: store.clone(),
|
||||
callable,
|
||||
r#type,
|
||||
ty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &FuncType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &FuncType {
|
||||
&self.ty
|
||||
}
|
||||
|
||||
pub fn param_arity(&self) -> usize {
|
||||
self.r#type.params().len()
|
||||
self.ty.params().len()
|
||||
}
|
||||
|
||||
pub fn result_arity(&self) -> usize {
|
||||
self.r#type.results().len()
|
||||
self.ty.results().len()
|
||||
}
|
||||
|
||||
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
|
||||
@@ -178,32 +179,39 @@ impl fmt::Debug for Func {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Global {
|
||||
inner: Rc<GlobalInner>,
|
||||
}
|
||||
|
||||
struct GlobalInner {
|
||||
_store: Store,
|
||||
r#type: GlobalType,
|
||||
ty: GlobalType,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
#[allow(dead_code)]
|
||||
wasmtime_state: Option<crate::trampoline::GlobalState>,
|
||||
}
|
||||
|
||||
impl Global {
|
||||
pub fn new(store: &Store, r#type: GlobalType, val: Val) -> Global {
|
||||
pub fn new(store: &Store, ty: GlobalType, val: Val) -> Global {
|
||||
let (wasmtime_export, wasmtime_state) =
|
||||
generate_global_export(&r#type, val).expect("generated global");
|
||||
generate_global_export(&ty, val).expect("generated global");
|
||||
Global {
|
||||
_store: store.clone(),
|
||||
r#type,
|
||||
wasmtime_export,
|
||||
wasmtime_state: Some(wasmtime_state),
|
||||
inner: Rc::new(GlobalInner {
|
||||
_store: store.clone(),
|
||||
ty,
|
||||
wasmtime_export,
|
||||
wasmtime_state: Some(wasmtime_state),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &GlobalType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &GlobalType {
|
||||
&self.inner.ty
|
||||
}
|
||||
|
||||
fn wasmtime_global_definition(&self) -> *mut wasmtime_runtime::VMGlobalDefinition {
|
||||
match self.wasmtime_export {
|
||||
match self.inner.wasmtime_export {
|
||||
wasmtime_runtime::Export::Global { definition, .. } => definition,
|
||||
_ => panic!("global definition not found"),
|
||||
}
|
||||
@@ -212,22 +220,22 @@ impl Global {
|
||||
pub fn get(&self) -> Val {
|
||||
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
||||
unsafe {
|
||||
match self.r#type().content() {
|
||||
match self.ty().content() {
|
||||
ValType::I32 => Val::from(*definition.as_i32()),
|
||||
ValType::I64 => Val::from(*definition.as_i64()),
|
||||
ValType::F32 => Val::F32(*definition.as_u32()),
|
||||
ValType::F64 => Val::F64(*definition.as_u64()),
|
||||
_ => unimplemented!("Global::get for {:?}", self.r#type().content()),
|
||||
_ => unimplemented!("Global::get for {:?}", self.ty().content()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, val: Val) {
|
||||
if val.r#type() != *self.r#type().content() {
|
||||
pub fn set(&self, val: Val) {
|
||||
if val.ty() != *self.ty().content() {
|
||||
panic!(
|
||||
"global of type {:?} cannot be set to {:?}",
|
||||
self.r#type().content(),
|
||||
val.r#type()
|
||||
self.ty().content(),
|
||||
val.ty()
|
||||
);
|
||||
}
|
||||
let definition = unsafe { &mut *self.wasmtime_global_definition() };
|
||||
@@ -237,13 +245,13 @@ impl Global {
|
||||
Val::I64(i) => *definition.as_i64_mut() = i,
|
||||
Val::F32(f) => *definition.as_u32_mut() = f,
|
||||
Val::F64(f) => *definition.as_u64_mut() = f,
|
||||
_ => unimplemented!("Global::set for {:?}", val.r#type()),
|
||||
_ => unimplemented!("Global::set for {:?}", val.ty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn wasmtime_export(&self) -> &wasmtime_runtime::Export {
|
||||
&self.wasmtime_export
|
||||
&self.inner.wasmtime_export
|
||||
}
|
||||
|
||||
pub(crate) fn from_wasmtime_global(export: wasmtime_runtime::Export, store: &Store) -> Global {
|
||||
@@ -254,17 +262,20 @@ impl Global {
|
||||
};
|
||||
let ty = GlobalType::from_wasmtime_global(&global);
|
||||
Global {
|
||||
_store: store.clone(),
|
||||
r#type: ty,
|
||||
wasmtime_export: export,
|
||||
wasmtime_state: None,
|
||||
inner: Rc::new(GlobalInner {
|
||||
_store: store.clone(),
|
||||
ty: ty,
|
||||
wasmtime_export: export,
|
||||
wasmtime_state: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Table {
|
||||
store: Store,
|
||||
r#type: TableType,
|
||||
ty: TableType,
|
||||
wasmtime_handle: InstanceHandle,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
}
|
||||
@@ -299,13 +310,13 @@ fn set_table_item(
|
||||
}
|
||||
|
||||
impl Table {
|
||||
pub fn new(store: &Store, r#type: TableType, init: Val) -> Table {
|
||||
match r#type.element() {
|
||||
pub fn new(store: &Store, ty: TableType, init: Val) -> Table {
|
||||
match ty.element() {
|
||||
ValType::FuncRef => (),
|
||||
_ => panic!("table is not for funcref"),
|
||||
}
|
||||
let (mut wasmtime_handle, wasmtime_export) =
|
||||
generate_table_export(&r#type).expect("generated table");
|
||||
generate_table_export(&ty).expect("generated table");
|
||||
|
||||
// Initialize entries with the init value.
|
||||
match wasmtime_export {
|
||||
@@ -323,14 +334,14 @@ impl Table {
|
||||
|
||||
Table {
|
||||
store: store.clone(),
|
||||
r#type,
|
||||
ty,
|
||||
wasmtime_handle,
|
||||
wasmtime_export,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &TableType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &TableType {
|
||||
&self.ty
|
||||
}
|
||||
|
||||
fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex {
|
||||
@@ -362,9 +373,9 @@ impl Table {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, delta: u32, init: Val) -> bool {
|
||||
pub fn grow(&self, delta: u32, init: Val) -> bool {
|
||||
let index = self.wasmtime_table_index();
|
||||
if let Some(len) = self.wasmtime_handle.table_grow(index, delta) {
|
||||
if let Some(len) = self.wasmtime_handle.clone().table_grow(index, delta) {
|
||||
let mut wasmtime_handle = self.wasmtime_handle.clone();
|
||||
for i in 0..delta {
|
||||
let i = len - (delta - i);
|
||||
@@ -395,34 +406,35 @@ impl Table {
|
||||
let ty = TableType::from_wasmtime_table(&table.table);
|
||||
Table {
|
||||
store: store.clone(),
|
||||
r#type: ty,
|
||||
ty: ty,
|
||||
wasmtime_handle: instance_handle,
|
||||
wasmtime_export: export,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Memory {
|
||||
_store: Store,
|
||||
r#type: MemoryType,
|
||||
ty: MemoryType,
|
||||
wasmtime_handle: InstanceHandle,
|
||||
wasmtime_export: wasmtime_runtime::Export,
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub fn new(store: &Store, r#type: MemoryType) -> Memory {
|
||||
pub fn new(store: &Store, ty: MemoryType) -> Memory {
|
||||
let (wasmtime_handle, wasmtime_export) =
|
||||
generate_memory_export(&r#type).expect("generated memory");
|
||||
generate_memory_export(&ty).expect("generated memory");
|
||||
Memory {
|
||||
_store: store.clone(),
|
||||
r#type,
|
||||
ty,
|
||||
wasmtime_handle,
|
||||
wasmtime_export,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> &MemoryType {
|
||||
&self.r#type
|
||||
pub fn ty(&self) -> &MemoryType {
|
||||
&self.ty
|
||||
}
|
||||
|
||||
fn wasmtime_memory_definition(&self) -> *mut wasmtime_runtime::VMMemoryDefinition {
|
||||
@@ -453,12 +465,15 @@ impl Memory {
|
||||
(self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32
|
||||
}
|
||||
|
||||
pub fn grow(&mut self, delta: u32) -> bool {
|
||||
pub fn grow(&self, delta: u32) -> bool {
|
||||
match self.wasmtime_export {
|
||||
wasmtime_runtime::Export::Memory { definition, .. } => {
|
||||
let definition = unsafe { &(*definition) };
|
||||
let index = self.wasmtime_handle.memory_index(definition);
|
||||
self.wasmtime_handle.memory_grow(index, delta).is_some()
|
||||
self.wasmtime_handle
|
||||
.clone()
|
||||
.memory_grow(index, delta)
|
||||
.is_some()
|
||||
}
|
||||
_ => panic!("memory definition not found"),
|
||||
}
|
||||
@@ -481,7 +496,7 @@ impl Memory {
|
||||
let ty = MemoryType::from_wasmtime_memory(&memory.memory);
|
||||
Memory {
|
||||
_store: store.clone(),
|
||||
r#type: ty,
|
||||
ty: ty,
|
||||
wasmtime_handle: instance_handle,
|
||||
wasmtime_export: export,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user