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