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