Skip to content
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
31 changes: 7 additions & 24 deletions crates/wasmtime/src/runtime/gc/enabled/arrayref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::runtime::vm::VMGcRef;
use crate::store::StoreId;
use crate::vm::{VMArrayRef, VMGcHeader};
use crate::vm::{self, VMArrayRef, VMGcHeader};
use crate::{AnyRef, FieldType};
use crate::{
ArrayType, AsContext, AsContextMut, EqRef, GcHeapOutOfMemory, GcRefImpl, GcRootIndex, HeapType,
Expand Down Expand Up @@ -297,18 +297,9 @@ impl ArrayRef {
elem: &Val,
len: u32,
) -> Result<Rooted<ArrayRef>> {
Self::_new(store.as_context_mut().0, allocator, elem, len)
}

pub(crate) fn _new(
store: &mut StoreOpaque,
allocator: &ArrayRefPre,
elem: &Val,
len: u32,
) -> Result<Rooted<ArrayRef>> {
store.retry_after_gc((), |store, ()| {
Self::new_from_iter(store, allocator, RepeatN(elem, len))
})
let store = store.as_context_mut().0;
assert!(!store.async_support());
vm::assert_ready(Self::_new_async(store, allocator, elem, len))
}

/// Asynchronously allocate a new `array` of the given length, with every
Expand Down Expand Up @@ -454,17 +445,9 @@ impl ArrayRef {
allocator: &ArrayRefPre,
elems: &[Val],
) -> Result<Rooted<ArrayRef>> {
Self::_new_fixed(store.as_context_mut().0, allocator, elems)
}

pub(crate) fn _new_fixed(
store: &mut StoreOpaque,
allocator: &ArrayRefPre,
elems: &[Val],
) -> Result<Rooted<ArrayRef>> {
store.retry_after_gc((), |store, ()| {
Self::new_from_iter(store, allocator, elems.iter())
})
let store = store.as_context_mut().0;
assert!(!store.async_support());
vm::assert_ready(Self::_new_fixed_async(store, allocator, elems))
}

/// Asynchronously allocate a new `array` containing the given elements.
Expand Down
27 changes: 4 additions & 23 deletions crates/wasmtime/src/runtime/gc/enabled/exnref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::runtime::vm::VMGcRef;
use crate::store::StoreId;
use crate::vm::{VMExnRef, VMGcHeader};
use crate::vm::{self, VMExnRef, VMGcHeader};
use crate::{
AsContext, AsContextMut, GcRefImpl, GcRootIndex, HeapType, ManuallyRooted, RefType, Result,
Rooted, Val, ValRaw, ValType, WasmTy,
Expand Down Expand Up @@ -205,23 +205,9 @@ impl ExnRef {
tag: &Tag,
fields: &[Val],
) -> Result<Rooted<ExnRef>> {
Self::_new(store.as_context_mut().0, allocator, tag, fields)
}

pub(crate) fn _new(
store: &mut StoreOpaque,
allocator: &ExnRefPre,
tag: &Tag,
fields: &[Val],
) -> Result<Rooted<ExnRef>> {
assert!(
!store.async_support(),
"use `ExnRef::new_async` with asynchronous stores"
);
Self::type_check_tag_and_fields(store, allocator, tag, fields)?;
store.retry_after_gc((), |store, ()| {
Self::new_unchecked(store, allocator, tag, fields)
})
let store = store.as_context_mut().0;
assert!(!store.async_support());
vm::assert_ready(Self::_new_async(store, allocator, tag, fields))
}

/// Asynchronously allocate a new exception object and get a
Expand Down Expand Up @@ -262,17 +248,12 @@ impl ExnRef {
Self::_new_async(store.as_context_mut().0, allocator, tag, fields).await
}

#[cfg(feature = "async")]
pub(crate) async fn _new_async(
store: &mut StoreOpaque,
allocator: &ExnRefPre,
tag: &Tag,
fields: &[Val],
) -> Result<Rooted<ExnRef>> {
assert!(
store.async_support(),
"use `ExnRef::new` with synchronous stores"
);
Self::type_check_tag_and_fields(store, allocator, tag, fields)?;
store
.retry_after_gc_async((), |store, ()| {
Expand Down
35 changes: 3 additions & 32 deletions crates/wasmtime/src/runtime/gc/enabled/externref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use super::{AnyRef, RootedGcRefImpl};
use crate::prelude::*;
use crate::runtime::vm::VMGcRef;
use crate::runtime::vm::{self, VMGcRef};
use crate::{
AsContextMut, GcHeapOutOfMemory, GcRefImpl, GcRootIndex, HeapType, ManuallyRooted, RefType,
Result, Rooted, StoreContext, StoreContextMut, ValRaw, ValType, WasmTy,
Expand Down Expand Up @@ -215,36 +215,8 @@ impl ExternRef {
T: 'static + Any + Send + Sync,
{
let ctx = context.as_context_mut().0;
Self::_new(ctx, value)
}

pub(crate) fn _new<T>(store: &mut StoreOpaque, value: T) -> Result<Rooted<ExternRef>>
where
T: 'static + Any + Send + Sync,
{
// Allocate the box once, regardless how many gc-and-retry attempts we
// make.
let value: Box<dyn Any + Send + Sync> = Box::new(value);

let gc_ref = store
.retry_after_gc(value, |store, value| {
store
.require_gc_store_mut()?
.alloc_externref(value)
.context("unrecoverable error when allocating new `externref`")?
.map_err(|(x, n)| GcHeapOutOfMemory::new(x, n).into())
})
// Translate the `GcHeapOutOfMemory`'s inner value from the boxed
// trait object into `T`.
.map_err(
|e| match e.downcast::<GcHeapOutOfMemory<Box<dyn Any + Send + Sync>>>() {
Ok(oom) => oom.map_inner(|x| *x.downcast::<T>().unwrap()).into(),
Err(e) => e,
},
)?;

let mut ctx = AutoAssertNoGc::new(store);
Ok(Self::from_cloned_gc_ref(&mut ctx, gc_ref.into()))
assert!(!ctx.async_support());
vm::assert_ready(Self::_new_async(ctx, value))
}

/// Asynchronously allocates a new `ExternRef` wrapping the given value.
Expand Down Expand Up @@ -331,7 +303,6 @@ impl ExternRef {
Self::_new_async(ctx, value).await
}

#[cfg(feature = "async")]
pub(crate) async fn _new_async<T>(
store: &mut StoreOpaque,
value: T,
Expand Down
21 changes: 4 additions & 17 deletions crates/wasmtime/src/runtime/gc/enabled/structref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::runtime::vm::VMGcRef;
use crate::store::StoreId;
use crate::vm::{VMGcHeader, VMStructRef};
use crate::vm::{self, VMGcHeader, VMStructRef};
use crate::{AnyRef, FieldType};
use crate::{
AsContext, AsContextMut, EqRef, GcHeapOutOfMemory, GcRefImpl, GcRootIndex, HeapType,
Expand Down Expand Up @@ -231,22 +231,9 @@ impl StructRef {
allocator: &StructRefPre,
fields: &[Val],
) -> Result<Rooted<StructRef>> {
Self::_new(store.as_context_mut().0, allocator, fields)
}

pub(crate) fn _new(
store: &mut StoreOpaque,
allocator: &StructRefPre,
fields: &[Val],
) -> Result<Rooted<StructRef>> {
assert!(
!store.async_support(),
"use `StructRef::new_async` with asynchronous stores"
);
Self::type_check_fields(store, allocator, fields)?;
store.retry_after_gc((), |store, ()| {
Self::new_unchecked(store, allocator, fields)
})
let store = store.as_context_mut().0;
assert!(!store.async_support());
vm::assert_ready(Self::_new_async(store, allocator, fields))
}

/// Asynchronously allocate a new `struct` and get a reference to it.
Expand Down
33 changes: 0 additions & 33 deletions crates/wasmtime/src/runtime/store/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,39 +165,6 @@ impl StoreOpaque {
}
}

/// Attempt an allocation, if it fails due to GC OOM, then do a GC and
/// retry.
pub(crate) fn retry_after_gc<T, U>(
&mut self,
value: T,
alloc_func: impl Fn(&mut Self, T) -> Result<U>,
) -> Result<U>
where
T: Send + Sync + 'static,
{
assert!(
!self.async_support(),
"use the `*_async` versions of methods when async is configured"
);
vm::assert_ready(self.ensure_gc_store())?;
match alloc_func(self, value) {
Ok(x) => Ok(x),
Err(e) => match e.downcast::<crate::GcHeapOutOfMemory<T>>() {
Ok(oom) => {
let (value, oom) = oom.take_inner();
// SAFETY: FIXME(#11409)
unsafe {
vm::assert_ready(
self.gc_unsafe_get_limiter(None, Some(oom.bytes_needed())),
);
}
alloc_func(self, value)
}
Err(e) => Err(e),
},
}
}

/// Attempt an allocation, if it fails due to GC OOM, then do a GC and
/// retry.
pub(crate) async fn retry_after_gc_async<T, U>(
Expand Down