dusk_wasmtime/runtime/gc/enabled/
rooting.rs

1//! Garbage collection rooting APIs.
2//!
3//! Rooting prevents GC objects from being collected while they are actively
4//! being used.
5//!
6//! ## Goals
7//!
8//! We have a few sometimes-conflicting goals with our GC rooting APIs:
9//!
10//! 1. Safety: It should never be possible to get a use-after-free bug because
11//!    the user misused the rooting APIs, the collector "mistakenly" determined
12//!    an object was unreachable and collected it, and then the user tried to
13//!    access the object. This is our highest priority.
14//!
15//! 2. Moving GC: Our rooting APIs should moving collectors (such as
16//!    generational and compacting collectors) where an object might get
17//!    relocated after a collection and we need to update the GC root's pointer
18//!    to the moved object. This means we either need cooperation and internal
19//!    mutability from individual GC roots as well as the ability to enumerate
20//!    all GC roots on the native Rust stack, or we need a level of indirection.
21//!
22//! 3. Performance: Our rooting APIs should generally be as low-overhead as
23//!    possible. They definitely shouldn't require synchronization and locking
24//!    to create, access, and drop GC roots.
25//!
26//! 4. Ergonomics: Our rooting APIs should be, if not a pleasure, then at least
27//!    not a burden for users. Additionally, the API's types should be `Sync`
28//!    and `Send` so that they work well with async Rust.
29//!
30//! For example, goals (3) and (4) are in conflict when we think about how to
31//! support (2). Ideally, for ergonomics, a root would automatically unroot
32//! itself when dropped. But in the general case that requires holding a
33//! reference to the store's root set, and that root set needs to be held
34//! simultaneously by all GC roots, and they each need to mutate the set to
35//! unroot themselves. That implies `Rc<RefCell<...>>` or `Arc<Mutex<...>>`! The
36//! former makes the store and GC root types not `Send` and not `Sync`. The
37//! latter imposes synchronization and locking overhead. So we instead make GC
38//! roots indirect and require passing in a store context explicitly to unroot
39//! in the general case. This trades worse ergonomics for better performance and
40//! support for moving GC.
41//!
42//! ## Two Flavors of Rooting API
43//!
44//! Okay, with that out of the way, this module provides two flavors of rooting
45//! API. One for the common, scoped lifetime case, and another for the rare case
46//! where we really need a GC root with an arbitrary, non-LIFO/non-scoped
47//! lifetime:
48//!
49//! 1. `RootScope` and `Rooted<T>`: These are used for temporarily rooting GC
50//!    objects for the duration of a scope. The internal implementation takes
51//!    advantage of the LIFO property inherent in scopes, making creating and
52//!    dropping `Rooted<T>`s and `RootScope`s super fast and roughly equivalent
53//!    to bump allocation.
54//!
55//!    This type is vaguely similar to V8's [`HandleScope`].
56//!
57//!    [`HandleScope`]: https://v8.github.io/api/head/classv8_1_1HandleScope.html
58//!
59//!    Note that `Rooted<T>` can't be statically tied to its context scope via a
60//!    lifetime parameter, unfortunately, as that would allow the creation of
61//!    only one `Rooted<T>` at a time, since the `Rooted<T>` would take a borrow
62//!    of the whole context.
63//!
64//!    This supports the common use case for rooting and provides good
65//!    ergonomics.
66//!
67//! 2. `ManuallyRooted<T>`: This is the fully general rooting API used for
68//!    holding onto non-LIFO GC roots with arbitrary lifetimes. However, users
69//!    must manually unroot them. Failure to manually unroot a
70//!    `ManuallyRooted<T>` before it is dropped will result in the GC object
71//!    (and everything it transitively references) leaking for the duration of
72//!    the `Store`'s lifetime.
73//!
74//!    This type is roughly similar to SpiderMonkey's [`PersistentRooted<T>`],
75//!    although they avoid the manual-unrooting with internal mutation and
76//!    shared references. (Our constraints mean we can't do those things, as
77//!    mentioned explained above.)
78//!
79//!    [`PersistentRooted<T>`]: http://devdoc.net/web/developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::PersistentRooted.html
80//!
81//! At the end of the day, both `Rooted<T>` and `ManuallyRooted<T>` are just
82//! tagged indices into the store's `RootSet`. This indirection allows working
83//! with Rust's borrowing discipline (we use `&mut Store` to represent mutable
84//! access to the GC heap) while still allowing rooted references to be moved
85//! around without tying up the whole store in borrows. Additionally, and
86//! crucially, this indirection allows us to update the *actual* GC pointers in
87//! the `RootSet` and support moving GCs (again, as mentioned above).
88//!
89//! ## Unrooted References
90//!
91//! We generally don't expose *unrooted* GC references in the Wasmtime API at
92//! this time -- and I expect it will be a very long time before we do, but in
93//! the limit we may want to let users define their own GC-managed types that
94//! participate in GC tracing and all that -- so we don't have to worry about
95//! failure to root an object causing use-after-free bugs or failing to update a
96//! GC root pointer after a moving GC as long as users stick to our safe rooting
97//! APIs. (The one exception is `ValRaw`, which does hold raw GC references. But
98//! with `ValRaw` all bets are off and safety is 100% up to the user.)
99//!
100//! We do, however, have to worry about these things internally. So first of
101//! all, try to avoid ever working with unrooted GC references if you
102//! can. However, if you really must, consider also using an `AutoAssertNoGc`
103//! across the block of code that is manipulating raw GC references.
104
105use crate::{
106    store::{AutoAssertNoGc, StoreId, StoreOpaque},
107    AsContext, AsContextMut, GcRef, Result, RootedGcRef,
108};
109use anyhow::anyhow;
110use std::{
111    fmt::Debug,
112    hash::Hash,
113    ops::{Deref, DerefMut},
114};
115use wasmtime_runtime::{GcRootsList, GcStore, VMGcRef};
116use wasmtime_slab::{Id as SlabId, Slab};
117
118mod sealed {
119    use super::*;
120
121    /// Sealed, `wasmtime`-internal trait for GC references.
122    ///
123    /// # Safety
124    ///
125    /// All types implementing this trait must:
126    ///
127    /// * Be a newtype of a `GcRootIndex`
128    ///
129    /// * Not implement `Copy` or `Clone`
130    ///
131    /// * Only have `&self` methods.
132    pub unsafe trait GcRefImpl: Sized {
133        /// Transmute a `&GcRootIndex` into an `&Self`.
134        fn transmute_ref(index: &GcRootIndex) -> &Self;
135    }
136
137    /// Sealed, `wasmtime`-internal trait for the common methods on rooted GC
138    /// references.
139    pub trait RootedGcRefImpl<T: GcRef> {
140        /// Get this rooted GC reference's raw `VMGcRef` out of the store's GC
141        /// root set.
142        ///
143        /// Returns `None` for objects that have since been unrooted (eg because
144        /// its associated `RootedScope` was dropped).
145        ///
146        /// Panics if this root is not associated with the given store.
147        fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef>;
148
149        /// Same as `get_gc_ref` but returns an error instead of `None` for
150        /// objects that have been unrooted.
151        fn try_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Result<&'a VMGcRef> {
152            self.get_gc_ref(store).ok_or_else(|| {
153                anyhow!("attempted to use a garbage-collected object that has been unrooted")
154            })
155        }
156
157        /// Get a clone of this rooted GC reference's raw `VMGcRef` out of the
158        /// store's GC root set.
159        ///
160        /// Returns `None` for objects that have since been unrooted (eg because
161        /// its associated `RootedScope` was dropped).
162        ///
163        /// Panics if this root is not associated with the given store.
164        fn clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Option<VMGcRef> {
165            let gc_ref = self.get_gc_ref(store)?.unchecked_copy();
166            Some(store.unwrap_gc_store_mut().clone_gc_ref(&gc_ref))
167        }
168
169        /// Same as `clone_gc_ref` but returns an error instead of `None` for
170        /// objects that have been unrooted.
171        fn try_clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Result<VMGcRef> {
172            let gc_ref = self.try_gc_ref(store)?.unchecked_copy();
173            Ok(store.gc_store_mut()?.clone_gc_ref(&gc_ref))
174        }
175    }
176}
177pub(crate) use sealed::*;
178
179/// The index of a GC root inside a particular store's GC root set.
180///
181/// Can be either a LIFO- or manually-rooted object, depending on the
182/// `PackedIndex`.
183///
184/// Every `T` such that `T: GcRef` must be a newtype over this `GcRootIndex`.
185#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
186// Just `pub` to avoid `warn(private_interfaces)` in public APIs, which we can't
187// `allow(...)` on our MSRV yet.
188#[doc(hidden)]
189pub struct GcRootIndex {
190    store_id: StoreId,
191    generation: u32,
192    index: PackedIndex,
193}
194
195impl GcRootIndex {
196    #[inline]
197    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
198        self.store_id == store.id()
199    }
200
201    /// Same as `RootedGcRefImpl::get_gc_ref` but doesn't check that the raw GC
202    /// ref is only used during the scope of an `AutoAssertNoGc`.
203    ///
204    /// It is up to callers to avoid triggering a GC while holding onto the
205    /// resulting raw `VMGcRef`. Failure to uphold this invariant is memory safe
206    /// but will lead to general incorrectness such as panics and wrong results.
207    pub(crate) fn unchecked_get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> {
208        assert!(
209            self.comes_from_same_store(store),
210            "object used with wrong store"
211        );
212        if let Some(index) = self.index.as_lifo() {
213            let entry = store.gc_roots().lifo_roots.get(index)?;
214            if entry.generation == self.generation {
215                Some(&entry.gc_ref)
216            } else {
217                None
218            }
219        } else if let Some(id) = self.index.as_manual() {
220            let gc_ref = store.gc_roots().manually_rooted.get(id);
221            debug_assert!(gc_ref.is_some());
222            gc_ref
223        } else {
224            unreachable!()
225        }
226    }
227
228    /// Same as `RootedGcRefImpl::get_gc_ref` but not associated with any
229    /// particular `T: GcRef`.
230    pub(crate) fn get_gc_ref<'a>(&self, store: &'a AutoAssertNoGc<'_>) -> Option<&'a VMGcRef> {
231        self.unchecked_get_gc_ref(store)
232    }
233
234    /// Same as `unchecked_get_gc_ref` but returns an error instead of `None` if
235    /// the GC reference has been unrooted.
236    ///
237    /// # Panics
238    ///
239    /// Panics if `self` is not associated with the given store.
240    pub(crate) fn unchecked_try_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Result<&'a VMGcRef> {
241        self.unchecked_get_gc_ref(store).ok_or_else(|| {
242            anyhow!("attempted to use a garbage-collected object that has been unrooted")
243        })
244    }
245
246    /// Same as `get_gc_ref` but returns an error instead of `None` if the GC
247    /// reference has been unrooted.
248    pub(crate) fn try_gc_ref<'a>(&self, store: &'a AutoAssertNoGc<'_>) -> Result<&'a VMGcRef> {
249        self.get_gc_ref(store).ok_or_else(|| {
250            anyhow!("attempted to use a garbage-collected object that has been unrooted")
251        })
252    }
253
254    /// Same as `RootedGcRefImpl::clone_gc_ref` but not associated with any
255    /// particular `T: GcRef`.
256    pub(crate) fn try_clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Result<VMGcRef> {
257        let gc_ref = self.try_gc_ref(store)?.unchecked_copy();
258        Ok(store.gc_store_mut()?.clone_gc_ref(&gc_ref))
259    }
260}
261
262/// This is a bit-packed version of
263///
264/// ```ignore
265/// enema {
266///     Lifo(usize),
267///     Manual(SlabId),
268/// }
269/// ```
270///
271/// where the high bit is the discriminant and the lower 31 bits are the
272/// payload.
273#[derive(Clone, Copy, PartialEq, Eq, Hash)]
274struct PackedIndex(u32);
275
276impl Debug for PackedIndex {
277    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278        if let Some(index) = self.as_lifo() {
279            f.debug_tuple("PackedIndex::Lifo").field(&index).finish()
280        } else if let Some(id) = self.as_manual() {
281            f.debug_tuple("PackedIndex::Manual").field(&id).finish()
282        } else {
283            unreachable!()
284        }
285    }
286}
287
288impl PackedIndex {
289    const DISCRIMINANT_MASK: u32 = 0b1 << 31;
290    const LIFO_DISCRIMINANT: u32 = 0b0 << 31;
291    const MANUAL_DISCRIMINANT: u32 = 0b1 << 31;
292    const PAYLOAD_MASK: u32 = !Self::DISCRIMINANT_MASK;
293
294    fn new_lifo(index: usize) -> PackedIndex {
295        let index32 = u32::try_from(index).unwrap();
296        assert_eq!(index32 & Self::DISCRIMINANT_MASK, 0);
297        let packed = PackedIndex(Self::LIFO_DISCRIMINANT | index32);
298        debug_assert!(packed.is_lifo());
299        debug_assert_eq!(packed.as_lifo(), Some(index));
300        debug_assert!(!packed.is_manual());
301        debug_assert!(packed.as_manual().is_none());
302        packed
303    }
304
305    fn new_manual(id: SlabId) -> PackedIndex {
306        let raw = id.into_raw();
307        assert_eq!(raw & Self::DISCRIMINANT_MASK, 0);
308        let packed = PackedIndex(Self::MANUAL_DISCRIMINANT | raw);
309        debug_assert!(packed.is_manual());
310        debug_assert_eq!(packed.as_manual(), Some(id));
311        debug_assert!(!packed.is_lifo());
312        debug_assert!(packed.as_lifo().is_none());
313        packed
314    }
315
316    fn discriminant(&self) -> u32 {
317        self.0 & Self::DISCRIMINANT_MASK
318    }
319
320    fn is_lifo(&self) -> bool {
321        self.discriminant() == Self::LIFO_DISCRIMINANT
322    }
323
324    fn is_manual(&self) -> bool {
325        self.discriminant() == Self::MANUAL_DISCRIMINANT
326    }
327
328    fn payload(&self) -> u32 {
329        self.0 & Self::PAYLOAD_MASK
330    }
331
332    fn as_lifo(&self) -> Option<usize> {
333        if self.is_lifo() {
334            Some(usize::try_from(self.payload()).unwrap())
335        } else {
336            None
337        }
338    }
339
340    fn as_manual(&self) -> Option<SlabId> {
341        if self.is_manual() {
342            Some(SlabId::from_raw(self.payload()))
343        } else {
344            None
345        }
346    }
347}
348
349/// The set of all embedder-API GC roots in a single store/heap.
350#[derive(Debug, Default)]
351pub(crate) struct RootSet {
352    /// GC roots with arbitrary lifetime that are manually rooted and unrooted,
353    /// for use with `ManuallyRooted<T>`.
354    manually_rooted: Slab<VMGcRef>,
355
356    /// Strictly LIFO-ordered GC roots, for use with `RootScope` and
357    /// `Rooted<T>`.
358    lifo_roots: Vec<LifoRoot>,
359
360    /// Generation counter for entries to prevent ABA bugs with `RootScope` and
361    /// `Rooted<T>`.
362    lifo_generation: u32,
363}
364
365#[derive(Debug)]
366struct LifoRoot {
367    generation: u32,
368    gc_ref: VMGcRef,
369}
370
371impl RootSet {
372    pub(crate) fn trace_roots(&mut self, gc_roots_list: &mut GcRootsList) {
373        log::trace!("Begin trace user LIFO roots");
374        for root in &mut self.lifo_roots {
375            unsafe {
376                gc_roots_list.add_root((&mut root.gc_ref).into());
377            }
378        }
379        log::trace!("End trace user LIFO roots");
380
381        log::trace!("Begin trace user manual roots");
382        for (_id, root) in self.manually_rooted.iter_mut() {
383            unsafe {
384                gc_roots_list.add_root(root.into());
385            }
386        }
387        log::trace!("End trace user manual roots");
388    }
389
390    /// Enter a LIFO rooting scope.
391    ///
392    /// Returns an integer that should be passed unmodified to `exit_lifo_scope`
393    /// when the scope is finished.
394    ///
395    /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order.
396    #[inline]
397    pub(crate) fn enter_lifo_scope(&self) -> usize {
398        let len = self.lifo_roots.len();
399        log::debug!("Entering GC root set LIFO scope: {len}");
400        len
401    }
402
403    /// Exit a LIFO rooting scope.
404    ///
405    /// The `scope` argument must be the result of the corresponding
406    /// `enter_lifo_scope` call.
407    ///
408    /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order.
409    #[inline]
410    pub(crate) fn exit_lifo_scope(&mut self, gc_store: &mut GcStore, scope: usize) {
411        log::debug!("Exiting GC root set LIFO scope: {scope}");
412        debug_assert!(self.lifo_roots.len() >= scope);
413
414        // If we actually have roots to unroot, call an out-of-line slow path.
415        if self.lifo_roots.len() > scope {
416            self.exit_lifo_scope_slow(gc_store, scope);
417        }
418    }
419
420    #[inline(never)]
421    #[cold]
422    fn exit_lifo_scope_slow(&mut self, gc_store: &mut GcStore, scope: usize) {
423        self.lifo_generation += 1;
424
425        // TODO: In the case where we have a tracing GC that doesn't need to
426        // drop barriers, this should really be:
427        //
428        //     self.lifo_roots.truncate(scope);
429
430        let mut lifo_roots = std::mem::take(&mut self.lifo_roots);
431        for root in lifo_roots.drain(scope..) {
432            gc_store.drop_gc_ref(root.gc_ref);
433        }
434        self.lifo_roots = lifo_roots;
435    }
436
437    pub(crate) fn with_lifo_scope<S, T>(store: &mut S, f: impl FnOnce(&mut S) -> T) -> T
438    where
439        S: DerefMut<Target = StoreOpaque>,
440    {
441        let scope = store.gc_roots().enter_lifo_scope();
442        let ret = f(store);
443        store.exit_gc_lifo_scope(scope);
444        ret
445    }
446
447    pub(crate) fn push_lifo_root(&mut self, store_id: StoreId, gc_ref: VMGcRef) -> GcRootIndex {
448        let generation = self.lifo_generation;
449        let index = self.lifo_roots.len();
450        let index = PackedIndex::new_lifo(index);
451        self.lifo_roots.push(LifoRoot { generation, gc_ref });
452        GcRootIndex {
453            store_id,
454            generation,
455            index,
456        }
457    }
458}
459
460/// A scoped, rooted reference to a garbage-collected `T`.
461///
462/// A `Rooted<T>` is a strong handle to a garbage-collected `T`, preventing its
463/// referent (and anything else transitively referenced) from being collected by
464/// the GC during the scope within which this `Rooted<T>` was created.
465///
466/// When the context exits this `Rooted<T>`'s scope, the underlying GC object is
467/// automatically unrooted and any further attempts to use access the underlying
468/// object will return errors or otherwise fail.
469///
470/// `Rooted<T>` dereferences to its underlying `T`, allowing you to call `T`'s
471/// methods.
472///
473/// # Example
474///
475/// ```
476/// # use wasmtime::*;
477/// # fn _foo() -> Result<()> {
478/// let mut store = Store::<()>::default();
479///
480/// // Allocating a GC object returns a `Rooted<T>`.
481/// let hello: Rooted<ExternRef> = ExternRef::new(&mut store, "hello")?;
482///
483/// // Because `Rooted<T>` derefs to `T`, we can call `T` methods on a
484/// // `Rooted<T>`. For example, we can call the `ExternRef::data` method when we
485/// // have a `Rooted<ExternRef>`.
486/// let data = hello
487///     .data(&store)?
488///     .downcast_ref::<&str>()
489///     .ok_or_else(|| Error::msg("not a str"))?;
490/// assert_eq!(*data, "hello");
491///
492/// // A `Rooted<T>` roots its underlying GC object for the duration of the
493/// // scope of the store/caller/context that was passed to the method that created
494/// // it. If we only want to keep a GC reference rooted and alive temporarily, we
495/// // can introduce new scopes with `RootScope`.
496/// {
497///     let mut scope = RootScope::new(&mut store);
498///
499///     // This `Rooted<T>` is automatically unrooted after `scope` is dropped,
500///     // allowing the collector to reclaim its GC object in the next GC.
501///     let scoped_ref = ExternRef::new(&mut scope, "goodbye");
502/// }
503///
504/// let module = Module::new(store.engine(), r#"
505///     (module
506///         (global (export "global") (mut externref) (ref.null extern))
507///         (table (export "table") 10 externref)
508///         (func (export "func") (param externref) (result externref)
509///             local.get 0
510///         )
511///     )
512/// "#)?;
513/// let instance = Instance::new(&mut store, &module, &[])?;
514///
515/// // GC references returned from calls into Wasm also return (optional, if the
516/// // Wasm type is nullable) `Rooted<T>`s.
517/// let result: Option<Rooted<_>> = instance
518///     .get_typed_func::<Option<Rooted<ExternRef>>, Option<Rooted<ExternRef>>>(&mut store, "func")?
519///     .call(&mut store, Some(hello))?;
520///
521/// // Similarly, getting a GC reference from a Wasm instance's exported global
522/// // or table yields a `Rooted<T>`.
523///
524/// let global = instance
525///     .get_global(&mut store, "global")
526///     .ok_or_else(|| Error::msg("missing `global` export"))?;
527/// let global_val = global.get(&mut store);
528/// let global_ref: Option<&Rooted<_>> = global_val
529///     .externref()
530///     .ok_or_else(|| Error::msg("not an externref"))?;
531///
532/// let table = instance.get_table(&mut store, "table").unwrap();
533/// let table_elem = table
534///     .get(&mut store, 3)
535///     .ok_or_else(|| Error::msg("table out of bounds"))?;
536/// let table_elem_ref: Option<&Rooted<_>> = table_elem
537///     .as_extern()
538///     .ok_or_else(|| Error::msg("not an externref"))?;
539/// # Ok(())
540/// # }
541/// ```
542///
543/// # Differences Between `Rooted<T>` and `ManuallyRooted<T>`
544///
545/// While `Rooted<T>` is automatically unrooted when its scope is exited, this
546/// means that `Rooted<T>` is only valid for strictly last-in-first-out (LIFO,
547/// aka stack order) lifetimes. This is in contrast to
548/// [`ManuallyRooted<T>`][crate::ManuallyRooted], which supports rooting GC
549/// objects for arbitrary lifetimes, but requires manual unrooting.
550///
551/// | Type                                         | Supported Lifetimes         | Unrooting |
552/// |----------------------------------------------|-----------------------------|-----------|
553/// | [`Rooted<T>`][crate::Rooted]                 | Strictly LIFO / stack order | Automatic |
554/// | [`ManuallyRooted<T>`][crate::ManuallyRooted] | Arbitrary                   | Manual    |
555///
556/// `Rooted<T>` should suffice for most use cases, and provides better
557/// ergonomics, but `ManuallyRooted<T>` exists as a fully-general escape hatch.
558///
559/// # Scopes
560///
561/// Wasmtime automatically creates two kinds of scopes:
562///
563/// 1. A [`Store`][crate::Store] is the outermost rooting scope. Creating a
564///    `Root<T>` directly inside a `Store` permanently roots the underlying
565///    object, similar to dropping a
566///    [`ManuallyRooted<T>`][crate::ManuallyRooted] without unrooting it.
567///
568/// 2. A [`Caller`][crate::Caller] provides a rooting scope for the duration of
569///    a call from Wasm into a host function. Any objects rooted in a `Caller`
570///    will be unrooted after the host function returns. Note that there can be
571///    nested `Caller` scopes in the case where Wasm calls a host function,
572///    creating the first `Caller` and its rooting scope , and then the host
573///    function calls a Wasm function which then calls another host function,
574///    creating a second `Caller` and a second rooting scope. This nesting can
575///    be arbitrarily deep.
576///
577/// Additionally, if you would like to define finer-grained rooting scopes,
578/// Wasmtime provides the [`RootScope`][crate::RootScope] type.
579///
580/// Scopes are always nested in a last-in-first-out (LIFO) order. An outer scope
581/// is never exited (and the `Rooted<T>`s defined within it are never
582/// automatically unrooted) while an inner scope is still active. All inner
583/// scopes are exited before their outer scopes.
584///
585/// The following diagram illustrates various rooting scopes over time, how they
586/// nest, and when their `Rooted<T>`s are automatically unrooted:
587///
588/// ```text
589/// ----- new Store
590///   |
591///   |
592///   | let a: Rooted<T> = ...;
593///   |
594///   |
595///   | ----- call into Wasm
596///   |   |
597///   |   |
598///   |   | ----- Wasm calls host function F
599///   |   |   |
600///   |   |   |
601///   |   |   | let b: Rooted<T> = ...;
602///   |   |   |
603///   |   |   |
604///   |   |   | ----- F calls into Wasm
605///   |   |   |   |
606///   |   |   |   |
607///   |   |   |   | ----- Wasm call host function G
608///   |   |   |   |   |
609///   |   |   |   |   |
610///   |   |   |   |   | let c: Rooted<T> = ...;
611///   |   |   |   |   |
612///   |   |   |   |   |
613///   |   |   |   | ----- return to Wasm from host function G (unroots `c`)
614///   |   |   |   |
615///   |   |   |   |
616///   |   |   | ----- Wasm returns to F
617///   |   |   |
618///   |   |   |
619///   |   | ----- return from host function F (unroots `b`)
620///   |   |
621///   |   |
622///   | ----- return from Wasm
623///   |
624///   |
625///   | ----- let scope1 = RootScope::new(...);
626///   |   |
627///   |   |
628///   |   | let d: Rooted<T> = ...;
629///   |   |
630///   |   |
631///   |   | ----- let scope2 = RootScope::new(...);
632///   |   |   |
633///   |   |   |
634///   |   |   | let e: Rooted<T> = ...;
635///   |   |   |
636///   |   |   |
637///   |   | ----- drop `scope2` (unroots `e`)
638///   |   |
639///   |   |
640///   | ----- drop `scope1` (unroots `d`)
641///   |
642///   |
643/// ----- drop Store (unroots `a`)
644/// ```
645///
646/// A `Rooted<T>` can be used successfully as long as it is still rooted so, in
647/// the above diagram, `d` is valid inside `scope2` because `scope2` is wholly
648/// contained within the scope `d` was rooted within (`scope1`).
649///
650/// See also the documentation for [`RootScope`][crate::RootScope].
651#[repr(transparent)]
652pub struct Rooted<T: GcRef> {
653    inner: GcRootIndex,
654    _phantom: std::marker::PhantomData<T>,
655}
656
657impl<T: GcRef> Clone for Rooted<T> {
658    fn clone(&self) -> Self {
659        Rooted {
660            inner: self.inner,
661            _phantom: std::marker::PhantomData,
662        }
663    }
664}
665
666impl<T: GcRef> Copy for Rooted<T> {}
667
668impl<T: GcRef> Debug for Rooted<T> {
669    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
670        let name = format!("Rooted<{}>", std::any::type_name::<T>());
671        f.debug_struct(&name).field("inner", &self.inner).finish()
672    }
673}
674
675impl<T: GcRef> RootedGcRefImpl<T> for Rooted<T> {
676    fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> {
677        assert!(
678            self.comes_from_same_store(store),
679            "object used with wrong store"
680        );
681        let index = self.inner.index.as_lifo().unwrap();
682        let entry = store.gc_roots().lifo_roots.get(index)?;
683        if entry.generation == self.inner.generation {
684            Some(&entry.gc_ref)
685        } else {
686            None
687        }
688    }
689}
690
691impl<T: GcRef> Deref for Rooted<T> {
692    type Target = T;
693
694    fn deref(&self) -> &Self::Target {
695        T::transmute_ref(&self.inner)
696    }
697}
698
699impl<T: GcRef> Rooted<T> {
700    /// Push the given `VMGcRef` onto our LIFO root set.
701    ///
702    /// `gc_ref` should belong to `store`'s heap; failure to uphold this is
703    /// memory safe but will result in general failures down the line such as
704    /// panics or incorrect results.
705    ///
706    /// `gc_ref` should be a GC reference pointing to an instance of the GC type
707    /// that `T` represents. Failure to uphold this invariant is memory safe but
708    /// will result in general incorrectness such as panics and wrong results.
709    pub(crate) fn new(store: &mut AutoAssertNoGc<'_>, gc_ref: VMGcRef) -> Rooted<T> {
710        let id = store.id();
711        let roots = store.gc_roots_mut();
712        let inner = roots.push_lifo_root(id, gc_ref);
713        Rooted {
714            inner,
715            _phantom: std::marker::PhantomData,
716        }
717    }
718
719    #[inline]
720    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
721        debug_assert!(self.inner.index.is_lifo());
722        self.inner.comes_from_same_store(store)
723    }
724
725    /// Create a [`ManuallyRooted<T>`][crate::ManuallyRooted] holding onto the
726    /// same GC object as `self`.
727    ///
728    /// Returns `None` if `self` is used outside of its scope and has therefore
729    /// been unrooted.
730    ///
731    /// This does not unroot `self`, and `self` remains valid until its
732    /// associated scope is exited.
733    ///
734    /// # Panics
735    ///
736    /// Panics if this object is not associate with the given store.
737    ///
738    /// # Example
739    ///
740    /// ```
741    /// # use wasmtime::*;
742    /// # fn _foo() -> Result<()> {
743    /// let mut store = Store::<()>::default();
744    ///
745    /// let y: ManuallyRooted<_> = {
746    ///     // Create a nested rooting scope.
747    ///     let mut scope = RootScope::new(&mut store);
748    ///
749    ///     // `x` is only rooted within this nested scope.
750    ///     let x: Rooted<_> = ExternRef::new(&mut scope, "hello!")?;
751    ///
752    ///     // Extend `x`'s rooting past its scope's lifetime by converting it
753    ///     // to a `ManuallyRooted`.
754    ///     x.to_manually_rooted(&mut scope)?
755    /// };
756    ///
757    /// // Now we can still access the reference outside the scope it was
758    /// // originally defined within.
759    /// let data = y.data(&store)?;
760    /// let data = data.downcast_ref::<&str>().unwrap();
761    /// assert_eq!(*data, "hello!");
762    ///
763    /// // But we have to manually unroot `y`.
764    /// y.unroot(&mut store);
765    /// # Ok(())
766    /// # }
767    /// ```
768    pub fn to_manually_rooted(&self, mut store: impl AsContextMut) -> Result<ManuallyRooted<T>> {
769        self._to_manually_rooted(store.as_context_mut().0)
770    }
771
772    pub(crate) fn _to_manually_rooted(&self, store: &mut StoreOpaque) -> Result<ManuallyRooted<T>> {
773        let mut store = AutoAssertNoGc::new(store);
774        let gc_ref = self.try_clone_gc_ref(&mut store)?;
775        Ok(ManuallyRooted::new(&mut store, gc_ref))
776    }
777
778    /// Are these two `Rooted<T>`s the same GC root?
779    ///
780    /// Note that this function can return `false` even when `a` and `b` are
781    /// rooting the same underlying GC object, but the object was rooted
782    /// multiple times (for example in different scopes). Use
783    /// [`Rooted::ref_eq`][crate::Rooted::ref_eq] to test whether these are
784    /// references to the same underlying GC object or not.
785    ///
786    /// # Example
787    ///
788    /// ```
789    /// # use wasmtime::*;
790    /// # fn foo() -> Result<()> {
791    /// let mut store = Store::<()>::default();
792    ///
793    /// let a = ExternRef::new(&mut store, "hello")?;
794    /// let b = a;
795    ///
796    /// // `a` and `b` are the same GC root.
797    /// assert!(Rooted::rooted_eq(a, b));
798    ///
799    /// {
800    ///     let mut scope = RootScope::new(&mut store);
801    ///
802    ///     // `c` is a different GC root, in a different scope, even though it
803    ///     // is rooting the same object.
804    ///     let c = a.to_manually_rooted(&mut scope)?.into_rooted(&mut scope);
805    ///     assert!(!Rooted::rooted_eq(a, c));
806    /// }
807    ///
808    /// let x = ExternRef::new(&mut store, "goodbye")?;
809    ///
810    /// // `a` and `x` are different GC roots, rooting different objects.
811    /// assert!(!Rooted::rooted_eq(a, x));
812    /// # Ok(())
813    /// # }
814    /// ```
815    pub fn rooted_eq(a: Self, b: Self) -> bool {
816        a.inner == b.inner
817    }
818
819    /// Are these two GC roots referencing the same underlying GC object?
820    ///
821    /// This function will return `true` even when `a` and `b` are different GC
822    /// roots (for example because they were rooted in different scopes) if they
823    /// are rooting the same underlying GC object. To only test whether they are
824    /// the same GC root, and not whether they are rooting the same GC object,
825    /// use [`Rooted::rooted_eq`][crate::Rooted::rooted_eq].
826    ///
827    /// Returns an error if either `a` or `b` has been unrooted, for example
828    /// because the scope it was rooted within has been exited.
829    ///
830    /// Because this method takes any `impl RootedGcRef<T>` arguments, it can be
831    /// used to compare, for example, a `Rooted<T>` and a `ManuallyRooted<T>`.
832    ///
833    /// # Panics
834    ///
835    /// Panics if either `a` or `b` is not associated with the given `store`.
836    ///
837    /// # Example
838    ///
839    /// ```
840    /// # use wasmtime::*;
841    /// # fn foo() -> Result<()> {
842    /// let mut store = Store::<()>::default();
843    ///
844    /// let a = ExternRef::new(&mut store, "hello")?;
845    /// let b = a;
846    ///
847    /// // `a` and `b` are rooting the same object.
848    /// assert!(Rooted::ref_eq(&store, &a, &b)?);
849    ///
850    /// {
851    ///     let mut scope = RootScope::new(&mut store);
852    ///
853    ///     // `c` is a different GC root, in a different scope, but still
854    ///     // rooting the same object.
855    ///     let c = a.to_manually_rooted(&mut scope)?.into_rooted(&mut scope);
856    ///     assert!(!Rooted::ref_eq(&scope, &a, &c)?);
857    /// }
858    ///
859    /// let x = ExternRef::new(&mut store, "goodbye")?;
860    ///
861    /// // `a` and `x` are rooting different objects.
862    /// assert!(!Rooted::ref_eq(&store, &a, &x)?);
863    ///
864    /// // You can also compare `Rooted<T>`s and `ManuallyRooted<T>`s with this
865    /// // function.
866    /// let d = a.to_manually_rooted(&mut store)?;
867    /// assert!(Rooted::ref_eq(&store, &a, &d)?);
868    ///
869    /// d.unroot(&mut store);
870    /// # Ok(())
871    /// # }
872    /// ```
873    pub fn ref_eq(
874        store: impl AsContext,
875        a: &impl RootedGcRef<T>,
876        b: &impl RootedGcRef<T>,
877    ) -> Result<bool> {
878        let store = store.as_context().0;
879        let a = a.try_gc_ref(store)?;
880        let b = b.try_gc_ref(store)?;
881        Ok(a == b)
882    }
883
884    /// Hash this root.
885    ///
886    /// Note that, similar to `Rooted::rooted_eq`, this only operates on the
887    /// root and *not* the underlying GC reference. That means that two
888    /// different rootings of the same object will hash to different values
889    /// (modulo hash collisions). If this is undesirable, use the
890    /// [`ref_hash`][crate::Rooted::ref_hash] method instead.
891    pub fn rooted_hash<H>(&self, state: &mut H)
892    where
893        H: std::hash::Hasher,
894    {
895        self.inner.hash(state);
896    }
897
898    /// Hash the underlying rooted object reference.
899    ///
900    /// Note that, similar to `Rooted::ref_eq`, and operates on the underlying
901    /// rooted GC object reference, not the root. That means that two
902    /// *different* rootings of the same object will hash to the *same*
903    /// value. If this is undesirable, use the
904    /// [`rooted_hash`][crate::Rooted::rooted_hash] method instead.
905    pub fn ref_hash<H>(&self, store: impl AsContext, state: &mut H) -> Result<()>
906    where
907        H: std::hash::Hasher,
908    {
909        let gc_ref = self.try_gc_ref(store.as_context().0)?;
910        gc_ref.hash(state);
911        Ok(())
912    }
913}
914
915/// Nested rooting scopes.
916///
917/// `RootScope` allows the creation or nested rooting scopes for use with
918/// [`Rooted<T>`][crate::Rooted]. This allows for fine-grained control over how
919/// long a set of [`Rooted<T>`][crate::Rooted]s are strongly held alive, giving
920/// gives you the tools necessary to avoid holding onto GC objects longer than
921/// necessary. `Rooted<T>`s created within a `RootScope` are automatically
922/// unrooted when the `RootScope` is dropped. For more details on
923/// [`Rooted<T>`][crate::Rooted] lifetimes and their interaction with rooting
924/// scopes, see [`Rooted<T>`][crate::Rooted]'s documentation.
925///
926/// A `RootScope<C>` wraps a `C: AsContextMut` (that is, anything that
927/// represents exclusive access to a [`Store`][crate::Store]) and in turn
928/// implements [`AsContext`][crate::AsContext] and
929/// [`AsContextMut`][crate::AsContextMut] in terms of its underlying
930/// `C`. Therefore, `RootScope<C>` can be used anywhere you would use the
931/// underlying `C`, for example in the [`Global::get`][crate::Global::get]
932/// method. Any `Rooted<T>`s created by a method that a `RootScope<C>` was
933/// passed as context to are tied to the `RootScope<C>`'s scope and
934/// automatically unrooted when the scope is dropped.
935///
936/// # Example
937///
938/// ```
939/// # use wasmtime::*;
940/// # fn _foo() -> Result<()> {
941/// let mut store = Store::<()>::default();
942///
943/// let a: Rooted<_>;
944/// let b: Rooted<_>;
945/// let c: Rooted<_>;
946///
947/// // Root `a` in the store's scope. It will be rooted for the duration of the
948/// // store's lifetime.
949/// a = ExternRef::new(&mut store, 42)?;
950///
951/// // `a` is rooted, so we can access its data successfully.
952/// assert!(a.data(&store).is_ok());
953///
954/// {
955///     let mut scope1 = RootScope::new(&mut store);
956///
957///     // Root `b` in `scope1`.
958///     b = ExternRef::new(&mut scope1, 36)?;
959///
960///     // Both `a` and `b` are rooted.
961///     assert!(a.data(&scope1).is_ok());
962///     assert!(b.data(&scope1).is_ok());
963///
964///     {
965///         let mut scope2 = RootScope::new(&mut scope1);
966///
967///         // Root `c` in `scope2`.
968///         c = ExternRef::new(&mut scope2, 36)?;
969///
970///         // All of `a`, `b`, and `c` are rooted.
971///         assert!(a.data(&scope2).is_ok());
972///         assert!(b.data(&scope2).is_ok());
973///         assert!(c.data(&scope2).is_ok());
974///
975///         // Drop `scope2`.
976///     }
977///
978///     // Now `a` and `b` are still rooted, but `c` was unrooted when we dropped
979///     // `scope2`.
980///     assert!(a.data(&scope1).is_ok());
981///     assert!(b.data(&scope1).is_ok());
982///     assert!(c.data(&scope1).is_err());
983///
984///     // Drop `scope1`.
985/// }
986///
987/// // And now only `a` is still rooted. Both `b` and `c` were unrooted when we
988/// // dropped their respective rooting scopes.
989/// assert!(a.data(&store).is_ok());
990/// assert!(b.data(&store).is_err());
991/// assert!(c.data(&store).is_err());
992/// # Ok(())
993/// # }
994/// ```
995pub struct RootScope<C>
996where
997    C: AsContextMut,
998{
999    store: C,
1000    scope: usize,
1001}
1002
1003impl<C> Drop for RootScope<C>
1004where
1005    C: AsContextMut,
1006{
1007    fn drop(&mut self) {
1008        self.store.as_context_mut().0.exit_gc_lifo_scope(self.scope);
1009    }
1010}
1011
1012impl<C> RootScope<C>
1013where
1014    C: AsContextMut,
1015{
1016    // NB: we MUST NOT expose a method like
1017    //
1018    //     pub fn store(&mut self) -> &mut Store { ... }
1019    //
1020    // because callers could do treacherous things like
1021    //
1022    //     let scope1 = RootScope::new(&mut store1);
1023    //     let scope2 = RootScope::new(&mut store2);
1024    //     std::mem::swap(scope1.store(), scope2.store());
1025    //
1026    // and then we would start truncate the store's GC root set's LIFO roots to
1027    // the wrong lengths.
1028    //
1029    // Instead, we just implement `AsContext[Mut]` for `RootScope`.
1030
1031    /// Construct a new scope for rooting GC objects.
1032    ///
1033    /// # Example
1034    ///
1035    /// ```
1036    /// # use wasmtime::*;
1037    /// let mut store = Store::<()>::default();
1038    ///
1039    /// {
1040    ///     let mut scope = RootScope::new(&mut store);
1041    ///
1042    ///     // Temporarily root GC objects in this nested rooting scope...
1043    /// }
1044    /// ```
1045    pub fn new(store: C) -> Self {
1046        let scope = store.as_context().0.gc_roots().enter_lifo_scope();
1047        RootScope { store, scope }
1048    }
1049
1050    fn gc_roots(&mut self) -> &mut RootSet {
1051        self.store.as_context_mut().0.gc_roots_mut()
1052    }
1053
1054    fn lifo_roots(&mut self) -> &mut Vec<LifoRoot> {
1055        &mut self.gc_roots().lifo_roots
1056    }
1057
1058    /// Reserve enough capacity for `additional` GC roots in this scope.
1059    ///
1060    /// # Example
1061    ///
1062    /// ```
1063    /// # use wasmtime::*;
1064    /// let mut store = Store::<()>::default();
1065    ///
1066    /// {
1067    ///     let mut scope = RootScope::new(&mut store);
1068    ///
1069    ///     // Ensure we have enough storage pre-allocated to root five GC
1070    ///     // references inside this scope without any underlying reallocation.
1071    ///     scope.reserve(5);
1072    ///
1073    ///     // ...
1074    /// }
1075    /// ```
1076    pub fn reserve(&mut self, additional: usize) {
1077        self.lifo_roots().reserve(additional);
1078    }
1079}
1080
1081impl<T> AsContext for RootScope<T>
1082where
1083    T: AsContextMut,
1084{
1085    type Data = T::Data;
1086
1087    fn as_context(&self) -> crate::StoreContext<'_, Self::Data> {
1088        self.store.as_context()
1089    }
1090}
1091
1092impl<T> AsContextMut for RootScope<T>
1093where
1094    T: AsContextMut,
1095{
1096    fn as_context_mut(&mut self) -> crate::StoreContextMut<'_, Self::Data> {
1097        self.store.as_context_mut()
1098    }
1099}
1100
1101/// A rooted reference to a garbage-collected `T` with arbitrary lifetime.
1102///
1103/// A `ManuallyRooted<T>` is a strong handle to a garbage-collected `T`,
1104/// preventing its referent (and anything else transitively referenced) from
1105/// being collected by the GC until [`unroot`][crate::ManuallyRooted::unroot] is
1106/// explicitly called.
1107///
1108/// The primary way to create a `ManuallyRooted<T>` is to promote a temporary
1109/// `Rooted<T>` into a `ManuallyRooted<T>` via its
1110/// [`to_manually_rooted`][crate::Rooted::to_manually_rooted] method.
1111///
1112/// `ManuallyRooted<T>` dereferences to its underlying `T`, allowing you to call
1113/// `T`'s methods.
1114///
1115/// # Example
1116///
1117/// ```
1118/// # use wasmtime::*;
1119/// # fn _foo() -> Result<()> {
1120/// let mut store = Store::<Option<ManuallyRooted<ExternRef>>>::default();
1121///
1122/// // Create our `ManuallyRooted` in a nested scope to avoid rooting it for
1123/// // the duration of the store's lifetime.
1124/// let x = {
1125///     let mut scope = RootScope::new(&mut store);
1126///     let x = ExternRef::new(&mut scope, 1234)?;
1127///     x.to_manually_rooted(&mut scope)?
1128/// };
1129///
1130/// // Place `x` into our store.
1131/// *store.data_mut() = Some(x);
1132///
1133/// // Do a bunch stuff that may or may not access, replace, or take `x`...
1134///
1135/// // At any time, in any arbitrary scope, we can remove `x` from the store
1136/// // and unroot it:
1137/// if let Some(x) = store.data_mut().take() {
1138///     x.unroot(&mut store);
1139/// }
1140/// # Ok(())
1141/// # }
1142/// ```
1143///
1144/// # Differences Between `ManuallyRooted<T>` and `Rooted<T>`
1145///
1146/// While `ManuallyRooted<T>` can have arbitrary lifetimes, it requires manual
1147/// unrooting. This is in contrast to [`Rooted<T>`][crate::Rooted] which is
1148/// restricted to strictly last-in-first-out (LIFO, aka stack order) lifetimes,
1149/// but comes with automatic unrooting.
1150///
1151/// | Type                                         | Supported Lifetimes         | Unrooting |
1152/// |----------------------------------------------|-----------------------------|-----------|
1153/// | [`Rooted<T>`][crate::Rooted]                 | Strictly LIFO / stack order | Automatic |
1154/// | [`ManuallyRooted<T>`][crate::ManuallyRooted] | Arbitrary                   | Manual    |
1155///
1156/// `Rooted<T>` should suffice for most use cases, and provides better
1157/// ergonomics, but `ManuallyRooted<T>` exists as a fully-general escape hatch.
1158///
1159/// # Manual Unrooting
1160///
1161/// Failure to explicitly call [`unroot`][crate::ManuallyRooted::unroot] (or
1162/// another method that consumes `self` and unroots the reference, such as
1163/// [`into_rooted`][crate::ManuallyRooted::into_rooted]) will leak the
1164/// underlying GC object, preventing it from being garbage collected until its
1165/// owning [`Store`][crate::Store] is dropped. That means all of the following
1166/// will result in permanently rooting the underlying GC object:
1167///
1168/// * Implicitly dropping a `ManuallyRooted<T>`:
1169///
1170///   ```no_run
1171///   # use wasmtime::*;
1172///   # let get_manually_rooted = || -> ManuallyRooted<ExternRef> { todo!() };
1173///   {
1174///       let perma_root: ManuallyRooted<_> = get_manually_rooted();
1175///
1176///       // `perma_root` is implicitly dropped at the end of its scope,
1177///       // permanently rooting/leaking its referent.
1178///   }
1179///   ```
1180///
1181/// * Explicitly dropping a `ManuallyRooted<T>`: `drop(my_manually_rooted)`.
1182///
1183/// * Forgetting a `ManuallyRooted<T>`: `std::mem::forget(my_manually_rooted)`.
1184///
1185/// * Inserting a `ManuallyRooted<T>` into a `std::sync::Arc` or `std::rc::Rc`
1186///   cycle.
1187///
1188/// * Etc...
1189///
1190/// Wasmtime does *not* assert that a `ManuallyRooted<T>` is unrooted on `Drop`,
1191/// or otherwise raise a panic, log a warning, or etc... on failure to manually
1192/// unroot. Sometimes leaking is intentional and desirable, particularly when
1193/// dealing with short-lived [`Store`][crate::Store]s where unrooting would just
1194/// be busy work since the whole store is about to be dropped.
1195pub struct ManuallyRooted<T>
1196where
1197    T: GcRef,
1198{
1199    inner: GcRootIndex,
1200    _phantom: std::marker::PhantomData<T>,
1201}
1202
1203impl<T: GcRef> Debug for ManuallyRooted<T> {
1204    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1205        let name = format!("ManuallyRooted<{}>", std::any::type_name::<T>());
1206        f.debug_struct(&name).field("inner", &self.inner).finish()
1207    }
1208}
1209
1210impl<T: GcRef> Deref for ManuallyRooted<T> {
1211    type Target = T;
1212
1213    fn deref(&self) -> &Self::Target {
1214        T::transmute_ref(&self.inner)
1215    }
1216}
1217
1218impl<T> ManuallyRooted<T>
1219where
1220    T: GcRef,
1221{
1222    /// Construct a new manually-rooted GC root.
1223    ///
1224    /// `gc_ref` should belong to `store`'s heap; failure to uphold this is
1225    /// memory safe but will result in general failures down the line such as
1226    /// panics or incorrect results.
1227    ///
1228    /// `gc_ref` should be a GC reference pointing to an instance of the GC type
1229    /// that `T` represents. Failure to uphold this invariant is memory safe but
1230    /// will result in general incorrectness such as panics and wrong results.
1231    pub(crate) fn new(store: &mut AutoAssertNoGc<'_>, gc_ref: VMGcRef) -> Self {
1232        let id = store.gc_roots_mut().manually_rooted.alloc(gc_ref);
1233        ManuallyRooted {
1234            inner: GcRootIndex {
1235                store_id: store.id(),
1236                generation: 0,
1237                index: PackedIndex::new_manual(id),
1238            },
1239            _phantom: std::marker::PhantomData,
1240        }
1241    }
1242
1243    #[inline]
1244    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1245        debug_assert!(self.inner.index.is_manual());
1246        self.inner.comes_from_same_store(store)
1247    }
1248
1249    /// Clone this `ManuallyRooted`.
1250    ///
1251    /// Does not consume or unroot `self`: both `self` and the new
1252    /// `ManuallyRooted` return value will need to be manually unrooted.
1253    ///
1254    /// # Panics
1255    ///
1256    /// Panics if `self` is not associated with the given `store`.
1257    ///
1258    /// # Example
1259    ///
1260    /// ```
1261    /// # use wasmtime::*;
1262    /// # fn _foo() -> Result<()> {
1263    /// let mut store = Store::<Vec<ManuallyRooted<ExternRef>>>::default();
1264    ///
1265    /// // Create our `ManuallyRooted` in a nested scope to avoid rooting it for
1266    /// // the duration of the store's lifetime.
1267    /// let x = {
1268    ///     let mut scope = RootScope::new(&mut store);
1269    ///     let x = ExternRef::new(&mut scope, 1234)?;
1270    ///     x.to_manually_rooted(&mut scope)?
1271    /// };
1272    ///
1273    /// // Push five clones of `x` into our store.
1274    /// for _ in 0..5 {
1275    ///     let x_clone = x.clone(&mut store);
1276    ///     store.data_mut().push(x_clone);
1277    /// }
1278    /// # Ok(())
1279    /// # }
1280    /// ```
1281    pub fn clone(&self, mut store: impl AsContextMut) -> Self {
1282        self._clone(store.as_context_mut().0)
1283    }
1284
1285    pub(crate) fn _clone(&self, store: &mut StoreOpaque) -> Self {
1286        let mut store = AutoAssertNoGc::new(store);
1287        let gc_ref = self
1288            .clone_gc_ref(&mut store)
1289            .expect("ManuallyRooted always has a gc ref");
1290        Self::new(&mut store, gc_ref)
1291    }
1292
1293    /// Unroot this GC object.
1294    ///
1295    /// Failure to call this method will result in the GC object, and anything
1296    /// it transitively references, being kept alive (aka "leaking") for the
1297    /// entirety of the store's lifetime.
1298    ///
1299    /// See the type-level docs for example usage.
1300    pub fn unroot(self, mut store: impl AsContextMut) {
1301        self._unroot(store.as_context_mut().0)
1302    }
1303
1304    pub(crate) fn _unroot(self, store: &mut StoreOpaque) {
1305        assert!(
1306            self.comes_from_same_store(store),
1307            "object used with wrong store"
1308        );
1309
1310        let mut store = AutoAssertNoGc::new(store);
1311        let id = self.inner.index.as_manual().unwrap();
1312        let roots = store.gc_roots_mut();
1313        let gc_ref = roots.manually_rooted.dealloc(id);
1314        store.unwrap_gc_store_mut().drop_gc_ref(gc_ref);
1315    }
1316
1317    /// Clone this `ManuallyRooted<T>` into a `Rooted<T>`.
1318    ///
1319    /// This operation does not consume or unroot this `ManuallyRooted<T>`.
1320    ///
1321    /// The underlying GC object is re-rooted in the given context's scope. The
1322    /// resulting `Rooted<T>` is only valid during the given context's
1323    /// scope. See the [`Rooted<T>`][crate::Rooted] documentation for more
1324    /// details on rooting scopes.
1325    ///
1326    /// This operation does not consume or unroot this `ManuallyRooted<T>`.
1327    ///
1328    /// # Panics
1329    ///
1330    /// Panics if this object is not associated with the given context's store.
1331    ///
1332    /// # Example
1333    ///
1334    /// ```
1335    /// # use wasmtime::*;
1336    /// # fn _foo() -> Result<()> {
1337    /// let mut store = Store::<()>::default();
1338    ///
1339    /// let root1: Rooted<_>;
1340    ///
1341    /// let manual = {
1342    ///     let mut scope = RootScope::new(&mut store);
1343    ///     root1 = ExternRef::new(&mut scope, 1234)?;
1344    ///     root1.to_manually_rooted(&mut scope)?
1345    /// };
1346    ///
1347    /// // `root1` is no longer accessible because it was unrooted when `scope`
1348    /// // was dropped.
1349    /// assert!(root1.data(&store).is_err());
1350    ///
1351    /// // But we can re-root `manual` into this scope.
1352    /// let root2 = manual.to_rooted(&mut store);
1353    /// assert!(root2.data(&store).is_ok());
1354    ///
1355    /// // And we also still have access to `manual` and we still have to
1356    /// // manually unroot it.
1357    /// assert!(manual.data(&store).is_ok());
1358    /// manual.unroot(&mut store);
1359    /// # Ok(())
1360    /// # }
1361    /// ```
1362    pub fn to_rooted(&self, mut context: impl AsContextMut) -> Rooted<T> {
1363        self._to_rooted(context.as_context_mut().0)
1364    }
1365
1366    pub(crate) fn _to_rooted(&self, store: &mut StoreOpaque) -> Rooted<T> {
1367        assert!(
1368            self.comes_from_same_store(store),
1369            "object used with wrong store"
1370        );
1371        let mut store = AutoAssertNoGc::new(store);
1372        let gc_ref = self.clone_gc_ref(&mut store).unwrap();
1373        Rooted::new(&mut store, gc_ref)
1374    }
1375
1376    /// Convert this `ManuallyRooted<T>` into a `Rooted<T>`.
1377    ///
1378    /// The underlying GC object is re-rooted in the given context's scope. The
1379    /// resulting `Rooted<T>` is only valid during the given context's
1380    /// scope. See the [`Rooted<T>`][crate::Rooted] documentation for more
1381    /// details on rooting scopes.
1382    ///
1383    /// This operation consumes and unroots this `ManuallyRooted<T>`.
1384    ///
1385    /// # Panics
1386    ///
1387    /// Panics if this object is not associate with the given context's store.
1388    ///
1389    /// # Example
1390    ///
1391    /// ```
1392    /// # use wasmtime::*;
1393    /// # fn _foo() -> Result<()> {
1394    /// let mut store = Store::<()>::default();
1395    ///
1396    /// let root1: Rooted<_>;
1397    ///
1398    /// let manual = {
1399    ///     let mut scope = RootScope::new(&mut store);
1400    ///     root1 = ExternRef::new(&mut scope, 1234)?;
1401    ///     root1.to_manually_rooted(&mut scope)?
1402    /// };
1403    ///
1404    /// // `root1` is no longer accessible because it was unrooted when `scope`
1405    /// // was dropped.
1406    /// assert!(root1.data(&store).is_err());
1407    ///
1408    /// // But we can re-root `manual` into this scope.
1409    /// let root2 = manual.into_rooted(&mut store);
1410    /// assert!(root2.data(&store).is_ok());
1411    ///
1412    /// // `manual` was consumed by the `into_rooted` call, and we no longer
1413    /// // have access to it, nor need to manually unroot it.
1414    /// # Ok(())
1415    /// # }
1416    /// ```
1417    pub fn into_rooted(self, mut context: impl AsContextMut) -> Rooted<T> {
1418        self._into_rooted(context.as_context_mut().0)
1419    }
1420
1421    pub(crate) fn _into_rooted(self, store: &mut StoreOpaque) -> Rooted<T> {
1422        assert!(
1423            self.comes_from_same_store(store),
1424            "object used with wrong store"
1425        );
1426        let rooted = self._to_rooted(store);
1427        self._unroot(store);
1428        rooted
1429    }
1430
1431    /// Are these two GC roots referencing the same underlying GC object?
1432    ///
1433    /// This function will return `true` even when `a` and `b` are different GC
1434    /// roots (for example because they were rooted in different scopes) if they
1435    /// are rooting the same underlying GC object.
1436    ///
1437    /// Because this method takes any `impl RootedGcRef<T>` arguments, it can be
1438    /// used to compare, for example, a `Rooted<T>` and a `ManuallyRooted<T>`.
1439    ///
1440    /// # Panics
1441    ///
1442    /// Panics if either `a` or `b` is not associated with the given `store`.
1443    ///
1444    /// # Example
1445    ///
1446    /// ```
1447    /// # use wasmtime::*;
1448    /// # fn foo() -> Result<()> {
1449    /// let mut store = Store::<()>::default();
1450    ///
1451    /// let a = ExternRef::new_manually_rooted(&mut store, "hello")?;
1452    /// let b = a.clone(&mut store);
1453    ///
1454    /// // `a` and `b` are rooting the same object.
1455    /// assert!(ManuallyRooted::ref_eq(&store, &a, &b)?);
1456    ///
1457    /// {
1458    ///     let mut scope = RootScope::new(&mut store);
1459    ///
1460    ///     // `c` is a different GC root, is in a different scope, and is a
1461    ///     // `Rooted<T>` instead of a `ManuallyRooted<T>`, but is still rooting
1462    ///     // the same object.
1463    ///     let c = a.to_rooted(&mut scope);
1464    ///     assert!(ManuallyRooted::ref_eq(&scope, &a, &c)?);
1465    /// }
1466    ///
1467    /// let x = ExternRef::new_manually_rooted(&mut store, "goodbye")?;
1468    ///
1469    /// // `a` and `x` are rooting different objects.
1470    /// assert!(!ManuallyRooted::ref_eq(&store, &a, &x)?);
1471    ///
1472    /// a.unroot(&mut store);
1473    /// b.unroot(&mut store);
1474    /// x.unroot(&mut store);
1475    /// # Ok(())
1476    /// # }
1477    /// ```
1478    pub fn ref_eq(
1479        store: impl AsContext,
1480        a: &impl RootedGcRef<T>,
1481        b: &impl RootedGcRef<T>,
1482    ) -> Result<bool> {
1483        Rooted::ref_eq(store, a, b)
1484    }
1485
1486    /// Hash this root.
1487    ///
1488    /// Note that, similar to `Rooted::rooted_eq`, this only operates on the
1489    /// root and *not* the underlying GC reference. That means that two
1490    /// different rootings of the same object will hash to different values
1491    /// (modulo hash collisions). If this is undesirable, use the
1492    /// [`ref_hash`][crate::ManuallyRooted::ref_hash] method instead.
1493    pub fn rooted_hash<H>(&self, state: &mut H)
1494    where
1495        H: std::hash::Hasher,
1496    {
1497        self.inner.hash(state);
1498    }
1499
1500    /// Hash the underlying rooted object reference.
1501    ///
1502    /// Note that, similar to `Rooted::ref_eq`, and operates on the underlying
1503    /// rooted GC object reference, not the root. That means that two
1504    /// *different* rootings of the same object will hash to the *same*
1505    /// value. If this is undesirable, use the
1506    /// [`rooted_hash`][crate::Rooted::rooted_hash] method instead.
1507    pub fn ref_hash<H>(&self, store: impl AsContext, state: &mut H)
1508    where
1509        H: std::hash::Hasher,
1510    {
1511        let gc_ref = self
1512            .get_gc_ref(store.as_context().0)
1513            .expect("ManuallyRooted's get_gc_ref is infallible");
1514        gc_ref.hash(state);
1515    }
1516}
1517
1518impl<T: GcRef> RootedGcRefImpl<T> for ManuallyRooted<T> {
1519    fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> {
1520        assert!(
1521            self.comes_from_same_store(store),
1522            "object used with wrong store"
1523        );
1524
1525        let id = self.inner.index.as_manual().unwrap();
1526        store.gc_roots().manually_rooted.get(id)
1527    }
1528}
1529
1530#[cfg(test)]
1531mod tests {
1532    use crate::ExternRef;
1533
1534    use super::*;
1535
1536    #[test]
1537    fn sizes() {
1538        // Try to keep tabs on the size of these things. Don't want them growing
1539        // unintentionally.
1540        assert_eq!(std::mem::size_of::<Rooted<ExternRef>>(), 16);
1541        assert_eq!(std::mem::size_of::<ManuallyRooted<ExternRef>>(), 16);
1542    }
1543}