Trait wasmtime_runtime::GcHeap
source · pub unsafe trait GcHeap: 'static + Send + Sync {
Show 16 methods
// Required methods
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn enter_no_gc_scope(&mut self);
fn exit_no_gc_scope(&mut self);
fn header(&self, gc_ref: &VMGcRef) -> &VMGcHeader;
fn clone_gc_ref(&mut self, gc_ref: &VMGcRef) -> VMGcRef;
fn write_gc_ref(
&mut self,
host_data_table: &mut ExternRefHostDataTable,
destination: &mut Option<VMGcRef>,
source: Option<&VMGcRef>
);
fn expose_gc_ref_to_wasm(&mut self, gc_ref: VMGcRef);
fn need_gc_before_entering_wasm(&self, num_gc_refs: NonZeroUsize) -> bool;
fn alloc_externref(
&mut self,
host_data: ExternRefHostDataId
) -> Result<Option<VMExternRef>>;
fn externref_host_data(
&self,
externref: &VMExternRef
) -> ExternRefHostDataId;
fn gc<'a>(
&'a mut self,
roots: GcRootsIter<'a>,
host_data_table: &'a mut ExternRefHostDataTable
) -> Box<dyn GarbageCollection<'a> + 'a>;
unsafe fn vmctx_gc_heap_base(&self) -> *mut u8;
unsafe fn vmctx_gc_heap_bound(&self) -> usize;
unsafe fn vmctx_gc_heap_data(&self) -> *mut u8;
// Provided method
fn drop_gc_ref(
&mut self,
host_data_table: &mut ExternRefHostDataTable,
gc_ref: VMGcRef
) { ... }
}
Expand description
A heap that manages garbage-collected objects.
Each wasmtime::Store
is associated with a single GcHeap
, and a GcHeap
is only ever used with one store at a time, but GcHeap
s may be reused with
new stores after its original store is dropped. The reset
method will be
called in between each such reuse. (This reuse allows for better integration
with the pooling allocator).
If a GcHeap
mapped any memory, its Drop
implementation should unmap that
memory.
§Safety
The trait methods below are all safe: implementations of this trait must
ensure that these methods cannot be misused to create memory unsafety. The
expectation is that – given that VMGcRef
is a newtype over an index –
implementations perform similar tricks as Wasm linear memory
implementations. The heap should internally be a contiguous region of memory
and VMGcRef
indices into the heap must be bounds checked (explicitly or
implicitly via virtual memory tricks).
Furthermore, if heap corruption occurs because (for example) a VMGcRef
from a different heap is used with this heap, then that corruption must be
limited to within this heap. Every heap is a mini sandbox. It follows that
native pointers should never be written into or read out from the GC heap,
since that could spread corruption from inside the GC heap out to the native
host heap. The host data for an externref
, therefore, is stored in a side
table (ExternRefHostDataTable
) and never inside the heap. Only an id
referencing a slot in that table should ever be written into the GC heap.
These constraints give us great amounts of safety compared to working with
raw pointers. The worst that could happen is corruption local to heap and a
panic, or perhaps reading stale heap data from a previous Wasm instance. A
corrupt GcHeap
can never result in the native host’s corruption.
The downside is that we are introducing heap_base + index
computations and
bounds checking to access GC memory, adding performance overhead. This is
deemed to be a worthy trade off. Furthermore, it isn’t even a clear cut
performance degradation since this allows us to use 32-bit “pointers”,
giving us more compact data representations and the improved cache
utilization that implies.
Required Methods§
sourcefn as_any_mut(&mut self) -> &mut dyn Any
fn as_any_mut(&mut self) -> &mut dyn Any
Get this heap as an &mut Any
.
sourcefn enter_no_gc_scope(&mut self)
fn enter_no_gc_scope(&mut self)
Enter a no-GC scope.
Calling the gc
method when we are inside a no-GC scope should panic.
We can enter multiple, nested no-GC scopes and this method should account for that.
sourcefn exit_no_gc_scope(&mut self)
fn exit_no_gc_scope(&mut self)
Exit a no-GC scope.
Dual to enter_no_gc_scope
.
sourcefn header(&self, gc_ref: &VMGcRef) -> &VMGcHeader
fn header(&self, gc_ref: &VMGcRef) -> &VMGcHeader
Get a shared borrow of the VMGcHeader
that this GC reference is
pointing to.
sourcefn clone_gc_ref(&mut self, gc_ref: &VMGcRef) -> VMGcRef
fn clone_gc_ref(&mut self, gc_ref: &VMGcRef) -> VMGcRef
Read barrier called every time the runtime clones a GC reference.
Callers should pass a valid VMGcRef
that belongs to the given
heap. Failure to do so is memory safe, but may result in general
failures such as panics or incorrect results.
sourcefn write_gc_ref(
&mut self,
host_data_table: &mut ExternRefHostDataTable,
destination: &mut Option<VMGcRef>,
source: Option<&VMGcRef>
)
fn write_gc_ref( &mut self, host_data_table: &mut ExternRefHostDataTable, destination: &mut Option<VMGcRef>, source: Option<&VMGcRef> )
Write barrier called every time the runtime overwrites a GC reference.
The source
is a borrowed GC reference, and should not have been cloned
already for this write operation. This allows implementations to fuse
the source
’s read barrier into this write barrier.
If an externref
is reclaimed, then its associated entry in the
host_data_table
should be removed.
Callers should pass a valid VMGcRef
that belongs to the given heap for
both the source
and destination
. Failure to do so is memory safe,
but may result in general failures such as panics or incorrect results.
sourcefn expose_gc_ref_to_wasm(&mut self, gc_ref: VMGcRef)
fn expose_gc_ref_to_wasm(&mut self, gc_ref: VMGcRef)
Read barrier called whenever a GC reference is passed from the runtime to Wasm: an argument to a host-to-Wasm call, or a return from a Wasm-to-host call.
Callers should pass a valid VMGcRef
that belongs to the given
heap. Failure to do so is memory safe, but may result in general
failures such as panics or incorrect results.
sourcefn need_gc_before_entering_wasm(&self, num_gc_refs: NonZeroUsize) -> bool
fn need_gc_before_entering_wasm(&self, num_gc_refs: NonZeroUsize) -> bool
Predicate invoked before calling into or returning to Wasm to determine whether we should GC first.
num_gc_refs
is the number of non-i31ref
GC references that will be
passed into Wasm.
sourcefn alloc_externref(
&mut self,
host_data: ExternRefHostDataId
) -> Result<Option<VMExternRef>>
fn alloc_externref( &mut self, host_data: ExternRefHostDataId ) -> Result<Option<VMExternRef>>
Allocate a VMExternRef
with space for host data described by the given
layout.
Return values:
-
Ok(Some(_))
: The allocation was successful. -
Ok(None)
: There is currently no available space for this allocation. The caller should callself.gc()
, run the GC to completion so the collector can reclaim space, and then try allocating again. -
Err(_)
: The collector cannot satisfy this allocation request, and would not be able to even after the caller were to trigger a collection. This could be because, for example, the requested allocation is larger than this collector’s implementation limit for object size.
sourcefn externref_host_data(&self, externref: &VMExternRef) -> ExternRefHostDataId
fn externref_host_data(&self, externref: &VMExternRef) -> ExternRefHostDataId
Get the host data ID associated with the given externref
.
Callers should pass a valid externref
that belongs to the given
heap. Failure to do so is memory safe, but may result in general
failures such as panics or incorrect results.
sourcefn gc<'a>(
&'a mut self,
roots: GcRootsIter<'a>,
host_data_table: &'a mut ExternRefHostDataTable
) -> Box<dyn GarbageCollection<'a> + 'a>
fn gc<'a>( &'a mut self, roots: GcRootsIter<'a>, host_data_table: &'a mut ExternRefHostDataTable ) -> Box<dyn GarbageCollection<'a> + 'a>
Start a new garbage collection process.
The given roots
are GC roots and should not be collected (nor anything
transitively reachable from them).
Upon reclaiming an externref
, its associated entry in the
host_data_table
is removed.
Callers should pass valid GC roots that belongs to this heap, and the
host data table associated with this heap’s externref
s. Failure to do
so is memory safe, but may result in general failures such as panics or
incorrect results.
This method should panic if we are in a no-GC scope.
sourceunsafe fn vmctx_gc_heap_base(&self) -> *mut u8
unsafe fn vmctx_gc_heap_base(&self) -> *mut u8
sourceunsafe fn vmctx_gc_heap_bound(&self) -> usize
unsafe fn vmctx_gc_heap_bound(&self) -> usize
sourceunsafe fn vmctx_gc_heap_data(&self) -> *mut u8
unsafe fn vmctx_gc_heap_data(&self) -> *mut u8
Get the pointer that will be stored in the VMContext::gc_heap_data
field and be accessible from JIT code via collaboration with the
corresponding GcCompiler
trait.
§Safety
The returned pointer, if any, must remain valid as long as self
is not
dropped.
Provided Methods§
sourcefn drop_gc_ref(
&mut self,
host_data_table: &mut ExternRefHostDataTable,
gc_ref: VMGcRef
)
fn drop_gc_ref( &mut self, host_data_table: &mut ExternRefHostDataTable, gc_ref: VMGcRef )
Write barrier called whenever the runtime is nulling out a GC reference.
Default implemented in terms of the write_gc_ref
barrier.
If an externref
is reclaimed, then its associated entry in the
host_data_table
should be removed.
Callers should pass a valid VMGcRef
that belongs to the given
heap. Failure to do so is memory safe, but may result in general
failures such as panics or incorrect results.
The given gc_ref
should not be used again.