Skip to main content

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//! The two main design axes that trade off the above goals are:
31//!
32//! - Where the GC reference itself is held. A root object could
33//!   directly hold the underlying GC reference (offset into the GC
34//!   storage area), which would allow more efficient dereferencing
35//!   and access to the referred-to GC object. However, goal (2)
36//!   requires that the GC is able to update references when objects
37//!   move during a GC. Thus, such "direct roots" would need to be
38//!   registered somehow in a global root registry, and would need to
39//!   unregister themselves when dropped.
40//!
41//!   The alternative is to hold some indirect kind of reference to a
42//!   GC reference, with the latter stored directly in the `Store` so
43//!   the GC can update it freely. This adds one pointer-chasing hop
44//!   to accesses, but works much more nicely with ownership
45//!   semantics. Logically, the `Store` "owns" the actual pointers;
46//!   and rooting types own the slots that they are stored in.
47//!
48//!   For the above reasons, all of our rooting types below use
49//!   indirection. This avoids the need for an unsafe
50//!   intrusive-linked-list for global registration, or a shared
51//!   reference to a mutex-protected registry, or some other
52//!   error-prone technique.
53//!
54//! - How unrooting occurs. Ideally, a rooting type would implement
55//!   the Rust `Drop` trait and unroot itself when the Rust value is
56//!   dropped. However, because the rooting state is held in the
57//!   `Store`, this direct approach would imply keeping a shared,
58//!   mutex-protected handle to the registry in every rooting
59//!   object. This would add synchronization overhead to the common
60//!   case, and in general would be a bad tradeoff.
61//!
62//!   However, there are several other approaches:
63//!
64//!   - The user could use an RAII wrapper that *does* own the `Store`,
65//!     and defines a "scope" in which roots are created and then
66//!     bulk-unrooted at the close of the scope.
67//!   - The rooting type could hold a shared reference to some state
68//!     *other* than the full registry, and update a flag in that
69//!     state indicating it has been dropped; the `Store` could then
70//!     later observe that flag and remove the root. This would have
71//!     some allocation cost, but the shared state would be
72//!     independent of the `Store` and specific to each root, so would
73//!     impose no synchronization overhead between different roots or
74//!     the GC itself.
75//!   - The rooting type could provide a fully manual `unroot` method,
76//!     allowing the user to make use of their own knowledge of their
77//!     application's lifetimes and semantics and remove roots when
78//!     appropriate.
79//!
80//!   We provide an implementation of the first two of these
81//!   strategies below in `Rooted` and `OwnedRooted`. The last, fully
82//!   manual, approach is too difficult to use correctly (it cannot
83//!   implement Rust's `Drop` trait, but there is no way in Rust to
84//!   enforce that a value must be consumed rather than dropped) so it
85//!   is not implemented.
86//!
87//! ## Two Flavors of Rooting API
88//!
89//! Okay, with that out of the way, this module provides two flavors
90//! of rooting API. One for the common, scoped lifetime case, and one that
91//! carries ownership until dropped, and can work as an RAII handle
92//! that interacts well with Rust ownership semantics (but at a minor
93//! performance cost):
94//!
95//! 1. `RootScope` and `Rooted<T>`: These are used for temporarily rooting GC
96//!    objects for the duration of a scope. The internal implementation takes
97//!    advantage of the LIFO property inherent in scopes, making creating and
98//!    dropping `Rooted<T>`s and `RootScope`s super fast and roughly equivalent
99//!    to bump allocation.
100//!
101//!    This type is vaguely similar to V8's [`HandleScope`].
102//!
103//!    [`HandleScope`]: https://v8.github.io/api/head/classv8_1_1HandleScope.html
104//!
105//!    Note that `Rooted<T>` can't be statically tied to its context scope via a
106//!    lifetime parameter, unfortunately, as that would allow the creation of
107//!    only one `Rooted<T>` at a time, since the `Rooted<T>` would take a borrow
108//!    of the whole context.
109//!
110//!    This supports the common use case for rooting and provides good
111//!    ergonomics.
112//!
113//! 2. `OwnedRooted<T>`: This is a root that manages rooting and
114//!    unrooting automatically with its lifetime as a Rust value. In
115//!    other words, the continued existence of the Rust value ensures
116//!    the rooting of the underlying GC reference; and when the Rust
117//!    value is dropped, the underlying GC reference is no longer
118//!    rooted.
119//!
120//!    Internally, this root holds a shared reference to a
121//!    *root-specific* bit of state that is also tracked and observed
122//!    by the `Store`.  This means that there is minor memory
123//!    allocation overhead (an `Arc<()>`) for each such root; this
124//!    memory is shared over all clones of this root. The rooted GC
125//!    reference is *logically* unrooted as soon as the last clone of
126//!    this root is dropped. Internally the root may still exist until
127//!    the next GC, or "root trim" when another `OwnedRooted` is
128//!    created, but that is unobservable externally, and will not
129//!    result in any additional GC object lifetime because it is
130//!    always cleaned up before a gc.
131//!
132//!    This type is roughly similar to SpiderMonkey's [`PersistentRooted<T>`],
133//!    although they register roots on a per-thread `JSContext`, avoiding
134//!    mutation costs in a way that is not viable for Wasmtime (which needs
135//!    `Store`s to be `Send`).
136//!
137//!    [`PersistentRooted<T>`]: http://devdoc.net/web/developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference/JS::PersistentRooted.html
138//!
139//! At the end of the day, all of the above root types are just tagged
140//! indices into the store's `RootSet`. This indirection allows
141//! working with Rust's borrowing discipline (we use `&mut Store` to
142//! represent mutable access to the GC heap) while still allowing
143//! rooted references to be moved around without tying up the whole
144//! store in borrows. Additionally, and crucially, this indirection
145//! allows us to update the *actual* GC pointers in the `RootSet` and
146//! support moving GCs (again, as mentioned above).
147//!
148//! ## Unrooted References
149//!
150//! We generally don't expose *unrooted* GC references in the Wasmtime API at
151//! this time -- and I expect it will be a very long time before we do, but in
152//! the limit we may want to let users define their own GC-managed types that
153//! participate in GC tracing and all that -- so we don't have to worry about
154//! failure to root an object causing use-after-free bugs or failing to update a
155//! GC root pointer after a moving GC as long as users stick to our safe rooting
156//! APIs. (The one exception is `ValRaw`, which does hold raw GC references. But
157//! with `ValRaw` all bets are off and safety is 100% up to the user.)
158//!
159//! We do, however, have to worry about these things internally. So first of
160//! all, try to avoid ever working with unrooted GC references if you
161//! can. However, if you really must, consider also using an `AutoAssertNoGc`
162//! across the block of code that is manipulating raw GC references.
163
164use crate::runtime::vm::{GcRootsList, GcStore, VMGcRef};
165use crate::{
166    AsContext, AsContextMut, GcRef, Result, RootedGcRef,
167    error::OutOfMemory,
168    store::{AsStoreOpaque, AutoAssertNoGc, StoreId, StoreOpaque},
169};
170use crate::{ValRaw, prelude::*};
171use alloc::sync::{Arc, Weak};
172use core::any;
173use core::marker;
174use core::mem::{self, MaybeUninit};
175use core::num::{NonZeroU32, NonZeroU64, NonZeroUsize};
176use core::{
177    fmt::{self, Debug},
178    hash::{Hash, Hasher},
179    ops::{Deref, DerefMut},
180};
181use wasmtime_core::slab::{Id as SlabId, Slab};
182
183mod sealed {
184    use super::*;
185
186    /// Sealed, `wasmtime`-internal trait for GC references.
187    ///
188    /// # Safety
189    ///
190    /// All types implementing this trait must:
191    ///
192    /// * Be a newtype of a `GcRootIndex`
193    ///
194    /// * Not implement `Copy` or `Clone`
195    ///
196    /// * Only have `&self` methods.
197    pub unsafe trait GcRefImpl: Sized {
198        /// Transmute a `&GcRootIndex` into an `&Self`.
199        fn transmute_ref(index: &GcRootIndex) -> &Self;
200    }
201
202    /// Sealed, `wasmtime`-internal trait for the common methods on rooted GC
203    /// references.
204    pub trait RootedGcRefImpl<T: GcRef> {
205        /// Get this rooted GC reference's raw `VMGcRef` out of the store's GC
206        /// root set.
207        ///
208        /// Returns `None` for objects that have since been unrooted (eg because
209        /// its associated `RootedScope` was dropped).
210        ///
211        /// Panics if this root is not associated with the given store.
212        fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef>;
213
214        /// Same as `get_gc_ref` but returns an error instead of `None` for
215        /// objects that have been unrooted.
216        fn try_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Result<&'a VMGcRef> {
217            self.get_gc_ref(store).ok_or_else(|| {
218                format_err!("attempted to use a garbage-collected object that has been unrooted")
219            })
220        }
221
222        /// Get a clone of this rooted GC reference's raw `VMGcRef` out of the
223        /// store's GC root set.
224        ///
225        /// Returns `None` for objects that have since been unrooted (eg because
226        /// its associated `RootedScope` was dropped).
227        ///
228        /// Panics if this root is not associated with the given store.
229        fn clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Option<VMGcRef> {
230            let gc_ref = self.get_gc_ref(store)?.unchecked_copy();
231            Some(store.clone_gc_ref(&gc_ref))
232        }
233
234        /// Same as `clone_gc_ref` but returns an error instead of `None` for
235        /// objects that have been unrooted.
236        fn try_clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Result<VMGcRef> {
237            let gc_ref = self.try_gc_ref(store)?.unchecked_copy();
238            Ok(store.clone_gc_ref(&gc_ref))
239        }
240    }
241}
242pub(crate) use sealed::*;
243
244/// The index of a GC root inside a particular store's GC root set.
245///
246/// Can be either a LIFO- or owned-rooted object, depending on the
247/// `PackedIndex`.
248///
249/// Every `T` such that `T: GcRef` must be a newtype over this `GcRootIndex`.
250#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
251// Just `pub` to avoid `warn(private_interfaces)` in public APIs, which we can't
252// `allow(...)` on our MSRV yet.
253#[doc(hidden)]
254#[repr(C)] // NB: if this layout changes be sure to change the C API as well
255pub struct GcRootIndex {
256    store_id: StoreId,
257    generation: u32,
258    index: PackedIndex,
259}
260
261const _: () = {
262    // NB: these match the C API which should also be updated if this changes
263    assert!(mem::size_of::<GcRootIndex>() == 16);
264    assert!(mem::align_of::<GcRootIndex>() == mem::align_of::<u64>());
265};
266
267impl GcRootIndex {
268    #[inline]
269    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
270        self.store_id == store.id()
271    }
272
273    /// Same as `RootedGcRefImpl::get_gc_ref` but not associated with any
274    /// particular `T: GcRef`.
275    ///
276    /// We must avoid triggering a GC while holding onto the resulting raw
277    /// `VMGcRef` to avoid use-after-free bugs and similar. The `'a` lifetime
278    /// threaded from the `store` to the result will normally prevent GCs
279    /// statically, at compile time, since performing a GC requires a mutable
280    /// borrow of the store. However, if you call `VMGcRef::unchecked_copy` on
281    /// the resulting GC reference, then all bets are off and this invariant is
282    /// up to you to manually uphold. Failure to uphold this invariant is memory
283    /// safe but will lead to general incorrectness such as panics and wrong
284    /// results.
285    ///
286    /// # Panics
287    ///
288    /// Panics if `self` is not associated with the given store.
289    pub(crate) fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> {
290        assert!(
291            self.comes_from_same_store(store),
292            "object used with wrong store"
293        );
294        if let Some(index) = self.index.as_lifo() {
295            let entry = store.gc_roots().lifo_roots.get(index)?;
296            if entry.generation == self.generation {
297                Some(&entry.gc_ref)
298            } else {
299                None
300            }
301        } else if let Some(id) = self.index.as_owned() {
302            let gc_ref = store.gc_roots().owned_rooted.get(id);
303            debug_assert!(gc_ref.is_some());
304            gc_ref
305        } else {
306            unreachable!()
307        }
308    }
309
310    /// Same as `get_gc_ref` but returns an error instead of `None` if
311    /// the GC reference has been unrooted.
312    ///
313    /// # Panics
314    ///
315    /// Panics if `self` is not associated with the given store.
316    pub(crate) fn try_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Result<&'a VMGcRef> {
317        self.get_gc_ref(store).ok_or_else(|| {
318            format_err!("attempted to use a garbage-collected object that has been unrooted")
319        })
320    }
321
322    /// Same as `RootedGcRefImpl::clone_gc_ref` but not associated with any
323    /// particular `T: GcRef`.
324    pub(crate) fn try_clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Result<VMGcRef> {
325        let gc_ref = self.try_gc_ref(store)?.unchecked_copy();
326        Ok(store.clone_gc_ref(&gc_ref))
327    }
328
329    /// Exposes this value's raw `VMGcRef` to wasm as a `u32`.
330    pub(crate) fn expose_gc_ref_to_wasm(
331        &self,
332        store: &mut AutoAssertNoGc<'_>,
333    ) -> Result<NonZeroU32> {
334        let gc_ref = self.try_clone_gc_ref(store)?;
335
336        let raw = match store.optional_gc_store_mut() {
337            Some(s) => s.expose_gc_ref_to_wasm(gc_ref)?,
338            None => {
339                // NB: do not force the allocation of a GC heap just because the
340                // program is using `i31ref`s.
341                debug_assert!(gc_ref.is_i31());
342                gc_ref.as_raw_non_zero_u32()
343            }
344        };
345
346        Ok(raw)
347    }
348}
349
350/// This is a bit-packed version of
351///
352/// ```ignore
353/// enum {
354///     Lifo(usize),
355///     Owned(SlabId),
356/// }
357/// ```
358///
359/// where the high bit is the discriminant and the lower 31 bits are the
360/// payload.
361#[derive(Clone, Copy, PartialEq, Eq, Hash)]
362#[repr(transparent)]
363struct PackedIndex(u32);
364
365impl Debug for PackedIndex {
366    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367        if let Some(index) = self.as_lifo() {
368            f.debug_tuple("PackedIndex::Lifo").field(&index).finish()
369        } else if let Some(id) = self.as_owned() {
370            f.debug_tuple("PackedIndex::Owned").field(&id).finish()
371        } else {
372            unreachable!()
373        }
374    }
375}
376
377impl PackedIndex {
378    const DISCRIMINANT_MASK: u32 = 0b1 << 31;
379    const LIFO_DISCRIMINANT: u32 = 0b0 << 31;
380    const OWNED_DISCRIMINANT: u32 = 0b1 << 31;
381    const PAYLOAD_MASK: u32 = !Self::DISCRIMINANT_MASK;
382
383    fn new_lifo(index: usize) -> PackedIndex {
384        let index32 = u32::try_from(index).unwrap();
385        assert_eq!(index32 & Self::DISCRIMINANT_MASK, 0);
386        let packed = PackedIndex(Self::LIFO_DISCRIMINANT | index32);
387        debug_assert!(packed.is_lifo());
388        debug_assert_eq!(packed.as_lifo(), Some(index));
389        debug_assert!(!packed.is_owned());
390        debug_assert!(packed.as_owned().is_none());
391        packed
392    }
393
394    fn new_owned(id: SlabId) -> PackedIndex {
395        let raw = id.into_raw();
396        assert_eq!(raw & Self::DISCRIMINANT_MASK, 0);
397        let packed = PackedIndex(Self::OWNED_DISCRIMINANT | raw);
398        debug_assert!(packed.is_owned());
399        debug_assert_eq!(packed.as_owned(), Some(id));
400        debug_assert!(!packed.is_lifo());
401        debug_assert!(packed.as_lifo().is_none());
402        packed
403    }
404
405    fn discriminant(&self) -> u32 {
406        self.0 & Self::DISCRIMINANT_MASK
407    }
408
409    fn is_lifo(&self) -> bool {
410        self.discriminant() == Self::LIFO_DISCRIMINANT
411    }
412
413    fn is_owned(&self) -> bool {
414        self.discriminant() == Self::OWNED_DISCRIMINANT
415    }
416
417    fn payload(&self) -> u32 {
418        self.0 & Self::PAYLOAD_MASK
419    }
420
421    fn as_lifo(&self) -> Option<usize> {
422        if self.is_lifo() {
423            Some(usize::try_from(self.payload()).unwrap())
424        } else {
425            None
426        }
427    }
428
429    fn as_owned(&self) -> Option<SlabId> {
430        if self.is_owned() {
431            Some(SlabId::from_raw(self.payload()))
432        } else {
433            None
434        }
435    }
436}
437
438/// The set of all embedder-API GC roots in a single store/heap.
439#[derive(Debug, Default)]
440pub(crate) struct RootSet {
441    /// GC roots with arbitrary lifetime that are unrooted when
442    /// liveness flags are cleared (seen during a trimming pass), for
443    /// use with `OwnedRooted<T>`.
444    owned_rooted: Slab<VMGcRef>,
445
446    /// List of liveness flags and corresponding `SlabId`s into the
447    /// `owned_rooted` slab.
448    liveness_flags: Vec<(Weak<()>, SlabId)>,
449
450    /// High-water mark for liveness flag trimming. We use this to
451    /// ensure we have amortized constant-time behavior on adding
452    /// roots. See note below on `trim_liveness_flags()`.
453    liveness_trim_high_water: Option<NonZeroUsize>,
454
455    /// Strictly LIFO-ordered GC roots, for use with `RootScope` and
456    /// `Rooted<T>`.
457    lifo_roots: Vec<LifoRoot>,
458
459    /// Generation counter for entries to prevent ABA bugs with `RootScope` and
460    /// `Rooted<T>`.
461    lifo_generation: u32,
462}
463
464#[derive(Debug)]
465struct LifoRoot {
466    generation: u32,
467    gc_ref: VMGcRef,
468}
469
470impl RootSet {
471    pub(crate) fn trace_roots(&mut self, gc_roots_list: &mut GcRootsList) {
472        log::trace!("Begin trace user LIFO roots");
473        for root in &mut self.lifo_roots {
474            unsafe {
475                gc_roots_list.add_vmgcref_root((&mut root.gc_ref).into(), "user LIFO root");
476            }
477        }
478        log::trace!("End trace user LIFO roots");
479
480        log::trace!("Begin trace user owned roots");
481        for (_id, root) in self.owned_rooted.iter_mut() {
482            unsafe {
483                gc_roots_list.add_vmgcref_root(root.into(), "user owned root");
484            }
485        }
486        log::trace!("End trace user owned roots");
487    }
488
489    /// Enter a LIFO rooting scope.
490    ///
491    /// Returns an integer that should be passed unmodified to `exit_lifo_scope`
492    /// when the scope is finished.
493    ///
494    /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order.
495    #[inline]
496    pub(crate) fn enter_lifo_scope(&self) -> usize {
497        self.lifo_roots.len()
498    }
499
500    /// Exit a LIFO rooting scope.
501    ///
502    /// The `scope` argument must be the result of the corresponding
503    /// `enter_lifo_scope` call.
504    ///
505    /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order.
506    #[inline]
507    pub(crate) fn exit_lifo_scope(&mut self, gc_store: Option<&mut GcStore>, scope: usize) {
508        debug_assert!(self.lifo_roots.len() >= scope);
509
510        // If we actually have roots to unroot, call an out-of-line slow path.
511        if self.lifo_roots.len() > scope {
512            self.exit_lifo_scope_slow(gc_store, scope);
513        }
514    }
515
516    #[inline(never)]
517    #[cold]
518    fn exit_lifo_scope_slow(&mut self, mut gc_store: Option<&mut GcStore>, scope: usize) {
519        self.lifo_generation += 1;
520
521        // TODO: In the case where we have a tracing GC that doesn't need to
522        // drop barriers, this should really be:
523        //
524        //     self.lifo_roots.truncate(scope);
525
526        let mut lifo_roots = mem::take(&mut self.lifo_roots);
527        for root in lifo_roots.drain(scope..) {
528            // Only drop the GC reference if we actually have a GC store. How
529            // can we have a GC reference but not a GC store? If we've only
530            // created `i31refs`, we never force a GC store's allocation. This
531            // is fine because `i31ref`s never need drop barriers.
532            if let Some(gc_store) = &mut gc_store {
533                gc_store.drop_gc_ref(root.gc_ref);
534            }
535        }
536        self.lifo_roots = lifo_roots;
537    }
538
539    pub(crate) fn with_lifo_scope<S, T>(store: &mut S, f: impl FnOnce(&mut S) -> T) -> T
540    where
541        S: ?Sized + DerefMut<Target = StoreOpaque>,
542    {
543        let scope = store.gc_roots().enter_lifo_scope();
544        let ret = f(store);
545        store.exit_gc_lifo_scope(scope);
546        ret
547    }
548
549    pub(crate) fn push_lifo_root(&mut self, store_id: StoreId, gc_ref: VMGcRef) -> GcRootIndex {
550        let generation = self.lifo_generation;
551        let index = self.lifo_roots.len();
552        let index = PackedIndex::new_lifo(index);
553        self.lifo_roots.push(LifoRoot { generation, gc_ref });
554        GcRootIndex {
555            store_id,
556            generation,
557            index,
558        }
559    }
560
561    /// Trim any stale (dropped) owned roots.
562    ///
563    /// `OwnedRooted` is implemented in a way that avoids the need to
564    /// have or keep a reference to the store (and thus this struct)
565    /// during its drop operation: to allow it to be independent, it
566    /// holds a shared reference to some other memory and sets that
567    /// "liveness flag" appropriately, then we later observe dead
568    /// liveness flags during a periodic scan and actually deallocate
569    /// the roots. We use an `Arc<()>` for this: it permits cheap
570    /// cloning, and it has minimal memory overhead. We hold a weak
571    /// ref in a list alongside the actual `GcRootIndex`, and we free
572    /// that index in the slab of owned roots when we observe that
573    /// only our weak ref remains.
574    ///
575    /// This trim step is logically separate from a full GC, though it
576    /// would not be very productive to do a GC without doing a
577    /// root-trim first: the root-trim should be quite a lot cheaper,
578    /// and it will allow for more garbage to exist.
579    ///
580    /// There is, additionally, nothing stopping us from doing trims
581    /// more often than just before each GC, and there are reasons
582    /// this could be a good idea: for example, a user program that
583    /// creates and removes many roots (perhaps as it accesses the GC
584    /// object graph) but ultimately is dealing with a static graph,
585    /// without further allocation, may need the "root set" to be GC'd
586    /// independently from the actual heap. Thus, we could trim before
587    /// adding a new root to ensure we don't grow that unboundedly (or
588    /// force an otherwise unneeded GC).
589    ///
590    /// The first case, just before GC, wants a "full trim": there's
591    /// no reason not to unroot as much as possible before we do the
592    /// expensive work of tracing the whole heap.
593    ///
594    /// On the other hand, the second case, adding a new root, wants a
595    /// kind of trim that is amortized constant time. Consider: if we
596    /// have some threshold for the trim, say N roots, and the user
597    /// program continually adds and removes one root such that it
598    /// goes just over the threshold, we might scan all N liveness
599    /// flags for each step, resulting in quadratic behavior overall.
600    ///
601    /// Thus, we implement a "high water mark" algorithm to guard
602    /// against this latter case: on the add-a-new-root case, we trim
603    /// only if the list is longer than the high water mark, and we
604    /// set the high water mark each time based on the after-trim
605    /// size. See below for details on this algorithm.
606    ///
607    /// `eager` chooses whether we eagerly trim roots or pre-filter
608    /// using the high-water mark.
609    ///
610    /// # Growth Algorithm
611    ///
612    /// We want to balance two factors: we must ensure that the
613    /// algorithmic complexity of creating a new root is amortized
614    /// O(1), and we must ensure that repeated creation and deletion
615    /// of roots without any GC must result in a root-set that has a
616    /// size linear in the actual live-root-set size. Stated formally:
617    ///
618    /// 1. Root creation must be O(1), amortized
619    /// 2. liveness_flags.len() must be O(|max live owned roots|),
620    ///    i.e., must not grow to larger than a constant multiple of
621    ///    the maximum working-root-set size of the program.
622    ///
623    /// Note that a naive exponential-growth-of-threshold algorithm,
624    /// where we trim when the root set reaches 1, 2, 4, 8, 16, 32,
625    /// ... elements, provides the first but *not* the second
626    /// property. A workload that has a constant live root set but
627    /// creates and drops roots constantly (say, as it's traversing a
628    /// static graph and moving "fingers" through it) will cause the
629    /// `liveness_flags` array to grow unboundedly.
630    ///
631    /// Instead, it turns out that we can achieve both of these goals
632    /// with a simple rule: we trim when the root list length reaches
633    /// a high-water mark; and then *after* trimming, we set the
634    /// high-water mark equal to the resulting live-root count
635    /// multiplied by a factor (e.g., 2).
636    ///
637    /// ## Proof
638    ///
639    /// - Root creation is O(1)
640    ///
641    ///   Assume a sequence of root creation and drop events (and no
642    ///   GCs, with a static GC graph, in the worst case -- only roots
643    ///   are changing). We want to show that after N root creations,
644    ///   we have incurred only only O(N) cost scanning the
645    ///   `liveness_flags` list over the whole sequence.
646    ///
647    ///   Assume a default high-water mark of D (e.g., 8) at
648    ///   initialization with an empty root list.
649    ///
650    ///   Consider "epochs" in the sequence split by trim events where
651    ///   we scan the root list. Proceed by induction over epochs to
652    ///   show: after each epoch, we will have scanned at most 2N
653    ///   roots after N root creations.
654    ///
655    ///   (These epochs don't exist in the algorithm: this is just a
656    ///   mechanism to analyze the behavior.)
657    ///
658    ///   Base case: after the first epoch, with D root creations, we
659    ///   will scan D roots.
660    ///
661    ///   Induction step: we have created N roots and scanned at most
662    ///   2N roots. After previous scan, L roots are still live; then
663    ///   we set the high-water mark for next scan at 2L. The list
664    ///   already has L, so after another L root creations, the epoch
665    ///   ends. We will then incur a scan cost of 2L (the full
666    ///   list). At that point we have thus seen N + L root creations,
667    ///   with 2N + 2L scan cost; the invariant holds.
668    ///
669    ///   (It's counter-intuitive that *not* raising the high-water
670    ///   mark exponentially can still result in a constant amortized
671    ///   cost! One intuition to understand this is that each root
672    ///   that remains alive after a scan pushes the next high-water
673    ///   mark up by one, so requires a new root creation to "pay for"
674    ///   its next scan. So any given root may be scanned many times,
675    ///   but each such root ensures other root creations happen to
676    ///   maintain the amortized cost.)
677    ///
678    /// - `liveness_flags.len()` is always O(|max live roots|)
679    ///
680    ///   Before the first trim, we have between 0 and D live roots,
681    ///   which is O(1) (`D` is a compile-time constant).
682    ///
683    ///   Just after a trim, the `liveness_flags` list has only live
684    ///   roots, and the max live-root count is at least the count at
685    ///   this time, so the property holds.
686    ///
687    ///   The instantaneous maximum number of live roots is greater
688    ///   than or equal to the maximum number of live roots observed
689    ///   during a trim. (The trim is just some point in time, and the
690    ///   max at some point in time is at most the overall max.)
691    ///
692    ///   The high-water mark is set at 2 * `liveness_flags.len()`
693    ///   after a trim, i.e., the number of live roots at that
694    ///   time. We trim when we reach the high-water mark. So the
695    ///   length of the array cannot exceed 2 *
696    ///   `liveness_flags.len()`, which is less than or equal to the
697    ///   overall max. So transitively, the list length at any time is
698    ///   always O(|max live roots|).
699    ///
700    /// We thus have tight bounds (deterministic, not randomized) for
701    /// all possible sequences of root creation/dropping, ensuring
702    /// robustness.
703    pub(crate) fn trim_liveness_flags(&mut self, gc_store: &mut GcStore, eager: bool) {
704        const DEFAULT_HIGH_WATER: usize = 8;
705        const GROWTH_FACTOR: usize = 2;
706        let high_water_mark = self
707            .liveness_trim_high_water
708            .map(|x| x.get())
709            .unwrap_or(DEFAULT_HIGH_WATER);
710        if !eager && self.liveness_flags.len() < high_water_mark {
711            return;
712        }
713
714        self.liveness_flags.retain(|(flag, index)| {
715            if flag.strong_count() == 0 {
716                // No more `OwnedRooted` instances are holding onto
717                // this; dealloc the index and drop our Weak.
718                let gc_ref = self.owned_rooted.dealloc(*index);
719                gc_store.drop_gc_ref(gc_ref);
720                // Don't retain in the list.
721                false
722            } else {
723                // Retain in the list.
724                true
725            }
726        });
727
728        let post_trim_len = self.liveness_flags.len();
729        let high_water_mark = core::cmp::max(
730            DEFAULT_HIGH_WATER,
731            post_trim_len.saturating_mul(GROWTH_FACTOR),
732        );
733        self.liveness_trim_high_water = Some(NonZeroUsize::new(high_water_mark).unwrap());
734    }
735}
736
737/// A scoped, rooted reference to a garbage-collected `T`.
738///
739/// A `Rooted<T>` is a strong handle to a garbage-collected `T`, preventing its
740/// referent (and anything else transitively referenced) from being collected by
741/// the GC during the scope within which this `Rooted<T>` was created.
742///
743/// When the context exits this `Rooted<T>`'s scope, the underlying GC object is
744/// automatically unrooted and any further attempts to use access the underlying
745/// object will return errors or otherwise fail.
746///
747/// `Rooted<T>` dereferences to its underlying `T`, allowing you to call `T`'s
748/// methods.
749///
750/// # Example
751///
752/// ```
753/// # use wasmtime::*;
754/// # fn _foo() -> Result<()> {
755/// let mut store = Store::<()>::default();
756///
757/// // Allocating a GC object returns a `Rooted<T>`.
758/// let hello: Rooted<ExternRef> = ExternRef::new(&mut store, "hello")?;
759///
760/// // Because `Rooted<T>` derefs to `T`, we can call `T` methods on a
761/// // `Rooted<T>`. For example, we can call the `ExternRef::data` method when we
762/// // have a `Rooted<ExternRef>`.
763/// let data = hello
764///     .data(&store)?
765///     .ok_or_else(|| Error::msg("externref has no host data"))?
766///     .downcast_ref::<&str>()
767///     .ok_or_else(|| Error::msg("not a str"))?;
768/// assert_eq!(*data, "hello");
769///
770/// // A `Rooted<T>` roots its underlying GC object for the duration of the
771/// // scope of the store/caller/context that was passed to the method that created
772/// // it. If we only want to keep a GC reference rooted and alive temporarily, we
773/// // can introduce new scopes with `RootScope`.
774/// {
775///     let mut scope = RootScope::new(&mut store);
776///
777///     // This `Rooted<T>` is automatically unrooted after `scope` is dropped,
778///     // allowing the collector to reclaim its GC object in the next GC.
779///     let scoped_ref = ExternRef::new(&mut scope, "goodbye");
780/// }
781///
782/// let module = Module::new(store.engine(), r#"
783///     (module
784///         (global (export "global") (mut externref) (ref.null extern))
785///         (table (export "table") 10 externref)
786///         (func (export "func") (param externref) (result externref)
787///             local.get 0
788///         )
789///     )
790/// "#)?;
791/// let instance = Instance::new(&mut store, &module, &[])?;
792///
793/// // GC references returned from calls into Wasm also return (optional, if the
794/// // Wasm type is nullable) `Rooted<T>`s.
795/// let result: Option<Rooted<_>> = instance
796///     .get_typed_func::<Option<Rooted<ExternRef>>, Option<Rooted<ExternRef>>>(&mut store, "func")?
797///     .call(&mut store, Some(hello))?;
798///
799/// // Similarly, getting a GC reference from a Wasm instance's exported global
800/// // or table yields a `Rooted<T>`.
801///
802/// let global = instance
803///     .get_global(&mut store, "global")
804///     .ok_or_else(|| Error::msg("missing `global` export"))?;
805/// let global_val = global.get(&mut store);
806/// let global_ref: Option<&Rooted<_>> = global_val
807///     .externref()
808///     .ok_or_else(|| Error::msg("not an externref"))?;
809///
810/// let table = instance.get_table(&mut store, "table").unwrap();
811/// let table_elem = table
812///     .get(&mut store, 3)
813///     .ok_or_else(|| Error::msg("table out of bounds"))?;
814/// let table_elem_ref: Option<&Rooted<_>> = table_elem
815///     .as_extern()
816///     .ok_or_else(|| Error::msg("not an externref"))?;
817/// # Ok(())
818/// # }
819/// ```
820///
821/// # Differences Between `Rooted<T>` and `OwnedRooted<T>`
822///
823/// While `Rooted<T>` is automatically unrooted when its scope is
824/// exited, this means that `Rooted<T>` is only valid for strictly
825/// last-in-first-out (LIFO, aka stack order) lifetimes. This is in
826/// contrast to [`OwnedRooted<T>`][crate::OwnedRooted], which supports
827/// rooting GC objects for arbitrary lifetimes.
828///
829/// | Type                                         | Supported Lifetimes         | Unrooting | Cost                             |
830/// |----------------------------------------------|-----------------------------|-----------|----------------------------------|
831/// | [`Rooted<T>`][crate::Rooted]                 | Strictly LIFO / stack order | Automatic | very low (LIFO array)            |
832/// | [`OwnedRooted<T>`][crate::OwnedRooted]       | Arbitrary                   | Automatic | medium (separate `Arc` to track) |
833///
834/// `Rooted<T>` should suffice for most use cases, and provides decent
835/// ergonomics. In cases where LIFO scopes are difficult to reason
836/// about, e.g. heap-managed data structures, or when they may cause
837/// erroneous behavior, e.g. in errors that are propagated up the call
838/// stack, `OwnedRooted<T>` provides very safe ergonomics but at a
839/// small dynamic cost for the separate tracking allocation.
840///
841/// # Scopes
842///
843/// Wasmtime automatically creates two kinds of scopes:
844///
845/// 1. A [`Store`][crate::Store] is the outermost rooting scope. Creating a
846///    `Root<T>` directly inside a `Store` permanently roots the underlying
847///    object.
848///
849/// 2. A [`Caller`][crate::Caller] provides a rooting scope for the duration of
850///    a call from Wasm into a host function. Any objects rooted in a `Caller`
851///    will be unrooted after the host function returns. Note that there can be
852///    nested `Caller` scopes in the case where Wasm calls a host function,
853///    creating the first `Caller` and its rooting scope , and then the host
854///    function calls a Wasm function which then calls another host function,
855///    creating a second `Caller` and a second rooting scope. This nesting can
856///    be arbitrarily deep.
857///
858/// Additionally, if you would like to define finer-grained rooting scopes,
859/// Wasmtime provides the [`RootScope`][crate::RootScope] type.
860///
861/// Scopes are always nested in a last-in-first-out (LIFO) order. An outer scope
862/// is never exited (and the `Rooted<T>`s defined within it are never
863/// automatically unrooted) while an inner scope is still active. All inner
864/// scopes are exited before their outer scopes.
865///
866/// The following diagram illustrates various rooting scopes over time, how they
867/// nest, and when their `Rooted<T>`s are automatically unrooted:
868///
869/// ```text
870/// ----- new Store
871///   |
872///   |
873///   | let a: Rooted<T> = ...;
874///   |
875///   |
876///   | ----- call into Wasm
877///   |   |
878///   |   |
879///   |   | ----- Wasm calls host function F
880///   |   |   |
881///   |   |   |
882///   |   |   | let b: Rooted<T> = ...;
883///   |   |   |
884///   |   |   |
885///   |   |   | ----- F calls into Wasm
886///   |   |   |   |
887///   |   |   |   |
888///   |   |   |   | ----- Wasm call host function G
889///   |   |   |   |   |
890///   |   |   |   |   |
891///   |   |   |   |   | let c: Rooted<T> = ...;
892///   |   |   |   |   |
893///   |   |   |   |   |
894///   |   |   |   | ----- return to Wasm from host function G (unroots `c`)
895///   |   |   |   |
896///   |   |   |   |
897///   |   |   | ----- Wasm returns to F
898///   |   |   |
899///   |   |   |
900///   |   | ----- return from host function F (unroots `b`)
901///   |   |
902///   |   |
903///   | ----- return from Wasm
904///   |
905///   |
906///   | ----- let scope1 = RootScope::new(...);
907///   |   |
908///   |   |
909///   |   | let d: Rooted<T> = ...;
910///   |   |
911///   |   |
912///   |   | ----- let scope2 = RootScope::new(...);
913///   |   |   |
914///   |   |   |
915///   |   |   | let e: Rooted<T> = ...;
916///   |   |   |
917///   |   |   |
918///   |   | ----- drop `scope2` (unroots `e`)
919///   |   |
920///   |   |
921///   | ----- drop `scope1` (unroots `d`)
922///   |
923///   |
924/// ----- drop Store (unroots `a`)
925/// ```
926///
927/// A `Rooted<T>` can be used successfully as long as it is still rooted so, in
928/// the above diagram, `d` is valid inside `scope2` because `scope2` is wholly
929/// contained within the scope `d` was rooted within (`scope1`).
930///
931/// See also the documentation for [`RootScope`][crate::RootScope].
932#[repr(transparent)]
933pub struct Rooted<T: GcRef> {
934    inner: GcRootIndex,
935    _phantom: marker::PhantomData<T>,
936}
937
938impl<T: GcRef> Clone for Rooted<T> {
939    fn clone(&self) -> Self {
940        Rooted {
941            inner: self.inner,
942            _phantom: marker::PhantomData,
943        }
944    }
945}
946
947impl<T: GcRef> Copy for Rooted<T> {}
948
949impl<T: GcRef> Debug for Rooted<T> {
950    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
951        let name = format!("Rooted<{}>", any::type_name::<T>());
952        f.debug_struct(&name).field("inner", &self.inner).finish()
953    }
954}
955
956impl<T: GcRef> RootedGcRefImpl<T> for Rooted<T> {
957    fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> {
958        assert!(
959            self.comes_from_same_store(store),
960            "object used with wrong store"
961        );
962        let index = self.inner.index.as_lifo().unwrap();
963        let entry = store.gc_roots().lifo_roots.get(index)?;
964        if entry.generation == self.inner.generation {
965            Some(&entry.gc_ref)
966        } else {
967            None
968        }
969    }
970}
971
972impl<T: GcRef> Deref for Rooted<T> {
973    type Target = T;
974
975    fn deref(&self) -> &Self::Target {
976        T::transmute_ref(&self.inner)
977    }
978}
979
980impl<T: GcRef> Rooted<T> {
981    /// Push the given `VMGcRef` onto our LIFO root set.
982    ///
983    /// `gc_ref` should belong to `store`'s heap; failure to uphold this is
984    /// memory safe but will result in general failures down the line such as
985    /// panics or incorrect results.
986    ///
987    /// `gc_ref` should be a GC reference pointing to an instance of the GC type
988    /// that `T` represents. Failure to uphold this invariant is memory safe but
989    /// will result in general incorrectness such as panics and wrong results.
990    pub(crate) fn new(store: &mut AutoAssertNoGc<'_>, gc_ref: VMGcRef) -> Rooted<T> {
991        let id = store.id();
992        let roots = store.gc_roots_mut();
993        let inner = roots.push_lifo_root(id, gc_ref);
994        Rooted {
995            inner,
996            _phantom: marker::PhantomData,
997        }
998    }
999
1000    /// Create a new `Rooted<T>` from a `GcRootIndex`.
1001    ///
1002    /// Note that `Rooted::from_gc_root_index(my_rooted.index)` is not
1003    /// necessarily an identity function, as it allows changing the `T` type
1004    /// parameter.
1005    ///
1006    /// The given index should be a LIFO index of a GC reference pointing to an
1007    /// instance of the GC type that `T` represents. Failure to uphold this
1008    /// invariant is memory safe but will result in general incorrectness such
1009    /// as panics and wrong results.
1010    pub(crate) fn from_gc_root_index(inner: GcRootIndex) -> Rooted<T> {
1011        debug_assert!(inner.index.is_lifo());
1012        Rooted {
1013            inner,
1014            _phantom: marker::PhantomData,
1015        }
1016    }
1017
1018    #[inline]
1019    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1020        debug_assert!(self.inner.index.is_lifo());
1021        self.inner.comes_from_same_store(store)
1022    }
1023
1024    /// Create an [`OwnedRooted<T>`][crate::OwnedRooted] holding onto the
1025    /// same GC object as `self`.
1026    ///
1027    /// Returns `None` if `self` is used outside of its scope and has therefore
1028    /// been unrooted.
1029    ///
1030    /// This does not unroot `self`, and `self` remains valid until its
1031    /// associated scope is exited.
1032    ///
1033    /// # Panics
1034    ///
1035    /// Panics if this object is not associate with the given store.
1036    ///
1037    /// # Example
1038    ///
1039    /// ```
1040    /// # use wasmtime::*;
1041    /// # fn _foo() -> Result<()> {
1042    /// let mut store = Store::<()>::default();
1043    ///
1044    /// let y: OwnedRooted<_> = {
1045    ///     // Create a nested rooting scope.
1046    ///     let mut scope = RootScope::new(&mut store);
1047    ///
1048    ///     // `x` is only rooted within this nested scope.
1049    ///     let x: Rooted<_> = ExternRef::new(&mut scope, "hello!")?;
1050    ///
1051    ///     // Extend `x`'s rooting past its scope's lifetime by converting it
1052    ///     // to an `OwnedRooted`.
1053    ///     x.to_owned_rooted(&mut scope)?
1054    /// };
1055    ///
1056    /// // Now we can still access the reference outside the scope it was
1057    /// // originally defined within.
1058    /// let data = y.data(&store)?.expect("should have host data");
1059    /// let data = data.downcast_ref::<&str>().expect("host data should be str");
1060    /// assert_eq!(*data, "hello!");
1061    /// # Ok(())
1062    /// # }
1063    /// ```
1064    pub fn to_owned_rooted(&self, mut store: impl AsContextMut) -> Result<OwnedRooted<T>> {
1065        self._to_owned_rooted(store.as_context_mut().0)
1066    }
1067
1068    pub(crate) fn _to_owned_rooted(&self, store: &mut StoreOpaque) -> Result<OwnedRooted<T>> {
1069        let mut store = AutoAssertNoGc::new(store);
1070        let gc_ref = self.try_clone_gc_ref(&mut store)?;
1071        Ok(OwnedRooted::new(&mut store, gc_ref)?)
1072    }
1073
1074    /// Are these two `Rooted<T>`s the same GC root?
1075    ///
1076    /// Note that this function can return `false` even when `a` and `b` are
1077    /// rooting the same underlying GC object, but the object was rooted
1078    /// multiple times (for example in different scopes). Use
1079    /// [`Rooted::ref_eq`][crate::Rooted::ref_eq] to test whether these are
1080    /// references to the same underlying GC object or not.
1081    ///
1082    /// # Example
1083    ///
1084    /// ```
1085    /// # use wasmtime::*;
1086    /// # fn foo() -> Result<()> {
1087    /// let mut store = Store::<()>::default();
1088    ///
1089    /// let a = ExternRef::new(&mut store, "hello")?;
1090    /// let b = a;
1091    ///
1092    /// // `a` and `b` are the same GC root.
1093    /// assert!(Rooted::rooted_eq(a, b));
1094    ///
1095    /// {
1096    ///     let mut scope = RootScope::new(&mut store);
1097    ///
1098    ///     // `c` is a different GC root, in a different scope, even though it
1099    ///     // is rooting the same object.
1100    ///     let c = a.to_owned_rooted(&mut scope)?.to_rooted(&mut scope);
1101    ///     assert!(!Rooted::rooted_eq(a, c));
1102    /// }
1103    ///
1104    /// let x = ExternRef::new(&mut store, "goodbye")?;
1105    ///
1106    /// // `a` and `x` are different GC roots, rooting different objects.
1107    /// assert!(!Rooted::rooted_eq(a, x));
1108    /// # Ok(())
1109    /// # }
1110    /// ```
1111    pub fn rooted_eq(a: Self, b: Self) -> bool {
1112        a.inner == b.inner
1113    }
1114
1115    /// Are these two GC roots referencing the same underlying GC object?
1116    ///
1117    /// This function will return `true` even when `a` and `b` are different GC
1118    /// roots (for example because they were rooted in different scopes) if they
1119    /// are rooting the same underlying GC object. To only test whether they are
1120    /// the same GC root, and not whether they are rooting the same GC object,
1121    /// use [`Rooted::rooted_eq`][crate::Rooted::rooted_eq].
1122    ///
1123    /// Returns an error if either `a` or `b` has been unrooted, for example
1124    /// because the scope it was rooted within has been exited.
1125    ///
1126    /// Because this method takes any `impl RootedGcRef<T>` arguments, it can be
1127    /// used to compare, for example, a `Rooted<T>` and a `OwnedRooted<T>`.
1128    ///
1129    /// # Panics
1130    ///
1131    /// Panics if either `a` or `b` is not associated with the given `store`.
1132    ///
1133    /// # Example
1134    ///
1135    /// ```
1136    /// # use wasmtime::*;
1137    /// # fn foo() -> Result<()> {
1138    /// let mut store = Store::<()>::default();
1139    ///
1140    /// let a = ExternRef::new(&mut store, "hello")?;
1141    /// let b = a;
1142    ///
1143    /// // `a` and `b` are rooting the same object.
1144    /// assert!(Rooted::ref_eq(&store, &a, &b)?);
1145    ///
1146    /// {
1147    ///     let mut scope = RootScope::new(&mut store);
1148    ///
1149    ///     // `c` is a different GC root, in a different scope, but still
1150    ///     // rooting the same object.
1151    ///     let c = a.to_owned_rooted(&mut scope)?.to_rooted(&mut scope);
1152    ///     assert!(!Rooted::ref_eq(&scope, &a, &c)?);
1153    /// }
1154    ///
1155    /// let x = ExternRef::new(&mut store, "goodbye")?;
1156    ///
1157    /// // `a` and `x` are rooting different objects.
1158    /// assert!(!Rooted::ref_eq(&store, &a, &x)?);
1159    ///
1160    /// // You can also compare `Rooted<T>`s and `OwnedRooted<T>`s with this
1161    /// // function.
1162    /// let d = a.to_owned_rooted(&mut store)?;
1163    /// assert!(Rooted::ref_eq(&store, &a, &d)?);
1164    /// # Ok(())
1165    /// # }
1166    /// ```
1167    pub fn ref_eq(
1168        store: impl AsContext,
1169        a: &impl RootedGcRef<T>,
1170        b: &impl RootedGcRef<T>,
1171    ) -> Result<bool> {
1172        let store = store.as_context().0;
1173        Self::_ref_eq(store, a, b)
1174    }
1175
1176    pub(crate) fn _ref_eq(
1177        store: &StoreOpaque,
1178        a: &impl RootedGcRef<T>,
1179        b: &impl RootedGcRef<T>,
1180    ) -> Result<bool> {
1181        let a = a.try_gc_ref(store)?;
1182        let b = b.try_gc_ref(store)?;
1183        Ok(a == b)
1184    }
1185
1186    /// Hash this root.
1187    ///
1188    /// Note that, similar to `Rooted::rooted_eq`, this only operates on the
1189    /// root and *not* the underlying GC reference. That means that two
1190    /// different rootings of the same object will hash to different values
1191    /// (modulo hash collisions). If this is undesirable, use the
1192    /// [`ref_hash`][crate::Rooted::ref_hash] method instead.
1193    pub fn rooted_hash<H>(&self, state: &mut H)
1194    where
1195        H: Hasher,
1196    {
1197        self.inner.hash(state);
1198    }
1199
1200    /// Hash the underlying rooted object reference.
1201    ///
1202    /// Note that, similar to `Rooted::ref_eq`, and operates on the underlying
1203    /// rooted GC object reference, not the root. That means that two
1204    /// *different* rootings of the same object will hash to the *same*
1205    /// value. If this is undesirable, use the
1206    /// [`rooted_hash`][crate::Rooted::rooted_hash] method instead.
1207    pub fn ref_hash<H>(&self, store: impl AsContext, state: &mut H) -> Result<()>
1208    where
1209        H: Hasher,
1210    {
1211        let gc_ref = self.try_gc_ref(store.as_context().0)?;
1212        gc_ref.hash(state);
1213        Ok(())
1214    }
1215
1216    /// Cast `self` to a `Rooted<U>`.
1217    ///
1218    /// It is the caller's responsibility to ensure that `self` is actually a
1219    /// `U`. Failure to uphold this invariant will be memory safe but will
1220    /// result in general incorrectness such as panics and wrong results.
1221    pub(crate) fn unchecked_cast<U: GcRef>(self) -> Rooted<U> {
1222        Rooted::from_gc_root_index(self.inner)
1223    }
1224
1225    /// Common implementation of the `WasmTy::store` trait method for all
1226    /// `Rooted<T>`s.
1227    pub(super) fn wasm_ty_store(
1228        self,
1229        store: &mut AutoAssertNoGc<'_>,
1230        ptr: &mut MaybeUninit<ValRaw>,
1231        val_raw: impl Fn(u32) -> ValRaw,
1232    ) -> Result<()> {
1233        let raw = self.inner.expose_gc_ref_to_wasm(store)?;
1234        ptr.write(val_raw(raw.get()));
1235        Ok(())
1236    }
1237
1238    /// Common implementation of the `WasmTy::load` trait method for all
1239    /// `Rooted<T>`s.
1240    pub(super) fn wasm_ty_load(
1241        store: &mut AutoAssertNoGc<'_>,
1242        raw_gc_ref: u32,
1243        from_cloned_gc_ref: impl Fn(&mut AutoAssertNoGc<'_>, VMGcRef) -> Self,
1244    ) -> Self {
1245        debug_assert_ne!(raw_gc_ref, 0);
1246        let gc_ref = VMGcRef::from_raw_u32(raw_gc_ref).expect("non-null");
1247
1248        let gc_ref = match store.optional_gc_store_mut() {
1249            Some(s) => s.clone_gc_ref(&gc_ref),
1250            None => {
1251                // NB: do not force the allocation of a GC heap just because the
1252                // program is using `i31ref`s.
1253                debug_assert!(gc_ref.is_i31());
1254                gc_ref.unchecked_copy()
1255            }
1256        };
1257
1258        from_cloned_gc_ref(store, gc_ref)
1259    }
1260
1261    /// Common implementation of the `WasmTy::store` trait method for all
1262    /// `Option<Rooted<T>>`s.
1263    pub(super) fn wasm_ty_option_store(
1264        me: Option<Self>,
1265        store: &mut AutoAssertNoGc<'_>,
1266        ptr: &mut MaybeUninit<ValRaw>,
1267        val_raw: impl Fn(u32) -> ValRaw,
1268    ) -> Result<()> {
1269        match me {
1270            Some(me) => me.wasm_ty_store(store, ptr, val_raw),
1271            None => {
1272                ptr.write(val_raw(0));
1273                Ok(())
1274            }
1275        }
1276    }
1277
1278    /// Common implementation of the `WasmTy::load` trait method for all
1279    /// `Option<Rooted<T>>`s.
1280    pub(super) fn wasm_ty_option_load(
1281        store: &mut AutoAssertNoGc<'_>,
1282        raw_gc_ref: u32,
1283        from_cloned_gc_ref: impl Fn(&mut AutoAssertNoGc<'_>, VMGcRef) -> Self,
1284    ) -> Option<Self> {
1285        let gc_ref = VMGcRef::from_raw_u32(raw_gc_ref)?;
1286        let gc_ref = store.clone_gc_ref(&gc_ref);
1287        Some(from_cloned_gc_ref(store, gc_ref))
1288    }
1289
1290    pub(crate) fn try_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Result<&'a VMGcRef> {
1291        <Self as RootedGcRefImpl<_>>::try_gc_ref(self, store)
1292    }
1293
1294    pub(crate) fn try_clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Result<VMGcRef> {
1295        <Self as RootedGcRefImpl<_>>::try_clone_gc_ref(self, store)
1296    }
1297}
1298
1299/// Nested rooting scopes.
1300///
1301/// `RootScope` allows the creation or nested rooting scopes for use with
1302/// [`Rooted<T>`][crate::Rooted]. This allows for fine-grained control over how
1303/// long a set of [`Rooted<T>`][crate::Rooted]s are strongly held alive, giving
1304/// gives you the tools necessary to avoid holding onto GC objects longer than
1305/// necessary. `Rooted<T>`s created within a `RootScope` are automatically
1306/// unrooted when the `RootScope` is dropped. For more details on
1307/// [`Rooted<T>`][crate::Rooted] lifetimes and their interaction with rooting
1308/// scopes, see [`Rooted<T>`][crate::Rooted]'s documentation.
1309///
1310/// A `RootScope<C>` wraps a `C: AsContextMut` (that is, anything that
1311/// represents exclusive access to a [`Store`][crate::Store]) and in turn
1312/// implements [`AsContext`][crate::AsContext] and
1313/// [`AsContextMut`][crate::AsContextMut] in terms of its underlying
1314/// `C`. Therefore, `RootScope<C>` can be used anywhere you would use the
1315/// underlying `C`, for example in the [`Global::get`][crate::Global::get]
1316/// method. Any `Rooted<T>`s created by a method that a `RootScope<C>` was
1317/// passed as context to are tied to the `RootScope<C>`'s scope and
1318/// automatically unrooted when the scope is dropped.
1319///
1320/// # Example
1321///
1322/// ```
1323/// # use wasmtime::*;
1324/// # fn _foo() -> Result<()> {
1325/// let mut store = Store::<()>::default();
1326///
1327/// let a: Rooted<_>;
1328/// let b: Rooted<_>;
1329/// let c: Rooted<_>;
1330///
1331/// // Root `a` in the store's scope. It will be rooted for the duration of the
1332/// // store's lifetime.
1333/// a = ExternRef::new(&mut store, 42)?;
1334///
1335/// // `a` is rooted, so we can access its data successfully.
1336/// assert!(a.data(&store).is_ok());
1337///
1338/// {
1339///     let mut scope1 = RootScope::new(&mut store);
1340///
1341///     // Root `b` in `scope1`.
1342///     b = ExternRef::new(&mut scope1, 36)?;
1343///
1344///     // Both `a` and `b` are rooted.
1345///     assert!(a.data(&scope1).is_ok());
1346///     assert!(b.data(&scope1).is_ok());
1347///
1348///     {
1349///         let mut scope2 = RootScope::new(&mut scope1);
1350///
1351///         // Root `c` in `scope2`.
1352///         c = ExternRef::new(&mut scope2, 36)?;
1353///
1354///         // All of `a`, `b`, and `c` are rooted.
1355///         assert!(a.data(&scope2).is_ok());
1356///         assert!(b.data(&scope2).is_ok());
1357///         assert!(c.data(&scope2).is_ok());
1358///
1359///         // Drop `scope2`.
1360///     }
1361///
1362///     // Now `a` and `b` are still rooted, but `c` was unrooted when we dropped
1363///     // `scope2`.
1364///     assert!(a.data(&scope1).is_ok());
1365///     assert!(b.data(&scope1).is_ok());
1366///     assert!(c.data(&scope1).is_err());
1367///
1368///     // Drop `scope1`.
1369/// }
1370///
1371/// // And now only `a` is still rooted. Both `b` and `c` were unrooted when we
1372/// // dropped their respective rooting scopes.
1373/// assert!(a.data(&store).is_ok());
1374/// assert!(b.data(&store).is_err());
1375/// assert!(c.data(&store).is_err());
1376/// # Ok(())
1377/// # }
1378/// ```
1379pub struct RootScope<C>
1380where
1381    C: AsContextMut,
1382{
1383    store: C,
1384    scope: usize,
1385}
1386
1387impl<C> Drop for RootScope<C>
1388where
1389    C: AsContextMut,
1390{
1391    fn drop(&mut self) {
1392        self.store.as_context_mut().0.exit_gc_lifo_scope(self.scope);
1393    }
1394}
1395
1396impl<C> RootScope<C>
1397where
1398    C: AsContextMut,
1399{
1400    // NB: we MUST NOT expose a method like
1401    //
1402    //     pub fn store(&mut self) -> &mut Store { ... }
1403    //
1404    // because callers could do treacherous things like
1405    //
1406    //     let scope1 = RootScope::new(&mut store1);
1407    //     let scope2 = RootScope::new(&mut store2);
1408    //     std::mem::swap(scope1.store(), scope2.store());
1409    //
1410    // and then we would start truncate the store's GC root set's LIFO roots to
1411    // the wrong lengths.
1412    //
1413    // Instead, we just implement `AsContext[Mut]` for `RootScope`.
1414
1415    /// Construct a new scope for rooting GC objects.
1416    ///
1417    /// # Example
1418    ///
1419    /// ```
1420    /// # use wasmtime::*;
1421    /// let mut store = Store::<()>::default();
1422    ///
1423    /// {
1424    ///     let mut scope = RootScope::new(&mut store);
1425    ///
1426    ///     // Temporarily root GC objects in this nested rooting scope...
1427    /// }
1428    /// ```
1429    pub fn new(store: C) -> Self {
1430        let scope = store.as_context().0.gc_roots().enter_lifo_scope();
1431        RootScope { store, scope }
1432    }
1433
1434    fn gc_roots(&mut self) -> &mut RootSet {
1435        self.store.as_context_mut().0.gc_roots_mut()
1436    }
1437
1438    fn lifo_roots(&mut self) -> &mut Vec<LifoRoot> {
1439        &mut self.gc_roots().lifo_roots
1440    }
1441
1442    /// Reserve enough capacity for `additional` GC roots in this scope.
1443    ///
1444    /// # Example
1445    ///
1446    /// ```
1447    /// # use wasmtime::*;
1448    /// let mut store = Store::<()>::default();
1449    ///
1450    /// {
1451    ///     let mut scope = RootScope::new(&mut store);
1452    ///
1453    ///     // Ensure we have enough storage pre-allocated to root five GC
1454    ///     // references inside this scope without any underlying reallocation.
1455    ///     scope.reserve(5);
1456    ///
1457    ///     // ...
1458    /// }
1459    /// ```
1460    pub fn reserve(&mut self, additional: usize) {
1461        self.lifo_roots().reserve(additional);
1462    }
1463}
1464
1465impl<T> AsContext for RootScope<T>
1466where
1467    T: AsContextMut,
1468{
1469    type Data = T::Data;
1470
1471    fn as_context(&self) -> crate::StoreContext<'_, Self::Data> {
1472        self.store.as_context()
1473    }
1474}
1475
1476impl<T> AsContextMut for RootScope<T>
1477where
1478    T: AsContextMut,
1479{
1480    fn as_context_mut(&mut self) -> crate::StoreContextMut<'_, Self::Data> {
1481        self.store.as_context_mut()
1482    }
1483}
1484
1485/// Internal version of `RootScope` that only wraps a `&mut StoreOpaque` rather
1486/// than a whole `impl AsContextMut<Data = T>`.
1487pub(crate) struct OpaqueRootScope<S>
1488where
1489    S: AsStoreOpaque,
1490{
1491    store: S,
1492    scope: usize,
1493}
1494
1495impl<S> Drop for OpaqueRootScope<S>
1496where
1497    S: AsStoreOpaque,
1498{
1499    fn drop(&mut self) {
1500        self.store.as_store_opaque().exit_gc_lifo_scope(self.scope);
1501    }
1502}
1503
1504impl<S> Deref for OpaqueRootScope<S>
1505where
1506    S: AsStoreOpaque,
1507{
1508    type Target = S;
1509
1510    fn deref(&self) -> &Self::Target {
1511        &self.store
1512    }
1513}
1514
1515// XXX: Don't use this `DerefMut` implementation to `mem::{swap,replace}` or
1516// etc... the underlying `StoreOpaque` in a `OpaqueRootScope`! That will result
1517// in truncating the store's GC root set's LIFO roots to the wrong length.
1518//
1519// We don't implement `DerefMut` for `RootScope` for exactly this reason, but
1520// allow it for `OpaqueRootScope` because it is only Wasmtime-internal and not
1521// publicly exported.
1522impl<S> DerefMut for OpaqueRootScope<S>
1523where
1524    S: AsStoreOpaque,
1525{
1526    fn deref_mut(&mut self) -> &mut Self::Target {
1527        &mut self.store
1528    }
1529}
1530
1531impl<S> OpaqueRootScope<S>
1532where
1533    S: AsStoreOpaque,
1534{
1535    pub(crate) fn new(mut store: S) -> Self {
1536        let scope = store.as_store_opaque().gc_roots().enter_lifo_scope();
1537        OpaqueRootScope { store, scope }
1538    }
1539}
1540
1541/// A rooted reference to a garbage-collected `T` with automatic lifetime.
1542///
1543/// An `OwnedRooted<T>` is a strong handle to a garbage-collected `T`,
1544/// preventing its referent (and anything else transitively referenced) from
1545/// being collected by the GC until it is dropped.
1546///
1547/// An `OwnedRooted<T>` keeps its rooted GC object alive at least
1548/// until the `OwnedRooted<T>` itself is dropped. The
1549/// "de-registration" of the root is automatic and is triggered (in a
1550/// deferred way) by the drop of this type.
1551///
1552/// The primary way to create an `OwnedRooted<T>` is to promote a temporary
1553/// `Rooted<T>` into an `OwnedRooted<T>` via its
1554/// [`to_owned_rooted`][crate::Rooted::to_owned_rooted] method.
1555///
1556/// `OwnedRooted<T>` dereferences to its underlying `T`, allowing you to call
1557/// `T`'s methods.
1558///
1559/// # Example
1560///
1561/// ```
1562/// # use wasmtime::*;
1563/// # fn _foo() -> Result<()> {
1564/// let mut store = Store::<Option<OwnedRooted<ExternRef>>>::default();
1565///
1566/// // Create our `OwnedRooted` in a nested scope to avoid rooting it for
1567/// // the duration of the store's lifetime.
1568/// let x = {
1569///     let mut scope = RootScope::new(&mut store);
1570///     let x = ExternRef::new(&mut scope, 1234)?;
1571///     x.to_owned_rooted(&mut scope)?
1572/// };
1573///
1574/// // Place `x` into our store.
1575/// *store.data_mut() = Some(x);
1576///
1577/// // Do a bunch stuff that may or may not access, replace, or take `x`...
1578/// # Ok(())
1579/// # }
1580/// ```
1581pub struct OwnedRooted<T>
1582where
1583    T: GcRef,
1584{
1585    inner: GcRootIndex,
1586    liveness_flag: Arc<()>,
1587    _phantom: marker::PhantomData<T>,
1588}
1589
1590const _: () = {
1591    use crate::{AnyRef, ExternRef};
1592
1593    // NB: these match the C API which should also be updated if this changes.
1594    //
1595    // The size is really "16 + pointer + alignment", which is either
1596    // 20 bytes on some 32-bit platforms or 24 bytes on other 32-bit
1597    // platforms (e.g., riscv32, which adds an extra 4 bytes of
1598    // padding) and 64-bit platforms.
1599    assert!(
1600        mem::size_of::<OwnedRooted<AnyRef>>() >= 16 && mem::size_of::<OwnedRooted<AnyRef>>() <= 24
1601    );
1602    assert!(mem::align_of::<OwnedRooted<AnyRef>>() == mem::align_of::<u64>());
1603    assert!(
1604        mem::size_of::<OwnedRooted<ExternRef>>() >= 16
1605            && mem::size_of::<OwnedRooted<ExternRef>>() <= 24
1606    );
1607    assert!(mem::align_of::<OwnedRooted<ExternRef>>() == mem::align_of::<u64>());
1608};
1609
1610impl<T: GcRef> Debug for OwnedRooted<T> {
1611    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1612        let name = format!("OwnedRooted<{}>", any::type_name::<T>());
1613        f.debug_struct(&name).field("inner", &self.inner).finish()
1614    }
1615}
1616
1617impl<T: GcRef> Deref for OwnedRooted<T> {
1618    type Target = T;
1619
1620    fn deref(&self) -> &Self::Target {
1621        T::transmute_ref(&self.inner)
1622    }
1623}
1624
1625impl<T: GcRef> Clone for OwnedRooted<T> {
1626    fn clone(&self) -> Self {
1627        OwnedRooted {
1628            inner: self.inner,
1629            liveness_flag: self.liveness_flag.clone(),
1630            _phantom: marker::PhantomData,
1631        }
1632    }
1633}
1634
1635impl<T> OwnedRooted<T>
1636where
1637    T: GcRef,
1638{
1639    /// Construct a new owned GC root.
1640    ///
1641    /// `gc_ref` should belong to `store`'s heap; failure to uphold this is
1642    /// memory safe but will result in general failures down the line such as
1643    /// panics or incorrect results.
1644    ///
1645    /// `gc_ref` should be a GC reference pointing to an instance of the GC type
1646    /// that `T` represents. Failure to uphold this invariant is memory safe but
1647    /// will result in general incorrectness such as panics and wrong results.
1648    pub(crate) fn new(
1649        store: &mut AutoAssertNoGc<'_>,
1650        gc_ref: VMGcRef,
1651    ) -> Result<Self, OutOfMemory> {
1652        // We always have the opportunity to trim and unregister stale
1653        // owned roots whenever we have a mut borrow to the store. We
1654        // take the opportunity to do so here to avoid tying growth of
1655        // the root-set to the GC frequency -- it is much cheaper to
1656        // eagerly trim these roots. Note that the trimming keeps a
1657        // "high water mark" that grows exponentially, so we have
1658        // amortized constant time even though an individual trim
1659        // takes time linear in the number of roots.
1660        store.trim_gc_liveness_flags(false);
1661
1662        let roots = store.gc_roots_mut();
1663        let id = roots.owned_rooted.alloc(gc_ref)?;
1664        let liveness_flag = Arc::new(());
1665        roots
1666            .liveness_flags
1667            .push((Arc::downgrade(&liveness_flag), id));
1668        Ok(OwnedRooted {
1669            inner: GcRootIndex {
1670                store_id: store.id(),
1671                generation: 0,
1672                index: PackedIndex::new_owned(id),
1673            },
1674            liveness_flag,
1675            _phantom: marker::PhantomData,
1676        })
1677    }
1678
1679    #[inline]
1680    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1681        debug_assert!(self.inner.index.is_owned());
1682        self.inner.comes_from_same_store(store)
1683    }
1684
1685    /// Clone this `OwnedRooted<T>` into a `Rooted<T>`.
1686    ///
1687    /// This operation does not consume or unroot this `OwnedRooted<T>`.
1688    ///
1689    /// The underlying GC object is re-rooted in the given context's scope. The
1690    /// resulting `Rooted<T>` is only valid during the given context's
1691    /// scope. See the [`Rooted<T>`][crate::Rooted] documentation for more
1692    /// details on rooting scopes.
1693    ///
1694    /// This operation does not consume or unroot this `OwnedRooted<T>`.
1695    ///
1696    /// # Panics
1697    ///
1698    /// Panics if this object is not associated with the given context's store.
1699    ///
1700    /// # Example
1701    ///
1702    /// ```
1703    /// # use wasmtime::*;
1704    /// # fn _foo() -> Result<()> {
1705    /// let mut store = Store::<()>::default();
1706    ///
1707    /// let root1: Rooted<_>;
1708    ///
1709    /// let owned = {
1710    ///     let mut scope = RootScope::new(&mut store);
1711    ///     root1 = ExternRef::new(&mut scope, 1234)?;
1712    ///     root1.to_owned_rooted(&mut scope)?
1713    /// };
1714    ///
1715    /// // `root1` is no longer accessible because it was unrooted when `scope`
1716    /// // was dropped.
1717    /// assert!(root1.data(&store).is_err());
1718    ///
1719    /// // But we can re-root `owned` into this scope.
1720    /// let root2 = owned.to_rooted(&mut store);
1721    /// assert!(root2.data(&store).is_ok());
1722    /// # Ok(())
1723    /// # }
1724    /// ```
1725    pub fn to_rooted(&self, mut context: impl AsContextMut) -> Rooted<T> {
1726        self._to_rooted(context.as_context_mut().0)
1727    }
1728
1729    pub(crate) fn _to_rooted(&self, store: &mut StoreOpaque) -> Rooted<T> {
1730        assert!(
1731            self.comes_from_same_store(store),
1732            "object used with wrong store"
1733        );
1734        let mut store = AutoAssertNoGc::new(store);
1735        let gc_ref = self.clone_gc_ref(&mut store).unwrap();
1736        Rooted::new(&mut store, gc_ref)
1737    }
1738
1739    /// Are these two GC roots referencing the same underlying GC object?
1740    ///
1741    /// This function will return `true` even when `a` and `b` are different GC
1742    /// roots (for example because they were rooted in different scopes) if they
1743    /// are rooting the same underlying GC object.
1744    ///
1745    /// Because this method takes any `impl RootedGcRef<T>` arguments, it can be
1746    /// used to compare, for example, a `Rooted<T>` and an `OwnedRooted<T>`.
1747    ///
1748    /// # Panics
1749    ///
1750    /// Panics if either `a` or `b` is not associated with the given `store`.
1751    ///
1752    /// # Example
1753    ///
1754    /// ```
1755    /// # use wasmtime::*;
1756    /// # fn foo() -> Result<()> {
1757    /// let mut store = Store::<()>::default();
1758    ///
1759    /// let a;
1760    /// let b;
1761    /// let x;
1762    ///
1763    /// {
1764    ///     let mut scope = RootScope::new(&mut store);
1765    ///
1766    ///     a = ExternRef::new(&mut scope, "hello")?.to_owned_rooted(&mut scope)?;
1767    ///     b = a.clone();
1768    ///
1769    ///     // `a` and `b` are rooting the same object.
1770    ///     assert!(OwnedRooted::ref_eq(&scope, &a, &b)?);
1771    ///
1772    ///     // `c` is a different GC root, is in a different scope, and is a
1773    ///     // `Rooted<T>` instead of a `OwnedRooted<T>`, but is still rooting
1774    ///     // the same object.
1775    ///     let c = a.to_rooted(&mut scope);
1776    ///     assert!(OwnedRooted::ref_eq(&scope, &a, &c)?);
1777    ///
1778    ///     x = ExternRef::new(&mut scope, "goodbye")?.to_owned_rooted(&mut scope)?;
1779    ///
1780    ///     // `a` and `x` are rooting different objects.
1781    ///     assert!(!OwnedRooted::ref_eq(&scope, &a, &x)?);
1782    /// }
1783    /// # Ok(())
1784    /// # }
1785    /// ```
1786    pub fn ref_eq(
1787        store: impl AsContext,
1788        a: &impl RootedGcRef<T>,
1789        b: &impl RootedGcRef<T>,
1790    ) -> Result<bool> {
1791        Rooted::ref_eq(store, a, b)
1792    }
1793
1794    /// Hash this root.
1795    ///
1796    /// Note that, similar to `Rooted::rooted_eq`, this only operates on the
1797    /// root and *not* the underlying GC reference. That means that two
1798    /// different rootings of the same object will hash to different values
1799    /// (modulo hash collisions). If this is undesirable, use the
1800    /// [`ref_hash`][crate::OwnedRooted::ref_hash] method instead.
1801    pub fn rooted_hash<H>(&self, state: &mut H)
1802    where
1803        H: Hasher,
1804    {
1805        self.inner.hash(state);
1806    }
1807
1808    /// Hash the underlying rooted object reference.
1809    ///
1810    /// Note that, similar to `Rooted::ref_eq`, and operates on the underlying
1811    /// rooted GC object reference, not the root. That means that two
1812    /// *different* rootings of the same object will hash to the *same*
1813    /// value. If this is undesirable, use the
1814    /// [`rooted_hash`][crate::Rooted::rooted_hash] method instead.
1815    pub fn ref_hash<H>(&self, store: impl AsContext, state: &mut H)
1816    where
1817        H: Hasher,
1818    {
1819        let gc_ref = self
1820            .get_gc_ref(store.as_context().0)
1821            .expect("OwnedRooted's get_gc_ref is infallible");
1822        gc_ref.hash(state);
1823    }
1824
1825    /// Cast `self` to an `OwnedRooted<U>`.
1826    ///
1827    /// It is the caller's responsibility to ensure that `self` is actually a
1828    /// `U`. Failure to uphold this invariant will be memory safe but will
1829    /// result in general incorrectness such as panics and wrong results.
1830    pub(crate) fn unchecked_cast<U: GcRef>(self) -> OwnedRooted<U> {
1831        OwnedRooted {
1832            inner: self.inner,
1833            liveness_flag: self.liveness_flag,
1834            _phantom: core::marker::PhantomData,
1835        }
1836    }
1837
1838    /// Common implementation of the `WasmTy::store` trait method for all
1839    /// `OwnedRooted<T>`s.
1840    pub(super) fn wasm_ty_store(
1841        self,
1842        store: &mut AutoAssertNoGc<'_>,
1843        ptr: &mut MaybeUninit<ValRaw>,
1844        val_raw: impl Fn(u32) -> ValRaw,
1845    ) -> Result<()> {
1846        let raw = self.inner.expose_gc_ref_to_wasm(store)?;
1847        ptr.write(val_raw(raw.get()));
1848        Ok(())
1849    }
1850
1851    /// Common implementation of the `WasmTy::load` trait method for all
1852    /// `OwnedRooted<T>`s.
1853    pub(super) fn wasm_ty_load(
1854        store: &mut AutoAssertNoGc<'_>,
1855        raw_gc_ref: u32,
1856        from_cloned_gc_ref: impl Fn(&mut AutoAssertNoGc<'_>, VMGcRef) -> Rooted<T>,
1857    ) -> Self {
1858        debug_assert_ne!(raw_gc_ref, 0);
1859        let gc_ref = VMGcRef::from_raw_u32(raw_gc_ref).expect("non-null");
1860        let gc_ref = store.clone_gc_ref(&gc_ref);
1861        RootSet::with_lifo_scope(store, |store| {
1862            let rooted = from_cloned_gc_ref(store, gc_ref);
1863            rooted._to_owned_rooted(store).expect("rooted is in scope")
1864        })
1865    }
1866
1867    /// Common implementation of the `WasmTy::store` trait method for all
1868    /// `Option<OwnedRooted<T>>`s.
1869    pub(super) fn wasm_ty_option_store(
1870        me: Option<Self>,
1871        store: &mut AutoAssertNoGc<'_>,
1872        ptr: &mut MaybeUninit<ValRaw>,
1873        val_raw: impl Fn(u32) -> ValRaw,
1874    ) -> Result<()> {
1875        match me {
1876            Some(me) => me.wasm_ty_store(store, ptr, val_raw),
1877            None => {
1878                ptr.write(val_raw(0));
1879                Ok(())
1880            }
1881        }
1882    }
1883
1884    /// Common implementation of the `WasmTy::load` trait method for all
1885    /// `Option<OwnedRooted<T>>`s.
1886    pub(super) fn wasm_ty_option_load(
1887        store: &mut AutoAssertNoGc<'_>,
1888        raw_gc_ref: u32,
1889        from_cloned_gc_ref: impl Fn(&mut AutoAssertNoGc<'_>, VMGcRef) -> Rooted<T>,
1890    ) -> Option<Self> {
1891        let gc_ref = VMGcRef::from_raw_u32(raw_gc_ref)?;
1892        let gc_ref = store.clone_gc_ref(&gc_ref);
1893        RootSet::with_lifo_scope(store, |store| {
1894            let rooted = from_cloned_gc_ref(store, gc_ref);
1895            Some(rooted._to_owned_rooted(store).expect("rooted is in scope"))
1896        })
1897    }
1898
1899    #[doc(hidden)]
1900    pub fn into_parts_for_c_api(self) -> (NonZeroU64, u32, u32, *const ()) {
1901        (
1902            self.inner.store_id.as_raw(),
1903            self.inner.generation,
1904            self.inner.index.0,
1905            Arc::into_raw(self.liveness_flag),
1906        )
1907    }
1908
1909    #[doc(hidden)]
1910    pub unsafe fn from_borrowed_raw_parts_for_c_api(
1911        a: NonZeroU64,
1912        b: u32,
1913        c: u32,
1914        d: *const (),
1915    ) -> OwnedRooted<T> {
1916        // We are given a *borrow* of the Arc. This is a little
1917        // sketchy because `Arc::from_raw()` takes *ownership* of the
1918        // passed-in pointer, so we need to clone then forget that
1919        // original.
1920        let liveness_flag = {
1921            let original = unsafe { Arc::from_raw(d) };
1922            let clone = original.clone();
1923            core::mem::forget(original);
1924            clone
1925        };
1926        OwnedRooted {
1927            inner: GcRootIndex {
1928                store_id: StoreId::from_raw(a),
1929                generation: b,
1930                index: PackedIndex(c),
1931            },
1932            liveness_flag,
1933            _phantom: marker::PhantomData,
1934        }
1935    }
1936
1937    #[doc(hidden)]
1938    pub unsafe fn from_owned_raw_parts_for_c_api(
1939        a: NonZeroU64,
1940        b: u32,
1941        c: u32,
1942        d: *const (),
1943    ) -> OwnedRooted<T> {
1944        let liveness_flag = unsafe { Arc::from_raw(d) };
1945        OwnedRooted {
1946            inner: GcRootIndex {
1947                store_id: StoreId::from_raw(a),
1948                generation: b,
1949                index: PackedIndex(c),
1950            },
1951            liveness_flag,
1952            _phantom: marker::PhantomData,
1953        }
1954    }
1955}
1956
1957impl<T: GcRef> RootedGcRefImpl<T> for OwnedRooted<T> {
1958    fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> {
1959        assert!(
1960            self.comes_from_same_store(store),
1961            "object used with wrong store"
1962        );
1963
1964        let id = self.inner.index.as_owned().unwrap();
1965        store.gc_roots().owned_rooted.get(id)
1966    }
1967}
1968
1969#[cfg(test)]
1970mod tests {
1971    use crate::ExternRef;
1972
1973    use super::*;
1974
1975    #[test]
1976    fn sizes() {
1977        // Try to keep tabs on the size of these things. Don't want them growing
1978        // unintentionally.
1979        assert_eq!(std::mem::size_of::<Rooted<ExternRef>>(), 16);
1980        assert!(std::mem::size_of::<OwnedRooted<ExternRef>>() <= 24);
1981    }
1982}