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::prelude::*; 106 use crate::runtime::vm::{GcRootsList, GcStore, VMGcRef}; 107 use crate::{ 108 store::{AutoAssertNoGc, StoreId, StoreOpaque}, 109 AsContext, AsContextMut, GcRef, Result, RootedGcRef, 110 }; 111 use core::any; 112 use core::marker; 113 use core::mem; 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.unwrap_gc_store_mut().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.gc_store_mut()?.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>() == 8); 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 doesn't check that the raw GC 213 /// ref is only used during the scope of an `AutoAssertNoGc`. 214 /// 215 /// It is up to callers to avoid triggering a GC while holding onto the 216 /// resulting raw `VMGcRef`. Failure to uphold this invariant is memory safe 217 /// but will lead to general incorrectness such as panics and wrong results. 218 pub(crate) fn unchecked_get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> { 219 assert!( 220 self.comes_from_same_store(store), 221 "object used with wrong store" 222 ); 223 if let Some(index) = self.index.as_lifo() { 224 let entry = store.gc_roots().lifo_roots.get(index)?; 225 if entry.generation == self.generation { 226 Some(&entry.gc_ref) 227 } else { 228 None 229 } 230 } else if let Some(id) = self.index.as_manual() { 231 let gc_ref = store.gc_roots().manually_rooted.get(id); 232 debug_assert!(gc_ref.is_some()); 233 gc_ref 234 } else { 235 unreachable!() 236 } 237 } 238 239 /// Same as `RootedGcRefImpl::get_gc_ref` but not associated with any 240 /// particular `T: GcRef`. 241 pub(crate) fn get_gc_ref<'a>(&self, store: &'a AutoAssertNoGc<'_>) -> Option<&'a VMGcRef> { 242 self.unchecked_get_gc_ref(store) 243 } 244 245 /// Same as `unchecked_get_gc_ref` but returns an error instead of `None` if 246 /// the GC reference has been unrooted. 247 /// 248 /// # Panics 249 /// 250 /// Panics if `self` is not associated with the given store. 251 pub(crate) fn unchecked_try_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Result<&'a VMGcRef> { 252 self.unchecked_get_gc_ref(store).ok_or_else(|| { 253 anyhow!("attempted to use a garbage-collected object that has been unrooted") 254 }) 255 } 256 257 /// Same as `get_gc_ref` but returns an error instead of `None` if the GC 258 /// reference has been unrooted. 259 pub(crate) fn try_gc_ref<'a>(&self, store: &'a AutoAssertNoGc<'_>) -> Result<&'a VMGcRef> { 260 self.get_gc_ref(store).ok_or_else(|| { 261 anyhow!("attempted to use a garbage-collected object that has been unrooted") 262 }) 263 } 264 265 /// Same as `RootedGcRefImpl::clone_gc_ref` but not associated with any 266 /// particular `T: GcRef`. 267 pub(crate) fn try_clone_gc_ref(&self, store: &mut AutoAssertNoGc<'_>) -> Result<VMGcRef> { 268 let gc_ref = self.try_gc_ref(store)?.unchecked_copy(); 269 Ok(store.gc_store_mut()?.clone_gc_ref(&gc_ref)) 270 } 271 } 272 273 /// This is a bit-packed version of 274 /// 275 /// ```ignore 276 /// enema { 277 /// Lifo(usize), 278 /// Manual(SlabId), 279 /// } 280 /// ``` 281 /// 282 /// where the high bit is the discriminant and the lower 31 bits are the 283 /// payload. 284 #[derive(Clone, Copy, PartialEq, Eq, Hash)] 285 #[repr(transparent)] 286 struct PackedIndex(u32); 287 288 impl Debug for PackedIndex { 289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 290 if let Some(index) = self.as_lifo() { 291 f.debug_tuple("PackedIndex::Lifo").field(&index).finish() 292 } else if let Some(id) = self.as_manual() { 293 f.debug_tuple("PackedIndex::Manual").field(&id).finish() 294 } else { 295 unreachable!() 296 } 297 } 298 } 299 300 impl PackedIndex { 301 const DISCRIMINANT_MASK: u32 = 0b1 << 31; 302 const LIFO_DISCRIMINANT: u32 = 0b0 << 31; 303 const MANUAL_DISCRIMINANT: u32 = 0b1 << 31; 304 const PAYLOAD_MASK: u32 = !Self::DISCRIMINANT_MASK; 305 306 fn new_lifo(index: usize) -> PackedIndex { 307 let index32 = u32::try_from(index).unwrap(); 308 assert_eq!(index32 & Self::DISCRIMINANT_MASK, 0); 309 let packed = PackedIndex(Self::LIFO_DISCRIMINANT | index32); 310 debug_assert!(packed.is_lifo()); 311 debug_assert_eq!(packed.as_lifo(), Some(index)); 312 debug_assert!(!packed.is_manual()); 313 debug_assert!(packed.as_manual().is_none()); 314 packed 315 } 316 317 fn new_manual(id: SlabId) -> PackedIndex { 318 let raw = id.into_raw(); 319 assert_eq!(raw & Self::DISCRIMINANT_MASK, 0); 320 let packed = PackedIndex(Self::MANUAL_DISCRIMINANT | raw); 321 debug_assert!(packed.is_manual()); 322 debug_assert_eq!(packed.as_manual(), Some(id)); 323 debug_assert!(!packed.is_lifo()); 324 debug_assert!(packed.as_lifo().is_none()); 325 packed 326 } 327 328 fn discriminant(&self) -> u32 { 329 self.0 & Self::DISCRIMINANT_MASK 330 } 331 332 fn is_lifo(&self) -> bool { 333 self.discriminant() == Self::LIFO_DISCRIMINANT 334 } 335 336 fn is_manual(&self) -> bool { 337 self.discriminant() == Self::MANUAL_DISCRIMINANT 338 } 339 340 fn payload(&self) -> u32 { 341 self.0 & Self::PAYLOAD_MASK 342 } 343 344 fn as_lifo(&self) -> Option<usize> { 345 if self.is_lifo() { 346 Some(usize::try_from(self.payload()).unwrap()) 347 } else { 348 None 349 } 350 } 351 352 fn as_manual(&self) -> Option<SlabId> { 353 if self.is_manual() { 354 Some(SlabId::from_raw(self.payload())) 355 } else { 356 None 357 } 358 } 359 } 360 361 /// The set of all embedder-API GC roots in a single store/heap. 362 #[derive(Debug, Default)] 363 pub(crate) struct RootSet { 364 /// GC roots with arbitrary lifetime that are manually rooted and unrooted, 365 /// for use with `ManuallyRooted<T>`. 366 manually_rooted: Slab<VMGcRef>, 367 368 /// Strictly LIFO-ordered GC roots, for use with `RootScope` and 369 /// `Rooted<T>`. 370 lifo_roots: Vec<LifoRoot>, 371 372 /// Generation counter for entries to prevent ABA bugs with `RootScope` and 373 /// `Rooted<T>`. 374 lifo_generation: u32, 375 } 376 377 #[derive(Debug)] 378 struct LifoRoot { 379 generation: u32, 380 gc_ref: VMGcRef, 381 } 382 383 impl RootSet { 384 pub(crate) fn trace_roots(&mut self, gc_roots_list: &mut GcRootsList) { 385 log::trace!("Begin trace user LIFO roots"); 386 for root in &mut self.lifo_roots { 387 unsafe { 388 gc_roots_list.add_root((&mut root.gc_ref).into()); 389 } 390 } 391 log::trace!("End trace user LIFO roots"); 392 393 log::trace!("Begin trace user manual roots"); 394 for (_id, root) in self.manually_rooted.iter_mut() { 395 unsafe { 396 gc_roots_list.add_root(root.into()); 397 } 398 } 399 log::trace!("End trace user manual roots"); 400 } 401 402 /// Enter a LIFO rooting scope. 403 /// 404 /// Returns an integer that should be passed unmodified to `exit_lifo_scope` 405 /// when the scope is finished. 406 /// 407 /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order. 408 #[inline] 409 pub(crate) fn enter_lifo_scope(&self) -> usize { 410 self.lifo_roots.len() 411 } 412 413 /// Exit a LIFO rooting scope. 414 /// 415 /// The `scope` argument must be the result of the corresponding 416 /// `enter_lifo_scope` call. 417 /// 418 /// Calls to `{enter,exit}_lifo_scope` must happen in a strict LIFO order. 419 #[inline] 420 pub(crate) fn exit_lifo_scope(&mut self, gc_store: Option<&mut GcStore>, scope: usize) { 421 debug_assert!(self.lifo_roots.len() >= scope); 422 423 // If we actually have roots to unroot, call an out-of-line slow path. 424 if self.lifo_roots.len() > scope { 425 self.exit_lifo_scope_slow(gc_store, scope); 426 } 427 } 428 429 #[inline(never)] 430 #[cold] 431 fn exit_lifo_scope_slow(&mut self, mut gc_store: Option<&mut GcStore>, scope: usize) { 432 self.lifo_generation += 1; 433 434 // TODO: In the case where we have a tracing GC that doesn't need to 435 // drop barriers, this should really be: 436 // 437 // self.lifo_roots.truncate(scope); 438 439 let mut lifo_roots = mem::take(&mut self.lifo_roots); 440 for root in lifo_roots.drain(scope..) { 441 // Only drop the GC reference if we actually have a GC store. How 442 // can we have a GC reference but not a GC store? If we've only 443 // create `i31refs`, we never force a GC store's allocation. This is 444 // fine because `i31ref`s never need drop barriers. 445 if let Some(gc_store) = &mut gc_store { 446 gc_store.drop_gc_ref(root.gc_ref); 447 } 448 } 449 self.lifo_roots = lifo_roots; 450 } 451 452 pub(crate) fn with_lifo_scope<S, T>(store: &mut S, f: impl FnOnce(&mut S) -> T) -> T 453 where 454 S: DerefMut<Target = StoreOpaque>, 455 { 456 let scope = store.gc_roots().enter_lifo_scope(); 457 let ret = f(store); 458 store.exit_gc_lifo_scope(scope); 459 ret 460 } 461 462 pub(crate) fn push_lifo_root(&mut self, store_id: StoreId, gc_ref: VMGcRef) -> GcRootIndex { 463 let generation = self.lifo_generation; 464 let index = self.lifo_roots.len(); 465 let index = PackedIndex::new_lifo(index); 466 self.lifo_roots.push(LifoRoot { generation, gc_ref }); 467 GcRootIndex { 468 store_id, 469 generation, 470 index, 471 } 472 } 473 } 474 475 /// A scoped, rooted reference to a garbage-collected `T`. 476 /// 477 /// A `Rooted<T>` is a strong handle to a garbage-collected `T`, preventing its 478 /// referent (and anything else transitively referenced) from being collected by 479 /// the GC during the scope within which this `Rooted<T>` was created. 480 /// 481 /// When the context exits this `Rooted<T>`'s scope, the underlying GC object is 482 /// automatically unrooted and any further attempts to use access the underlying 483 /// object will return errors or otherwise fail. 484 /// 485 /// `Rooted<T>` dereferences to its underlying `T`, allowing you to call `T`'s 486 /// methods. 487 /// 488 /// # Example 489 /// 490 /// ``` 491 /// # use wasmtime::*; 492 /// # fn _foo() -> Result<()> { 493 /// let mut store = Store::<()>::default(); 494 /// 495 /// // Allocating a GC object returns a `Rooted<T>`. 496 /// let hello: Rooted<ExternRef> = ExternRef::new(&mut store, "hello")?; 497 /// 498 /// // Because `Rooted<T>` derefs to `T`, we can call `T` methods on a 499 /// // `Rooted<T>`. For example, we can call the `ExternRef::data` method when we 500 /// // have a `Rooted<ExternRef>`. 501 /// let data = hello 502 /// .data(&store)? 503 /// .downcast_ref::<&str>() 504 /// .ok_or_else(|| Error::msg("not a str"))?; 505 /// assert_eq!(*data, "hello"); 506 /// 507 /// // A `Rooted<T>` roots its underlying GC object for the duration of the 508 /// // scope of the store/caller/context that was passed to the method that created 509 /// // it. If we only want to keep a GC reference rooted and alive temporarily, we 510 /// // can introduce new scopes with `RootScope`. 511 /// { 512 /// let mut scope = RootScope::new(&mut store); 513 /// 514 /// // This `Rooted<T>` is automatically unrooted after `scope` is dropped, 515 /// // allowing the collector to reclaim its GC object in the next GC. 516 /// let scoped_ref = ExternRef::new(&mut scope, "goodbye"); 517 /// } 518 /// 519 /// let module = Module::new(store.engine(), r#" 520 /// (module 521 /// (global (export "global") (mut externref) (ref.null extern)) 522 /// (table (export "table") 10 externref) 523 /// (func (export "func") (param externref) (result externref) 524 /// local.get 0 525 /// ) 526 /// ) 527 /// "#)?; 528 /// let instance = Instance::new(&mut store, &module, &[])?; 529 /// 530 /// // GC references returned from calls into Wasm also return (optional, if the 531 /// // Wasm type is nullable) `Rooted<T>`s. 532 /// let result: Option<Rooted<_>> = instance 533 /// .get_typed_func::<Option<Rooted<ExternRef>>, Option<Rooted<ExternRef>>>(&mut store, "func")? 534 /// .call(&mut store, Some(hello))?; 535 /// 536 /// // Similarly, getting a GC reference from a Wasm instance's exported global 537 /// // or table yields a `Rooted<T>`. 538 /// 539 /// let global = instance 540 /// .get_global(&mut store, "global") 541 /// .ok_or_else(|| Error::msg("missing `global` export"))?; 542 /// let global_val = global.get(&mut store); 543 /// let global_ref: Option<&Rooted<_>> = global_val 544 /// .externref() 545 /// .ok_or_else(|| Error::msg("not an externref"))?; 546 /// 547 /// let table = instance.get_table(&mut store, "table").unwrap(); 548 /// let table_elem = table 549 /// .get(&mut store, 3) 550 /// .ok_or_else(|| Error::msg("table out of bounds"))?; 551 /// let table_elem_ref: Option<&Rooted<_>> = table_elem 552 /// .as_extern() 553 /// .ok_or_else(|| Error::msg("not an externref"))?; 554 /// # Ok(()) 555 /// # } 556 /// ``` 557 /// 558 /// # Differences Between `Rooted<T>` and `ManuallyRooted<T>` 559 /// 560 /// While `Rooted<T>` is automatically unrooted when its scope is exited, this 561 /// means that `Rooted<T>` is only valid for strictly last-in-first-out (LIFO, 562 /// aka stack order) lifetimes. This is in contrast to 563 /// [`ManuallyRooted<T>`][crate::ManuallyRooted], which supports rooting GC 564 /// objects for arbitrary lifetimes, but requires manual unrooting. 565 /// 566 /// | Type | Supported Lifetimes | Unrooting | 567 /// |----------------------------------------------|-----------------------------|-----------| 568 /// | [`Rooted<T>`][crate::Rooted] | Strictly LIFO / stack order | Automatic | 569 /// | [`ManuallyRooted<T>`][crate::ManuallyRooted] | Arbitrary | Manual | 570 /// 571 /// `Rooted<T>` should suffice for most use cases, and provides better 572 /// ergonomics, but `ManuallyRooted<T>` exists as a fully-general escape hatch. 573 /// 574 /// # Scopes 575 /// 576 /// Wasmtime automatically creates two kinds of scopes: 577 /// 578 /// 1. A [`Store`][crate::Store] is the outermost rooting scope. Creating a 579 /// `Root<T>` directly inside a `Store` permanently roots the underlying 580 /// object, similar to dropping a 581 /// [`ManuallyRooted<T>`][crate::ManuallyRooted] without unrooting it. 582 /// 583 /// 2. A [`Caller`][crate::Caller] provides a rooting scope for the duration of 584 /// a call from Wasm into a host function. Any objects rooted in a `Caller` 585 /// will be unrooted after the host function returns. Note that there can be 586 /// nested `Caller` scopes in the case where Wasm calls a host function, 587 /// creating the first `Caller` and its rooting scope , and then the host 588 /// function calls a Wasm function which then calls another host function, 589 /// creating a second `Caller` and a second rooting scope. This nesting can 590 /// be arbitrarily deep. 591 /// 592 /// Additionally, if you would like to define finer-grained rooting scopes, 593 /// Wasmtime provides the [`RootScope`][crate::RootScope] type. 594 /// 595 /// Scopes are always nested in a last-in-first-out (LIFO) order. An outer scope 596 /// is never exited (and the `Rooted<T>`s defined within it are never 597 /// automatically unrooted) while an inner scope is still active. All inner 598 /// scopes are exited before their outer scopes. 599 /// 600 /// The following diagram illustrates various rooting scopes over time, how they 601 /// nest, and when their `Rooted<T>`s are automatically unrooted: 602 /// 603 /// ```text 604 /// ----- new Store 605 /// | 606 /// | 607 /// | let a: Rooted<T> = ...; 608 /// | 609 /// | 610 /// | ----- call into Wasm 611 /// | | 612 /// | | 613 /// | | ----- Wasm calls host function F 614 /// | | | 615 /// | | | 616 /// | | | let b: Rooted<T> = ...; 617 /// | | | 618 /// | | | 619 /// | | | ----- F calls into Wasm 620 /// | | | | 621 /// | | | | 622 /// | | | | ----- Wasm call host function G 623 /// | | | | | 624 /// | | | | | 625 /// | | | | | let c: Rooted<T> = ...; 626 /// | | | | | 627 /// | | | | | 628 /// | | | | ----- return to Wasm from host function G (unroots `c`) 629 /// | | | | 630 /// | | | | 631 /// | | | ----- Wasm returns to F 632 /// | | | 633 /// | | | 634 /// | | ----- return from host function F (unroots `b`) 635 /// | | 636 /// | | 637 /// | ----- return from Wasm 638 /// | 639 /// | 640 /// | ----- let scope1 = RootScope::new(...); 641 /// | | 642 /// | | 643 /// | | let d: Rooted<T> = ...; 644 /// | | 645 /// | | 646 /// | | ----- let scope2 = RootScope::new(...); 647 /// | | | 648 /// | | | 649 /// | | | let e: Rooted<T> = ...; 650 /// | | | 651 /// | | | 652 /// | | ----- drop `scope2` (unroots `e`) 653 /// | | 654 /// | | 655 /// | ----- drop `scope1` (unroots `d`) 656 /// | 657 /// | 658 /// ----- drop Store (unroots `a`) 659 /// ``` 660 /// 661 /// A `Rooted<T>` can be used successfully as long as it is still rooted so, in 662 /// the above diagram, `d` is valid inside `scope2` because `scope2` is wholly 663 /// contained within the scope `d` was rooted within (`scope1`). 664 /// 665 /// See also the documentation for [`RootScope`][crate::RootScope]. 666 #[repr(transparent)] 667 pub struct Rooted<T: GcRef> { 668 inner: GcRootIndex, 669 _phantom: marker::PhantomData<T>, 670 } 671 672 impl<T: GcRef> Clone for Rooted<T> { 673 fn clone(&self) -> Self { 674 Rooted { 675 inner: self.inner, 676 _phantom: marker::PhantomData, 677 } 678 } 679 } 680 681 impl<T: GcRef> Copy for Rooted<T> {} 682 683 impl<T: GcRef> Debug for Rooted<T> { 684 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 685 let name = format!("Rooted<{}>", any::type_name::<T>()); 686 f.debug_struct(&name).field("inner", &self.inner).finish() 687 } 688 } 689 690 impl<T: GcRef> RootedGcRefImpl<T> for Rooted<T> { 691 fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> { 692 assert!( 693 self.comes_from_same_store(store), 694 "object used with wrong store" 695 ); 696 let index = self.inner.index.as_lifo().unwrap(); 697 let entry = store.gc_roots().lifo_roots.get(index)?; 698 if entry.generation == self.inner.generation { 699 Some(&entry.gc_ref) 700 } else { 701 None 702 } 703 } 704 } 705 706 impl<T: GcRef> Deref for Rooted<T> { 707 type Target = T; 708 709 fn deref(&self) -> &Self::Target { 710 T::transmute_ref(&self.inner) 711 } 712 } 713 714 impl<T: GcRef> Rooted<T> { 715 /// Push the given `VMGcRef` onto our LIFO root set. 716 /// 717 /// `gc_ref` should belong to `store`'s heap; failure to uphold this is 718 /// memory safe but will result in general failures down the line such as 719 /// panics or incorrect results. 720 /// 721 /// `gc_ref` should be a GC reference pointing to an instance of the GC type 722 /// that `T` represents. Failure to uphold this invariant is memory safe but 723 /// will result in general incorrectness such as panics and wrong results. 724 pub(crate) fn new(store: &mut AutoAssertNoGc<'_>, gc_ref: VMGcRef) -> Rooted<T> { 725 let id = store.id(); 726 let roots = store.gc_roots_mut(); 727 let inner = roots.push_lifo_root(id, gc_ref); 728 Rooted { 729 inner, 730 _phantom: marker::PhantomData, 731 } 732 } 733 734 /// Create a new `Rooted<T>` from a `GcRootIndex`. 735 /// 736 /// Note that `Rooted::from_gc_root_index(my_rooted.index)` is not 737 /// necessarily an identity funciton, as it allows changing the `T` type 738 /// parameter. 739 /// 740 /// The given index should be a LIFO index of a GC reference pointing to an 741 /// instance of the GC type that `T` represents. Failure to uphold this 742 /// invariant is memory safe but will result in general incorrectness such 743 /// as panics and wrong results. 744 pub(crate) fn from_gc_root_index(inner: GcRootIndex) -> Rooted<T> { 745 debug_assert!(inner.index.is_lifo()); 746 Rooted { 747 inner, 748 _phantom: marker::PhantomData, 749 } 750 } 751 752 #[inline] 753 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool { 754 debug_assert!(self.inner.index.is_lifo()); 755 self.inner.comes_from_same_store(store) 756 } 757 758 /// Create a [`ManuallyRooted<T>`][crate::ManuallyRooted] holding onto the 759 /// same GC object as `self`. 760 /// 761 /// Returns `None` if `self` is used outside of its scope and has therefore 762 /// been unrooted. 763 /// 764 /// This does not unroot `self`, and `self` remains valid until its 765 /// associated scope is exited. 766 /// 767 /// # Panics 768 /// 769 /// Panics if this object is not associate with the given store. 770 /// 771 /// # Example 772 /// 773 /// ``` 774 /// # use wasmtime::*; 775 /// # fn _foo() -> Result<()> { 776 /// let mut store = Store::<()>::default(); 777 /// 778 /// let y: ManuallyRooted<_> = { 779 /// // Create a nested rooting scope. 780 /// let mut scope = RootScope::new(&mut store); 781 /// 782 /// // `x` is only rooted within this nested scope. 783 /// let x: Rooted<_> = ExternRef::new(&mut scope, "hello!")?; 784 /// 785 /// // Extend `x`'s rooting past its scope's lifetime by converting it 786 /// // to a `ManuallyRooted`. 787 /// x.to_manually_rooted(&mut scope)? 788 /// }; 789 /// 790 /// // Now we can still access the reference outside the scope it was 791 /// // originally defined within. 792 /// let data = y.data(&store)?; 793 /// let data = data.downcast_ref::<&str>().unwrap(); 794 /// assert_eq!(*data, "hello!"); 795 /// 796 /// // But we have to manually unroot `y`. 797 /// y.unroot(&mut store); 798 /// # Ok(()) 799 /// # } 800 /// ``` 801 pub fn to_manually_rooted(&self, mut store: impl AsContextMut) -> Result<ManuallyRooted<T>> { 802 self._to_manually_rooted(store.as_context_mut().0) 803 } 804 805 pub(crate) fn _to_manually_rooted(&self, store: &mut StoreOpaque) -> Result<ManuallyRooted<T>> { 806 let mut store = AutoAssertNoGc::new(store); 807 let gc_ref = self.try_clone_gc_ref(&mut store)?; 808 Ok(ManuallyRooted::new(&mut store, gc_ref)) 809 } 810 811 /// Are these two `Rooted<T>`s the same GC root? 812 /// 813 /// Note that this function can return `false` even when `a` and `b` are 814 /// rooting the same underlying GC object, but the object was rooted 815 /// multiple times (for example in different scopes). Use 816 /// [`Rooted::ref_eq`][crate::Rooted::ref_eq] to test whether these are 817 /// references to the same underlying GC object or not. 818 /// 819 /// # Example 820 /// 821 /// ``` 822 /// # use wasmtime::*; 823 /// # fn foo() -> Result<()> { 824 /// let mut store = Store::<()>::default(); 825 /// 826 /// let a = ExternRef::new(&mut store, "hello")?; 827 /// let b = a; 828 /// 829 /// // `a` and `b` are the same GC root. 830 /// assert!(Rooted::rooted_eq(a, b)); 831 /// 832 /// { 833 /// let mut scope = RootScope::new(&mut store); 834 /// 835 /// // `c` is a different GC root, in a different scope, even though it 836 /// // is rooting the same object. 837 /// let c = a.to_manually_rooted(&mut scope)?.into_rooted(&mut scope); 838 /// assert!(!Rooted::rooted_eq(a, c)); 839 /// } 840 /// 841 /// let x = ExternRef::new(&mut store, "goodbye")?; 842 /// 843 /// // `a` and `x` are different GC roots, rooting different objects. 844 /// assert!(!Rooted::rooted_eq(a, x)); 845 /// # Ok(()) 846 /// # } 847 /// ``` 848 pub fn rooted_eq(a: Self, b: Self) -> bool { 849 a.inner == b.inner 850 } 851 852 /// Are these two GC roots referencing the same underlying GC object? 853 /// 854 /// This function will return `true` even when `a` and `b` are different GC 855 /// roots (for example because they were rooted in different scopes) if they 856 /// are rooting the same underlying GC object. To only test whether they are 857 /// the same GC root, and not whether they are rooting the same GC object, 858 /// use [`Rooted::rooted_eq`][crate::Rooted::rooted_eq]. 859 /// 860 /// Returns an error if either `a` or `b` has been unrooted, for example 861 /// because the scope it was rooted within has been exited. 862 /// 863 /// Because this method takes any `impl RootedGcRef<T>` arguments, it can be 864 /// used to compare, for example, a `Rooted<T>` and a `ManuallyRooted<T>`. 865 /// 866 /// # Panics 867 /// 868 /// Panics if either `a` or `b` is not associated with the given `store`. 869 /// 870 /// # Example 871 /// 872 /// ``` 873 /// # use wasmtime::*; 874 /// # fn foo() -> Result<()> { 875 /// let mut store = Store::<()>::default(); 876 /// 877 /// let a = ExternRef::new(&mut store, "hello")?; 878 /// let b = a; 879 /// 880 /// // `a` and `b` are rooting the same object. 881 /// assert!(Rooted::ref_eq(&store, &a, &b)?); 882 /// 883 /// { 884 /// let mut scope = RootScope::new(&mut store); 885 /// 886 /// // `c` is a different GC root, in a different scope, but still 887 /// // rooting the same object. 888 /// let c = a.to_manually_rooted(&mut scope)?.into_rooted(&mut scope); 889 /// assert!(!Rooted::ref_eq(&scope, &a, &c)?); 890 /// } 891 /// 892 /// let x = ExternRef::new(&mut store, "goodbye")?; 893 /// 894 /// // `a` and `x` are rooting different objects. 895 /// assert!(!Rooted::ref_eq(&store, &a, &x)?); 896 /// 897 /// // You can also compare `Rooted<T>`s and `ManuallyRooted<T>`s with this 898 /// // function. 899 /// let d = a.to_manually_rooted(&mut store)?; 900 /// assert!(Rooted::ref_eq(&store, &a, &d)?); 901 /// 902 /// d.unroot(&mut store); 903 /// # Ok(()) 904 /// # } 905 /// ``` 906 pub fn ref_eq( 907 store: impl AsContext, 908 a: &impl RootedGcRef<T>, 909 b: &impl RootedGcRef<T>, 910 ) -> Result<bool> { 911 let store = store.as_context().0; 912 let a = a.try_gc_ref(store)?; 913 let b = b.try_gc_ref(store)?; 914 Ok(a == b) 915 } 916 917 /// Hash this root. 918 /// 919 /// Note that, similar to `Rooted::rooted_eq`, this only operates on the 920 /// root and *not* the underlying GC reference. That means that two 921 /// different rootings of the same object will hash to different values 922 /// (modulo hash collisions). If this is undesirable, use the 923 /// [`ref_hash`][crate::Rooted::ref_hash] method instead. 924 pub fn rooted_hash<H>(&self, state: &mut H) 925 where 926 H: Hasher, 927 { 928 self.inner.hash(state); 929 } 930 931 /// Hash the underlying rooted object reference. 932 /// 933 /// Note that, similar to `Rooted::ref_eq`, and operates on the underlying 934 /// rooted GC object reference, not the root. That means that two 935 /// *different* rootings of the same object will hash to the *same* 936 /// value. If this is undesirable, use the 937 /// [`rooted_hash`][crate::Rooted::rooted_hash] method instead. 938 pub fn ref_hash<H>(&self, store: impl AsContext, state: &mut H) -> Result<()> 939 where 940 H: Hasher, 941 { 942 let gc_ref = self.try_gc_ref(store.as_context().0)?; 943 gc_ref.hash(state); 944 Ok(()) 945 } 946 947 /// Cast `self` to a `Rooted<U>`. 948 /// 949 /// It is the caller's responsibility to ensure that `self` is actually a 950 /// `U`. Failure to uphold this invariant will be memory safe but will 951 /// result in general incorrectness such as panics and wrong results. 952 pub(crate) fn unchecked_cast<U: GcRef>(self) -> Rooted<U> { 953 Rooted::from_gc_root_index(self.inner) 954 } 955 } 956 957 /// Nested rooting scopes. 958 /// 959 /// `RootScope` allows the creation or nested rooting scopes for use with 960 /// [`Rooted<T>`][crate::Rooted]. This allows for fine-grained control over how 961 /// long a set of [`Rooted<T>`][crate::Rooted]s are strongly held alive, giving 962 /// gives you the tools necessary to avoid holding onto GC objects longer than 963 /// necessary. `Rooted<T>`s created within a `RootScope` are automatically 964 /// unrooted when the `RootScope` is dropped. For more details on 965 /// [`Rooted<T>`][crate::Rooted] lifetimes and their interaction with rooting 966 /// scopes, see [`Rooted<T>`][crate::Rooted]'s documentation. 967 /// 968 /// A `RootScope<C>` wraps a `C: AsContextMut` (that is, anything that 969 /// represents exclusive access to a [`Store`][crate::Store]) and in turn 970 /// implements [`AsContext`][crate::AsContext] and 971 /// [`AsContextMut`][crate::AsContextMut] in terms of its underlying 972 /// `C`. Therefore, `RootScope<C>` can be used anywhere you would use the 973 /// underlying `C`, for example in the [`Global::get`][crate::Global::get] 974 /// method. Any `Rooted<T>`s created by a method that a `RootScope<C>` was 975 /// passed as context to are tied to the `RootScope<C>`'s scope and 976 /// automatically unrooted when the scope is dropped. 977 /// 978 /// # Example 979 /// 980 /// ``` 981 /// # use wasmtime::*; 982 /// # fn _foo() -> Result<()> { 983 /// let mut store = Store::<()>::default(); 984 /// 985 /// let a: Rooted<_>; 986 /// let b: Rooted<_>; 987 /// let c: Rooted<_>; 988 /// 989 /// // Root `a` in the store's scope. It will be rooted for the duration of the 990 /// // store's lifetime. 991 /// a = ExternRef::new(&mut store, 42)?; 992 /// 993 /// // `a` is rooted, so we can access its data successfully. 994 /// assert!(a.data(&store).is_ok()); 995 /// 996 /// { 997 /// let mut scope1 = RootScope::new(&mut store); 998 /// 999 /// // Root `b` in `scope1`. 1000 /// b = ExternRef::new(&mut scope1, 36)?; 1001 /// 1002 /// // Both `a` and `b` are rooted. 1003 /// assert!(a.data(&scope1).is_ok()); 1004 /// assert!(b.data(&scope1).is_ok()); 1005 /// 1006 /// { 1007 /// let mut scope2 = RootScope::new(&mut scope1); 1008 /// 1009 /// // Root `c` in `scope2`. 1010 /// c = ExternRef::new(&mut scope2, 36)?; 1011 /// 1012 /// // All of `a`, `b`, and `c` are rooted. 1013 /// assert!(a.data(&scope2).is_ok()); 1014 /// assert!(b.data(&scope2).is_ok()); 1015 /// assert!(c.data(&scope2).is_ok()); 1016 /// 1017 /// // Drop `scope2`. 1018 /// } 1019 /// 1020 /// // Now `a` and `b` are still rooted, but `c` was unrooted when we dropped 1021 /// // `scope2`. 1022 /// assert!(a.data(&scope1).is_ok()); 1023 /// assert!(b.data(&scope1).is_ok()); 1024 /// assert!(c.data(&scope1).is_err()); 1025 /// 1026 /// // Drop `scope1`. 1027 /// } 1028 /// 1029 /// // And now only `a` is still rooted. Both `b` and `c` were unrooted when we 1030 /// // dropped their respective rooting scopes. 1031 /// assert!(a.data(&store).is_ok()); 1032 /// assert!(b.data(&store).is_err()); 1033 /// assert!(c.data(&store).is_err()); 1034 /// # Ok(()) 1035 /// # } 1036 /// ``` 1037 pub struct RootScope<C> 1038 where 1039 C: AsContextMut, 1040 { 1041 store: C, 1042 scope: usize, 1043 } 1044 1045 impl<C> Drop for RootScope<C> 1046 where 1047 C: AsContextMut, 1048 { 1049 fn drop(&mut self) { 1050 self.store.as_context_mut().0.exit_gc_lifo_scope(self.scope); 1051 } 1052 } 1053 1054 impl<C> RootScope<C> 1055 where 1056 C: AsContextMut, 1057 { 1058 // NB: we MUST NOT expose a method like 1059 // 1060 // pub fn store(&mut self) -> &mut Store { ... } 1061 // 1062 // because callers could do treacherous things like 1063 // 1064 // let scope1 = RootScope::new(&mut store1); 1065 // let scope2 = RootScope::new(&mut store2); 1066 // std::mem::swap(scope1.store(), scope2.store()); 1067 // 1068 // and then we would start truncate the store's GC root set's LIFO roots to 1069 // the wrong lengths. 1070 // 1071 // Instead, we just implement `AsContext[Mut]` for `RootScope`. 1072 1073 /// Construct a new scope for rooting GC objects. 1074 /// 1075 /// # Example 1076 /// 1077 /// ``` 1078 /// # use wasmtime::*; 1079 /// let mut store = Store::<()>::default(); 1080 /// 1081 /// { 1082 /// let mut scope = RootScope::new(&mut store); 1083 /// 1084 /// // Temporarily root GC objects in this nested rooting scope... 1085 /// } 1086 /// ``` 1087 pub fn new(store: C) -> Self { 1088 let scope = store.as_context().0.gc_roots().enter_lifo_scope(); 1089 RootScope { store, scope } 1090 } 1091 1092 fn gc_roots(&mut self) -> &mut RootSet { 1093 self.store.as_context_mut().0.gc_roots_mut() 1094 } 1095 1096 fn lifo_roots(&mut self) -> &mut Vec<LifoRoot> { 1097 &mut self.gc_roots().lifo_roots 1098 } 1099 1100 /// Reserve enough capacity for `additional` GC roots in this scope. 1101 /// 1102 /// # Example 1103 /// 1104 /// ``` 1105 /// # use wasmtime::*; 1106 /// let mut store = Store::<()>::default(); 1107 /// 1108 /// { 1109 /// let mut scope = RootScope::new(&mut store); 1110 /// 1111 /// // Ensure we have enough storage pre-allocated to root five GC 1112 /// // references inside this scope without any underlying reallocation. 1113 /// scope.reserve(5); 1114 /// 1115 /// // ... 1116 /// } 1117 /// ``` 1118 pub fn reserve(&mut self, additional: usize) { 1119 self.lifo_roots().reserve(additional); 1120 } 1121 } 1122 1123 impl<T> AsContext for RootScope<T> 1124 where 1125 T: AsContextMut, 1126 { 1127 type Data = T::Data; 1128 1129 fn as_context(&self) -> crate::StoreContext<'_, Self::Data> { 1130 self.store.as_context() 1131 } 1132 } 1133 1134 impl<T> AsContextMut for RootScope<T> 1135 where 1136 T: AsContextMut, 1137 { 1138 fn as_context_mut(&mut self) -> crate::StoreContextMut<'_, Self::Data> { 1139 self.store.as_context_mut() 1140 } 1141 } 1142 1143 /// A rooted reference to a garbage-collected `T` with arbitrary lifetime. 1144 /// 1145 /// A `ManuallyRooted<T>` is a strong handle to a garbage-collected `T`, 1146 /// preventing its referent (and anything else transitively referenced) from 1147 /// being collected by the GC until [`unroot`][crate::ManuallyRooted::unroot] is 1148 /// explicitly called. 1149 /// 1150 /// The primary way to create a `ManuallyRooted<T>` is to promote a temporary 1151 /// `Rooted<T>` into a `ManuallyRooted<T>` via its 1152 /// [`to_manually_rooted`][crate::Rooted::to_manually_rooted] method. 1153 /// 1154 /// `ManuallyRooted<T>` dereferences to its underlying `T`, allowing you to call 1155 /// `T`'s methods. 1156 /// 1157 /// # Example 1158 /// 1159 /// ``` 1160 /// # use wasmtime::*; 1161 /// # fn _foo() -> Result<()> { 1162 /// let mut store = Store::<Option<ManuallyRooted<ExternRef>>>::default(); 1163 /// 1164 /// // Create our `ManuallyRooted` in a nested scope to avoid rooting it for 1165 /// // the duration of the store's lifetime. 1166 /// let x = { 1167 /// let mut scope = RootScope::new(&mut store); 1168 /// let x = ExternRef::new(&mut scope, 1234)?; 1169 /// x.to_manually_rooted(&mut scope)? 1170 /// }; 1171 /// 1172 /// // Place `x` into our store. 1173 /// *store.data_mut() = Some(x); 1174 /// 1175 /// // Do a bunch stuff that may or may not access, replace, or take `x`... 1176 /// 1177 /// // At any time, in any arbitrary scope, we can remove `x` from the store 1178 /// // and unroot it: 1179 /// if let Some(x) = store.data_mut().take() { 1180 /// x.unroot(&mut store); 1181 /// } 1182 /// # Ok(()) 1183 /// # } 1184 /// ``` 1185 /// 1186 /// # Differences Between `ManuallyRooted<T>` and `Rooted<T>` 1187 /// 1188 /// While `ManuallyRooted<T>` can have arbitrary lifetimes, it requires manual 1189 /// unrooting. This is in contrast to [`Rooted<T>`][crate::Rooted] which is 1190 /// restricted to strictly last-in-first-out (LIFO, aka stack order) lifetimes, 1191 /// but comes with automatic unrooting. 1192 /// 1193 /// | Type | Supported Lifetimes | Unrooting | 1194 /// |----------------------------------------------|-----------------------------|-----------| 1195 /// | [`Rooted<T>`][crate::Rooted] | Strictly LIFO / stack order | Automatic | 1196 /// | [`ManuallyRooted<T>`][crate::ManuallyRooted] | Arbitrary | Manual | 1197 /// 1198 /// `Rooted<T>` should suffice for most use cases, and provides better 1199 /// ergonomics, but `ManuallyRooted<T>` exists as a fully-general escape hatch. 1200 /// 1201 /// # Manual Unrooting 1202 /// 1203 /// Failure to explicitly call [`unroot`][crate::ManuallyRooted::unroot] (or 1204 /// another method that consumes `self` and unroots the reference, such as 1205 /// [`into_rooted`][crate::ManuallyRooted::into_rooted]) will leak the 1206 /// underlying GC object, preventing it from being garbage collected until its 1207 /// owning [`Store`][crate::Store] is dropped. That means all of the following 1208 /// will result in permanently rooting the underlying GC object: 1209 /// 1210 /// * Implicitly dropping a `ManuallyRooted<T>`: 1211 /// 1212 /// ```no_run 1213 /// # use wasmtime::*; 1214 /// # let get_manually_rooted = || -> ManuallyRooted<ExternRef> { todo!() }; 1215 /// { 1216 /// let perma_root: ManuallyRooted<_> = get_manually_rooted(); 1217 /// 1218 /// // `perma_root` is implicitly dropped at the end of its scope, 1219 /// // permanently rooting/leaking its referent. 1220 /// } 1221 /// ``` 1222 /// 1223 /// * Explicitly dropping a `ManuallyRooted<T>`: `drop(my_manually_rooted)`. 1224 /// 1225 /// * Forgetting a `ManuallyRooted<T>`: `std::mem::forget(my_manually_rooted)`. 1226 /// 1227 /// * Inserting a `ManuallyRooted<T>` into a `std::sync::Arc` or `std::rc::Rc` 1228 /// cycle. 1229 /// 1230 /// * Etc... 1231 /// 1232 /// Wasmtime does *not* assert that a `ManuallyRooted<T>` is unrooted on `Drop`, 1233 /// or otherwise raise a panic, log a warning, or etc... on failure to manually 1234 /// unroot. Sometimes leaking is intentional and desirable, particularly when 1235 /// dealing with short-lived [`Store`][crate::Store]s where unrooting would just 1236 /// be busy work since the whole store is about to be dropped. 1237 #[repr(transparent)] // NB: the C API relies on this 1238 pub struct ManuallyRooted<T> 1239 where 1240 T: GcRef, 1241 { 1242 inner: GcRootIndex, 1243 _phantom: marker::PhantomData<T>, 1244 } 1245 1246 const _: () = { 1247 use crate::{AnyRef, ExternRef}; 1248 1249 // NB: these match the C API which should also be updated if this changes 1250 assert!(mem::size_of::<ManuallyRooted<AnyRef>>() == 16); 1251 assert!(mem::align_of::<ManuallyRooted<AnyRef>>() == 8); 1252 assert!(mem::size_of::<ManuallyRooted<ExternRef>>() == 16); 1253 assert!(mem::align_of::<ManuallyRooted<ExternRef>>() == 8); 1254 }; 1255 1256 impl<T: GcRef> Debug for ManuallyRooted<T> { 1257 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1258 let name = format!("ManuallyRooted<{}>", any::type_name::<T>()); 1259 f.debug_struct(&name).field("inner", &self.inner).finish() 1260 } 1261 } 1262 1263 impl<T: GcRef> Deref for ManuallyRooted<T> { 1264 type Target = T; 1265 1266 fn deref(&self) -> &Self::Target { 1267 T::transmute_ref(&self.inner) 1268 } 1269 } 1270 1271 impl<T> ManuallyRooted<T> 1272 where 1273 T: GcRef, 1274 { 1275 /// Construct a new manually-rooted GC root. 1276 /// 1277 /// `gc_ref` should belong to `store`'s heap; failure to uphold this is 1278 /// memory safe but will result in general failures down the line such as 1279 /// panics or incorrect results. 1280 /// 1281 /// `gc_ref` should be a GC reference pointing to an instance of the GC type 1282 /// that `T` represents. Failure to uphold this invariant is memory safe but 1283 /// will result in general incorrectness such as panics and wrong results. 1284 pub(crate) fn new(store: &mut AutoAssertNoGc<'_>, gc_ref: VMGcRef) -> Self { 1285 let id = store.gc_roots_mut().manually_rooted.alloc(gc_ref); 1286 ManuallyRooted { 1287 inner: GcRootIndex { 1288 store_id: store.id(), 1289 generation: 0, 1290 index: PackedIndex::new_manual(id), 1291 }, 1292 _phantom: marker::PhantomData, 1293 } 1294 } 1295 1296 #[inline] 1297 pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool { 1298 debug_assert!(self.inner.index.is_manual()); 1299 self.inner.comes_from_same_store(store) 1300 } 1301 1302 /// Clone this `ManuallyRooted`. 1303 /// 1304 /// Does not consume or unroot `self`: both `self` and the new 1305 /// `ManuallyRooted` return value will need to be manually unrooted. 1306 /// 1307 /// # Panics 1308 /// 1309 /// Panics if `self` is not associated with the given `store`. 1310 /// 1311 /// # Example 1312 /// 1313 /// ``` 1314 /// # use wasmtime::*; 1315 /// # fn _foo() -> Result<()> { 1316 /// let mut store = Store::<Vec<ManuallyRooted<ExternRef>>>::default(); 1317 /// 1318 /// // Create our `ManuallyRooted` in a nested scope to avoid rooting it for 1319 /// // the duration of the store's lifetime. 1320 /// let x = { 1321 /// let mut scope = RootScope::new(&mut store); 1322 /// let x = ExternRef::new(&mut scope, 1234)?; 1323 /// x.to_manually_rooted(&mut scope)? 1324 /// }; 1325 /// 1326 /// // Push five clones of `x` into our store. 1327 /// for _ in 0..5 { 1328 /// let x_clone = x.clone(&mut store); 1329 /// store.data_mut().push(x_clone); 1330 /// } 1331 /// # Ok(()) 1332 /// # } 1333 /// ``` 1334 pub fn clone(&self, mut store: impl AsContextMut) -> Self { 1335 self._clone(store.as_context_mut().0) 1336 } 1337 1338 pub(crate) fn _clone(&self, store: &mut StoreOpaque) -> Self { 1339 let mut store = AutoAssertNoGc::new(store); 1340 let gc_ref = self 1341 .clone_gc_ref(&mut store) 1342 .expect("ManuallyRooted always has a gc ref"); 1343 Self::new(&mut store, gc_ref) 1344 } 1345 1346 /// Unroot this GC object. 1347 /// 1348 /// Failure to call this method will result in the GC object, and anything 1349 /// it transitively references, being kept alive (aka "leaking") for the 1350 /// entirety of the store's lifetime. 1351 /// 1352 /// See the type-level docs for example usage. 1353 pub fn unroot(self, mut store: impl AsContextMut) { 1354 self._unroot(store.as_context_mut().0) 1355 } 1356 1357 pub(crate) fn _unroot(self, store: &mut StoreOpaque) { 1358 assert!( 1359 self.comes_from_same_store(store), 1360 "object used with wrong store" 1361 ); 1362 1363 let mut store = AutoAssertNoGc::new(store); 1364 let id = self.inner.index.as_manual().unwrap(); 1365 let roots = store.gc_roots_mut(); 1366 let gc_ref = roots.manually_rooted.dealloc(id); 1367 store.unwrap_gc_store_mut().drop_gc_ref(gc_ref); 1368 } 1369 1370 /// Clone this `ManuallyRooted<T>` into a `Rooted<T>`. 1371 /// 1372 /// This operation does not consume or unroot this `ManuallyRooted<T>`. 1373 /// 1374 /// The underlying GC object is re-rooted in the given context's scope. The 1375 /// resulting `Rooted<T>` is only valid during the given context's 1376 /// scope. See the [`Rooted<T>`][crate::Rooted] documentation for more 1377 /// details on rooting scopes. 1378 /// 1379 /// This operation does not consume or unroot this `ManuallyRooted<T>`. 1380 /// 1381 /// # Panics 1382 /// 1383 /// Panics if this object is not associated with the given context's store. 1384 /// 1385 /// # Example 1386 /// 1387 /// ``` 1388 /// # use wasmtime::*; 1389 /// # fn _foo() -> Result<()> { 1390 /// let mut store = Store::<()>::default(); 1391 /// 1392 /// let root1: Rooted<_>; 1393 /// 1394 /// let manual = { 1395 /// let mut scope = RootScope::new(&mut store); 1396 /// root1 = ExternRef::new(&mut scope, 1234)?; 1397 /// root1.to_manually_rooted(&mut scope)? 1398 /// }; 1399 /// 1400 /// // `root1` is no longer accessible because it was unrooted when `scope` 1401 /// // was dropped. 1402 /// assert!(root1.data(&store).is_err()); 1403 /// 1404 /// // But we can re-root `manual` into this scope. 1405 /// let root2 = manual.to_rooted(&mut store); 1406 /// assert!(root2.data(&store).is_ok()); 1407 /// 1408 /// // And we also still have access to `manual` and we still have to 1409 /// // manually unroot it. 1410 /// assert!(manual.data(&store).is_ok()); 1411 /// manual.unroot(&mut store); 1412 /// # Ok(()) 1413 /// # } 1414 /// ``` 1415 pub fn to_rooted(&self, mut context: impl AsContextMut) -> Rooted<T> { 1416 self._to_rooted(context.as_context_mut().0) 1417 } 1418 1419 pub(crate) fn _to_rooted(&self, store: &mut StoreOpaque) -> Rooted<T> { 1420 assert!( 1421 self.comes_from_same_store(store), 1422 "object used with wrong store" 1423 ); 1424 let mut store = AutoAssertNoGc::new(store); 1425 let gc_ref = self.clone_gc_ref(&mut store).unwrap(); 1426 Rooted::new(&mut store, gc_ref) 1427 } 1428 1429 /// Convert this `ManuallyRooted<T>` into a `Rooted<T>`. 1430 /// 1431 /// The underlying GC object is re-rooted in the given context's scope. The 1432 /// resulting `Rooted<T>` is only valid during the given context's 1433 /// scope. See the [`Rooted<T>`][crate::Rooted] documentation for more 1434 /// details on rooting scopes. 1435 /// 1436 /// This operation consumes and unroots this `ManuallyRooted<T>`. 1437 /// 1438 /// # Panics 1439 /// 1440 /// Panics if this object is not associate with the given context's store. 1441 /// 1442 /// # Example 1443 /// 1444 /// ``` 1445 /// # use wasmtime::*; 1446 /// # fn _foo() -> Result<()> { 1447 /// let mut store = Store::<()>::default(); 1448 /// 1449 /// let root1: Rooted<_>; 1450 /// 1451 /// let manual = { 1452 /// let mut scope = RootScope::new(&mut store); 1453 /// root1 = ExternRef::new(&mut scope, 1234)?; 1454 /// root1.to_manually_rooted(&mut scope)? 1455 /// }; 1456 /// 1457 /// // `root1` is no longer accessible because it was unrooted when `scope` 1458 /// // was dropped. 1459 /// assert!(root1.data(&store).is_err()); 1460 /// 1461 /// // But we can re-root `manual` into this scope. 1462 /// let root2 = manual.into_rooted(&mut store); 1463 /// assert!(root2.data(&store).is_ok()); 1464 /// 1465 /// // `manual` was consumed by the `into_rooted` call, and we no longer 1466 /// // have access to it, nor need to manually unroot it. 1467 /// # Ok(()) 1468 /// # } 1469 /// ``` 1470 pub fn into_rooted(self, mut context: impl AsContextMut) -> Rooted<T> { 1471 self._into_rooted(context.as_context_mut().0) 1472 } 1473 1474 pub(crate) fn _into_rooted(self, store: &mut StoreOpaque) -> Rooted<T> { 1475 assert!( 1476 self.comes_from_same_store(store), 1477 "object used with wrong store" 1478 ); 1479 let rooted = self._to_rooted(store); 1480 self._unroot(store); 1481 rooted 1482 } 1483 1484 /// Are these two GC roots referencing the same underlying GC object? 1485 /// 1486 /// This function will return `true` even when `a` and `b` are different GC 1487 /// roots (for example because they were rooted in different scopes) if they 1488 /// are rooting the same underlying GC object. 1489 /// 1490 /// Because this method takes any `impl RootedGcRef<T>` arguments, it can be 1491 /// used to compare, for example, a `Rooted<T>` and a `ManuallyRooted<T>`. 1492 /// 1493 /// # Panics 1494 /// 1495 /// Panics if either `a` or `b` is not associated with the given `store`. 1496 /// 1497 /// # Example 1498 /// 1499 /// ``` 1500 /// # use wasmtime::*; 1501 /// # fn foo() -> Result<()> { 1502 /// let mut store = Store::<()>::default(); 1503 /// 1504 /// let a = ExternRef::new_manually_rooted(&mut store, "hello")?; 1505 /// let b = a.clone(&mut store); 1506 /// 1507 /// // `a` and `b` are rooting the same object. 1508 /// assert!(ManuallyRooted::ref_eq(&store, &a, &b)?); 1509 /// 1510 /// { 1511 /// let mut scope = RootScope::new(&mut store); 1512 /// 1513 /// // `c` is a different GC root, is in a different scope, and is a 1514 /// // `Rooted<T>` instead of a `ManuallyRooted<T>`, but is still rooting 1515 /// // the same object. 1516 /// let c = a.to_rooted(&mut scope); 1517 /// assert!(ManuallyRooted::ref_eq(&scope, &a, &c)?); 1518 /// } 1519 /// 1520 /// let x = ExternRef::new_manually_rooted(&mut store, "goodbye")?; 1521 /// 1522 /// // `a` and `x` are rooting different objects. 1523 /// assert!(!ManuallyRooted::ref_eq(&store, &a, &x)?); 1524 /// 1525 /// a.unroot(&mut store); 1526 /// b.unroot(&mut store); 1527 /// x.unroot(&mut store); 1528 /// # Ok(()) 1529 /// # } 1530 /// ``` 1531 pub fn ref_eq( 1532 store: impl AsContext, 1533 a: &impl RootedGcRef<T>, 1534 b: &impl RootedGcRef<T>, 1535 ) -> Result<bool> { 1536 Rooted::ref_eq(store, a, b) 1537 } 1538 1539 /// Hash this root. 1540 /// 1541 /// Note that, similar to `Rooted::rooted_eq`, this only operates on the 1542 /// root and *not* the underlying GC reference. That means that two 1543 /// different rootings of the same object will hash to different values 1544 /// (modulo hash collisions). If this is undesirable, use the 1545 /// [`ref_hash`][crate::ManuallyRooted::ref_hash] method instead. 1546 pub fn rooted_hash<H>(&self, state: &mut H) 1547 where 1548 H: Hasher, 1549 { 1550 self.inner.hash(state); 1551 } 1552 1553 /// Hash the underlying rooted object reference. 1554 /// 1555 /// Note that, similar to `Rooted::ref_eq`, and operates on the underlying 1556 /// rooted GC object reference, not the root. That means that two 1557 /// *different* rootings of the same object will hash to the *same* 1558 /// value. If this is undesirable, use the 1559 /// [`rooted_hash`][crate::Rooted::rooted_hash] method instead. 1560 pub fn ref_hash<H>(&self, store: impl AsContext, state: &mut H) 1561 where 1562 H: Hasher, 1563 { 1564 let gc_ref = self 1565 .get_gc_ref(store.as_context().0) 1566 .expect("ManuallyRooted's get_gc_ref is infallible"); 1567 gc_ref.hash(state); 1568 } 1569 1570 #[doc(hidden)] 1571 pub fn into_parts_for_c_api(self) -> (NonZeroU64, u32, u32) { 1572 ( 1573 self.inner.store_id.as_raw(), 1574 self.inner.generation, 1575 self.inner.index.0, 1576 ) 1577 } 1578 1579 #[doc(hidden)] 1580 pub unsafe fn from_raw_parts_for_c_api(a: NonZeroU64, b: u32, c: u32) -> ManuallyRooted<T> { 1581 ManuallyRooted { 1582 inner: GcRootIndex { 1583 store_id: StoreId::from_raw(a), 1584 generation: b, 1585 index: PackedIndex(c), 1586 }, 1587 _phantom: marker::PhantomData, 1588 } 1589 } 1590 1591 /// Cast `self` to a `ManuallyRooted<U>`. 1592 /// 1593 /// It is the caller's responsibility to ensure that `self` is actually a 1594 /// `U`. Failure to uphold this invariant will be memory safe but will 1595 /// result in general incorrectness such as panics and wrong results. 1596 pub(crate) fn unchecked_cast<U: GcRef>(self) -> ManuallyRooted<U> { 1597 let u = ManuallyRooted { 1598 inner: self.inner, 1599 _phantom: core::marker::PhantomData, 1600 }; 1601 core::mem::forget(self); 1602 u 1603 } 1604 } 1605 1606 impl<T: GcRef> RootedGcRefImpl<T> for ManuallyRooted<T> { 1607 fn get_gc_ref<'a>(&self, store: &'a StoreOpaque) -> Option<&'a VMGcRef> { 1608 assert!( 1609 self.comes_from_same_store(store), 1610 "object used with wrong store" 1611 ); 1612 1613 let id = self.inner.index.as_manual().unwrap(); 1614 store.gc_roots().manually_rooted.get(id) 1615 } 1616 } 1617 1618 #[cfg(test)] 1619 mod tests { 1620 use crate::ExternRef; 1621 1622 use super::*; 1623 1624 #[test] 1625 fn sizes() { 1626 // Try to keep tabs on the size of these things. Don't want them growing 1627 // unintentionally. 1628 assert_eq!(std::mem::size_of::<Rooted<ExternRef>>(), 16); 1629 assert_eq!(std::mem::size_of::<ManuallyRooted<ExternRef>>(), 16); 1630 } 1631 } 1632