Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce the wasmtime::EqRef type #9285

Merged
merged 3 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions crates/wasmtime/src/runtime/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,18 +601,23 @@ impl Func {
/// | `Func` | `(ref func)` |
/// | `Option<Nofunc>` | `nullfuncref` aka `(ref null nofunc)` |
/// | `NoFunc` | `(ref nofunc)` |
/// | `Option<ExternRef>` | `externref` aka `(ref null extern)` |
/// | `ExternRef` | `(ref extern)` |
/// | `Option<Rooted<ExternRef>>` | `externref` aka `(ref null extern)` |
/// | `Rooted<ExternRef>` | `(ref extern)` |
/// | `Option<NoExtern>` | `nullexternref` aka `(ref null noextern)` |
/// | `NoExtern` | `(ref noextern)` |
/// | `Option<AnyRef>` | `anyref` aka `(ref null any)` |
/// | `AnyRef` | `(ref any)` |
/// | `Option<Rooted<AnyRef>>` | `anyref` aka `(ref null any)` |
/// | `Rooted<AnyRef>` | `(ref any)` |
/// | `Option<Rooted<EqRef>>` | `eqref` aka `(ref null eq)` |
/// | `Rooted<EqRef>` | `(ref eq)` |
/// | `Option<I31>` | `i31ref` aka `(ref null i31)` |
/// | `I31` | `(ref i31)` |
/// | `Option<StructRef>` | `(ref null struct)` |
/// | `StructRef` | `(ref struct)` |
/// | `Option<ArrayRef>` | `(ref null array)` |
/// | `ArrayRef` | `(ref array)` |
/// | `Option<Rooted<StructRef>>` | `(ref null struct)` |
/// | `Rooted<StructRef>` | `(ref struct)` |
/// | `Option<Rooted<ArrayRef>>` | `(ref null array)` |
/// | `Rooted<ArrayRef>` | `(ref array)` |
///
/// Note that anywhere a `Rooted<T>` appears, a `ManuallyRooted<T>` may also
/// be used.
///
/// Any of the Rust types can be returned from the closure as well, in
/// addition to some extra types
Expand Down Expand Up @@ -1425,27 +1430,30 @@ impl Func {
/// | `i64` | `i64` or `u64` |
/// | `f32` | `f32` |
/// | `f64` | `f64` |
/// | `externref` aka `(ref null extern)` | `Option<ExternRef>` |
/// | `(ref extern)` | `ExternRef` |
/// | `(ref noextern)` | `NoExtern` |
/// | `externref` aka `(ref null extern)` | `Option<Rooted<ExternRef>>` |
/// | `(ref extern)` | `Rooted<ExternRef>` |
/// | `nullexternref` aka `(ref null noextern)` | `Option<NoExtern>` |
/// | `anyref` aka `(ref null any)` | `Option<AnyRef>` |
/// | `(ref any)` | `AnyRef` |
/// | `(ref noextern)` | `NoExtern` |
/// | `anyref` aka `(ref null any)` | `Option<Rooted<AnyRef>>` |
/// | `(ref any)` | `Rooted<AnyRef>` |
/// | `eqref` aka `(ref null eq)` | `Option<Rooted<EqRef>>` |
/// | `(ref eq)` | `Rooted<EqRef>` |
/// | `i31ref` aka `(ref null i31)` | `Option<I31>` |
/// | `(ref i31)` | `I31` |
/// | `structref` aka `(ref null struct)` | `Option<Struct>` |
/// | `(ref struct)` | `Struct` |
/// | `arrayref` aka `(ref null array)` | `Option<Array>` |
/// | `(ref array)` | `Array` |
/// | `structref` aka `(ref null struct)` | `Option<Rooted<StructRef>>` |
/// | `(ref struct)` | `Rooted<StructRef>` |
/// | `arrayref` aka `(ref null array)` | `Option<Rooted<ArrayRef>>` |
/// | `(ref array)` | `Rooted<ArrayRef>` |
/// | `funcref` aka `(ref null func)` | `Option<Func>` |
/// | `(ref func)` | `Func` |
/// | `(ref null <func type index>)` | `Option<Func>` |
/// | `(ref <func type index>)` | `Func` |
/// | `nullfuncref` aka `(ref null nofunc)` | `Option<NoFunc>` |
/// | `(ref nofunc)` | `NoFunc` |
/// | `v128` | `V128` on `x86-64` and `aarch64` only |
/// | `v128` | `V128` |
///
/// (Note that this mapping is the same as that of [`Func::wrap`]).
/// (Note that this mapping is the same as that of [`Func::wrap`], and that
/// anywhere a `Rooted<T>` appears, a `ManuallyRooted<T>` may also appear).
///
/// Note that once the [`TypedFunc`] return value is acquired you'll use either
/// [`TypedFunc::call`] or [`TypedFunc::call_async`] as necessary to actually invoke
Expand Down
2 changes: 2 additions & 0 deletions crates/wasmtime/src/runtime/gc/disabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@

mod anyref;
mod arrayref;
mod eqref;
mod externref;
mod i31;
mod rooting;
mod structref;

pub use anyref::*;
pub use arrayref::*;
pub use eqref::*;
pub use externref::*;
pub use i31::*;
pub use rooting::*;
Expand Down
32 changes: 31 additions & 1 deletion crates/wasmtime/src/runtime/gc/disabled/anyref.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
use crate::runtime::vm::VMGcRef;
use crate::{
store::{AutoAssertNoGc, StoreOpaque},
ArrayRef, AsContext, AsContextMut, GcRefImpl, HeapType, ManuallyRooted, Result, Rooted,
ArrayRef, AsContext, AsContextMut, EqRef, GcRefImpl, HeapType, ManuallyRooted, Result, Rooted,
StructRef, I31,
};

/// Support for `anyref` disabled at compile time because the `gc` cargo feature
/// was not enabled.
pub enum AnyRef {}

impl From<Rooted<EqRef>> for Rooted<AnyRef> {
#[inline]
fn from(s: Rooted<EqRef>) -> Self {
match s.inner {}
}
}

impl From<ManuallyRooted<EqRef>> for ManuallyRooted<AnyRef> {
#[inline]
fn from(s: ManuallyRooted<EqRef>) -> Self {
match s.inner {}
}
}

impl From<Rooted<StructRef>> for Rooted<AnyRef> {
#[inline]
fn from(s: Rooted<StructRef>) -> Self {
Expand Down Expand Up @@ -73,6 +87,22 @@ impl AnyRef {
match *self {}
}

pub fn is_eqref(&self, _store: impl AsContext) -> Result<bool> {
match *self {}
}

pub(crate) fn _is_eqref(&self, _store: &StoreOpaque) -> Result<bool> {
match *self {}
}

pub fn as_eqref(&self, _store: impl AsContext) -> Result<Option<EqRef>> {
match *self {}
}

pub fn unwrap_eqref(&self, _store: impl AsContext) -> Result<EqRef> {
match *self {}
}

pub fn is_i31(&self, _store: impl AsContext) -> Result<bool> {
match *self {}
}
Expand Down
117 changes: 117 additions & 0 deletions crates/wasmtime/src/runtime/gc/disabled/eqref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use crate::runtime::vm::VMGcRef;
use crate::{
store::{AutoAssertNoGc, StoreOpaque},
ArrayRef, AsContext, AsContextMut, GcRefImpl, HeapType, ManuallyRooted, Result, Rooted,
StructRef, I31,
};

/// Support for `eqref` disabled at compile time because the `gc` cargo feature
/// was not enabled.
pub enum EqRef {}

impl From<Rooted<StructRef>> for Rooted<EqRef> {
#[inline]
fn from(s: Rooted<StructRef>) -> Self {
match s.inner {}
}
}

impl From<ManuallyRooted<StructRef>> for ManuallyRooted<EqRef> {
#[inline]
fn from(s: ManuallyRooted<StructRef>) -> Self {
match s.inner {}
}
}

impl From<Rooted<ArrayRef>> for Rooted<EqRef> {
#[inline]
fn from(s: Rooted<ArrayRef>) -> Self {
match s.inner {}
}
}

impl From<ManuallyRooted<ArrayRef>> for ManuallyRooted<EqRef> {
#[inline]
fn from(s: ManuallyRooted<ArrayRef>) -> Self {
match s.inner {}
}
}

impl GcRefImpl for EqRef {}

impl EqRef {
pub(crate) fn from_cloned_gc_ref(
_store: &mut AutoAssertNoGc<'_>,
_gc_ref: VMGcRef,
) -> Rooted<Self> {
unreachable!()
}

pub fn ty(&self, _store: impl AsContext) -> Result<HeapType> {
match *self {}
}

pub(crate) fn _ty(&self, _store: &StoreOpaque) -> Result<HeapType> {
match *self {}
}

pub fn matches_ty(&self, _store: impl AsContext, _ty: &HeapType) -> Result<bool> {
match *self {}
}

pub fn is_i31(&self, _store: impl AsContext) -> Result<bool> {
match *self {}
}

pub(crate) fn _is_i31(&self, _store: &StoreOpaque) -> Result<bool> {
match *self {}
}

pub fn as_i31(&self, _store: impl AsContext) -> Result<Option<I31>> {
match *self {}
}

pub fn unwrap_i31(&self, _store: impl AsContext) -> Result<I31> {
match *self {}
}

pub fn is_struct(&self, _store: impl AsContext) -> Result<bool> {
match *self {}
}

pub(crate) fn _is_struct(&self, _store: &StoreOpaque) -> Result<bool> {
match *self {}
}

pub fn as_struct(&self, _store: impl AsContext) -> Result<Option<StructRef>> {
match *self {}
}

pub(crate) fn _as_struct(&self, _store: &StoreOpaque) -> Result<Option<StructRef>> {
match *self {}
}

pub fn unwrap_struct(&self, _store: impl AsContext) -> Result<StructRef> {
match *self {}
}

pub fn is_array(&self, _store: impl AsContext) -> Result<bool> {
match *self {}
}

pub(crate) fn _is_array(&self, _store: &StoreOpaque) -> Result<bool> {
match *self {}
}

pub fn as_array(&self, _store: impl AsContext) -> Result<Option<ArrayRef>> {
match *self {}
}

pub(crate) fn _as_array(&self, _store: &StoreOpaque) -> Result<Option<ArrayRef>> {
match *self {}
}

pub fn unwrap_array(&self, _store: impl AsContext) -> Result<ArrayRef> {
match *self {}
}
}
2 changes: 2 additions & 0 deletions crates/wasmtime/src/runtime/gc/enabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@

mod anyref;
mod arrayref;
mod eqref;
mod externref;
mod i31;
mod rooting;
mod structref;

pub use anyref::*;
pub use arrayref::*;
pub use eqref::*;
pub use externref::*;
pub use i31::*;
pub use rooting::*;
Expand Down
83 changes: 81 additions & 2 deletions crates/wasmtime/src/runtime/gc/enabled/anyref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::prelude::*;
use crate::runtime::vm::VMGcRef;
use crate::{
store::{AutoAssertNoGc, StoreOpaque},
ArrayRef, ArrayType, AsContext, AsContextMut, GcRefImpl, GcRootIndex, HeapType, ManuallyRooted,
RefType, Result, Rooted, StructRef, StructType, ValRaw, ValType, WasmTy, I31,
ArrayRef, ArrayType, AsContext, AsContextMut, EqRef, GcRefImpl, GcRootIndex, HeapType,
ManuallyRooted, RefType, Result, Rooted, StructRef, StructType, ValRaw, ValType, WasmTy, I31,
};
use core::mem;
use core::mem::MaybeUninit;
Expand Down Expand Up @@ -95,6 +95,20 @@ pub struct AnyRef {
pub(super) inner: GcRootIndex,
}

impl From<Rooted<EqRef>> for Rooted<AnyRef> {
#[inline]
fn from(e: Rooted<EqRef>) -> Self {
e.to_anyref()
}
}

impl From<ManuallyRooted<EqRef>> for ManuallyRooted<AnyRef> {
#[inline]
fn from(e: ManuallyRooted<EqRef>) -> Self {
e.to_anyref()
}
}

impl From<Rooted<StructRef>> for Rooted<AnyRef> {
#[inline]
fn from(s: Rooted<StructRef>) -> Self {
Expand Down Expand Up @@ -326,6 +340,71 @@ impl AnyRef {
}
}

/// Is this `anyref` an `eqref`?
///
/// # Errors
///
/// Return an error if this reference has been unrooted.
///
/// # Panics
///
/// Panics if this reference is associated with a different store.
pub fn is_eqref(&self, store: impl AsContext) -> Result<bool> {
self._is_eqref(store.as_context().0)
}

pub(crate) fn _is_eqref(&self, store: &StoreOpaque) -> Result<bool> {
assert!(self.comes_from_same_store(store));
let gc_ref = self.inner.try_gc_ref(store)?;
Ok(gc_ref.is_i31() || store.gc_store()?.kind(gc_ref).matches(VMGcKind::EqRef))
}

/// Downcast this `anyref` to an `eqref`.
///
/// If this `anyref` is an `eqref`, then `Some(_)` is returned.
///
/// If this `anyref` is not an `eqref`, then `None` is returned.
///
/// # Errors
///
/// Return an error if this reference has been unrooted.
///
/// # Panics
///
/// Panics if this reference is associated with a different store.
pub fn as_eqref(&self, store: impl AsContext) -> Result<Option<Rooted<EqRef>>> {
self._as_eqref(store.as_context().0)
}

pub(crate) fn _as_eqref(&self, store: &StoreOpaque) -> Result<Option<Rooted<EqRef>>> {
if self._is_eqref(store)? {
Ok(Some(Rooted::from_gc_root_index(self.inner)))
} else {
Ok(None)
}
}

/// Downcast this `anyref` to an `eqref`, panicking if this `anyref` is not
/// an `eqref`.
///
/// # Errors
///
/// Return an error if this reference has been unrooted.
///
/// # Panics
///
/// Panics if this reference is associated with a different store, or if
/// this `anyref` is not an `eqref`.
pub fn unwrap_eqref(&self, store: impl AsContext) -> Result<Rooted<EqRef>> {
self._unwrap_eqref(store.as_context().0)
}

pub(crate) fn _unwrap_eqref(&self, store: &StoreOpaque) -> Result<Rooted<EqRef>> {
Ok(self
._as_eqref(store)?
.expect("AnyRef::unwrap_eqref on non-eqref"))
}

/// Is this `anyref` an `i31`?
///
/// # Errors
Expand Down
Loading