1 use crate::component::RuntimeInstance; 2 use crate::component::func::HostFunc; 3 use crate::component::matching::InstanceType; 4 use crate::component::store::{ComponentInstanceId, StoreComponentInstanceId}; 5 use crate::component::{ 6 Component, ComponentExportIndex, ComponentNamedList, Func, Lift, Lower, ResourceType, 7 TypedFunc, types::ComponentItem, 8 }; 9 use crate::instance::OwnedImports; 10 use crate::linker::DefinitionType; 11 use crate::prelude::*; 12 use crate::runtime::vm::component::{ComponentInstance, TypedResource, TypedResourceIndex}; 13 use crate::runtime::vm::{self, VMFuncRef}; 14 use crate::store::{AsStoreOpaque, Asyncness, StoreOpaque}; 15 use crate::{AsContext, AsContextMut, Engine, Module, StoreContextMut}; 16 use alloc::sync::Arc; 17 use core::marker; 18 use core::pin::Pin; 19 use core::ptr::NonNull; 20 use wasmtime_environ::{EngineOrModuleTypeIndex, component::*}; 21 use wasmtime_environ::{EntityIndex, EntityType, PrimaryMap}; 22 23 /// An instantiated component. 24 /// 25 /// This type represents an instantiated [`Component`](super::Component). 26 /// Instances have exports which can be accessed through functions such as 27 /// [`Instance::get_func`] or [`Instance::get_export`]. Instances are owned by a 28 /// [`Store`](crate::Store) and all methods require a handle to the store. 29 /// 30 /// Component instances are created through 31 /// [`Linker::instantiate`](super::Linker::instantiate) and its family of 32 /// methods. 33 /// 34 /// This type is similar to the core wasm version 35 /// [`wasmtime::Instance`](crate::Instance) except that it represents an 36 /// instantiated component instead of an instantiated module. 37 #[derive(Copy, Clone, Debug)] 38 #[repr(transparent)] 39 pub struct Instance { 40 id: StoreComponentInstanceId, 41 } 42 43 // Double-check that the C representation in `component/instance.h` matches our 44 // in-Rust representation here in terms of size/alignment/etc. 45 const _: () = { 46 #[repr(C)] 47 struct C(u64, u32); 48 assert!(core::mem::size_of::<C>() == core::mem::size_of::<Instance>()); 49 assert!(core::mem::align_of::<C>() == core::mem::align_of::<Instance>()); 50 assert!(core::mem::offset_of!(Instance, id) == 0); 51 }; 52 53 impl Instance { 54 /// Creates a raw `Instance` from the internal identifiers within the store. 55 pub(crate) fn from_wasmtime(store: &StoreOpaque, id: ComponentInstanceId) -> Instance { 56 Instance { 57 id: StoreComponentInstanceId::new(store.id(), id), 58 } 59 } 60 61 /// Looks up an exported function by name within this [`Instance`]. 62 /// 63 /// The `store` argument provided must be the store that this instance 64 /// lives within and the `name` argument is the lookup key by which to find 65 /// the exported function. If the function is found then `Some` is returned 66 /// and otherwise `None` is returned. 67 /// 68 /// The `name` here can be a string such as `&str` or it can be a 69 /// [`ComponentExportIndex`] which is loaded prior from a [`Component`]. 70 /// 71 /// # Panics 72 /// 73 /// Panics if `store` does not own this instance. 74 /// 75 /// # Examples 76 /// 77 /// Looking up a function which is exported from the root of a component: 78 /// 79 /// ``` 80 /// use wasmtime::{Engine, Store}; 81 /// use wasmtime::component::{Component, Linker}; 82 /// 83 /// # fn main() -> wasmtime::Result<()> { 84 /// let engine = Engine::default(); 85 /// let component = Component::new( 86 /// &engine, 87 /// r#" 88 /// (component 89 /// (core module $m 90 /// (func (export "f")) 91 /// ) 92 /// (core instance $i (instantiate $m)) 93 /// (func (export "f") 94 /// (canon lift (core func $i "f"))) 95 /// ) 96 /// "#, 97 /// )?; 98 /// 99 /// // Look up the function by name 100 /// let mut store = Store::new(&engine, ()); 101 /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 102 /// let func = instance.get_func(&mut store, "f").unwrap(); 103 /// 104 /// // The function can also be looked up by an index via a precomputed index. 105 /// let export = component.get_export_index(None, "f").unwrap(); 106 /// let func = instance.get_func(&mut store, &export).unwrap(); 107 /// # Ok(()) 108 /// # } 109 /// ``` 110 /// 111 /// Looking up a function which is exported from a nested instance: 112 /// 113 /// ``` 114 /// use wasmtime::{Engine, Store}; 115 /// use wasmtime::component::{Component, Linker}; 116 /// 117 /// # fn main() -> wasmtime::Result<()> { 118 /// let engine = Engine::default(); 119 /// let component = Component::new( 120 /// &engine, 121 /// r#" 122 /// (component 123 /// (core module $m 124 /// (func (export "f")) 125 /// ) 126 /// (core instance $i (instantiate $m)) 127 /// (func $f 128 /// (canon lift (core func $i "f"))) 129 /// 130 /// (instance $i 131 /// (export "f" (func $f))) 132 /// (export "i" (instance $i)) 133 /// ) 134 /// "#, 135 /// )?; 136 /// 137 /// // First look up the exported instance, then use that to lookup the 138 /// // exported function. 139 /// let instance_index = component.get_export_index(None, "i").unwrap(); 140 /// let func_index = component.get_export_index(Some(&instance_index), "f").unwrap(); 141 /// 142 /// // Then use `func_index` at runtime. 143 /// let mut store = Store::new(&engine, ()); 144 /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 145 /// let func = instance.get_func(&mut store, &func_index).unwrap(); 146 /// 147 /// // Alternatively the `instance` can be used directly in conjunction with 148 /// // the `get_export_index` method. 149 /// let instance_index = instance.get_export_index(&mut store, None, "i").unwrap(); 150 /// let func_index = instance.get_export_index(&mut store, Some(&instance_index), "f").unwrap(); 151 /// let func = instance.get_func(&mut store, &func_index).unwrap(); 152 /// # Ok(()) 153 /// # } 154 /// ``` 155 pub fn get_func( 156 &self, 157 mut store: impl AsContextMut, 158 name: impl InstanceExportLookup, 159 ) -> Option<Func> { 160 let store = store.as_context_mut().0; 161 let instance = self.id.get(store); 162 let component = instance.component(); 163 164 // Validate that `name` exists within `self.` 165 let index = name.lookup(component)?; 166 167 // Validate that `index` is indeed a lifted function. 168 match &component.env_component().export_items[index] { 169 Export::LiftedFunction { .. } => {} 170 _ => return None, 171 } 172 173 // And package up the indices! 174 Some(Func::from_lifted_func(*self, index)) 175 } 176 177 /// Looks up an exported [`Func`] value by name and with its type. 178 /// 179 /// This function is a convenience wrapper over [`Instance::get_func`] and 180 /// [`Func::typed`]. For more information see the linked documentation. 181 /// 182 /// Returns an error if `name` isn't a function export or if the export's 183 /// type did not match `Params` or `Results` 184 /// 185 /// # Panics 186 /// 187 /// Panics if `store` does not own this instance. 188 pub fn get_typed_func<Params, Results>( 189 &self, 190 mut store: impl AsContextMut, 191 name: impl InstanceExportLookup, 192 ) -> Result<TypedFunc<Params, Results>> 193 where 194 Params: ComponentNamedList + Lower, 195 Results: ComponentNamedList + Lift, 196 { 197 let f = self 198 .get_func(store.as_context_mut(), name) 199 .ok_or_else(|| format_err!("failed to find function export"))?; 200 Ok(f.typed::<Params, Results>(store) 201 .with_context(|| format!("failed to convert function to given type"))?) 202 } 203 204 /// Looks up an exported module by name within this [`Instance`]. 205 /// 206 /// The `store` argument provided must be the store that this instance 207 /// lives within and the `name` argument is the lookup key by which to find 208 /// the exported module. If the module is found then `Some` is returned 209 /// and otherwise `None` is returned. 210 /// 211 /// The `name` here can be a string such as `&str` or it can be a 212 /// [`ComponentExportIndex`] which is loaded prior from a [`Component`]. 213 /// 214 /// For some examples see [`Instance::get_func`] for loading values from a 215 /// component. 216 /// 217 /// # Panics 218 /// 219 /// Panics if `store` does not own this instance. 220 pub fn get_module( 221 &self, 222 mut store: impl AsContextMut, 223 name: impl InstanceExportLookup, 224 ) -> Option<Module> { 225 let store = store.as_context_mut().0; 226 let (instance, export) = self.lookup_export(store, name)?; 227 match export { 228 Export::ModuleStatic { index, .. } => { 229 Some(instance.component().static_module(*index).clone()) 230 } 231 Export::ModuleImport { import, .. } => match instance.runtime_import(*import) { 232 RuntimeImport::Module(m) => Some(m.clone()), 233 _ => unreachable!(), 234 }, 235 _ => None, 236 } 237 } 238 239 /// Looks up an exported resource type by name within this [`Instance`]. 240 /// 241 /// The `store` argument provided must be the store that this instance 242 /// lives within and the `name` argument is the lookup key by which to find 243 /// the exported resource. If the resource is found then `Some` is returned 244 /// and otherwise `None` is returned. 245 /// 246 /// The `name` here can be a string such as `&str` or it can be a 247 /// [`ComponentExportIndex`] which is loaded prior from a [`Component`]. 248 /// 249 /// For some examples see [`Instance::get_func`] for loading values from a 250 /// component. 251 /// 252 /// # Panics 253 /// 254 /// Panics if `store` does not own this instance. 255 pub fn get_resource( 256 &self, 257 mut store: impl AsContextMut, 258 name: impl InstanceExportLookup, 259 ) -> Option<ResourceType> { 260 let store = store.as_context_mut().0; 261 let (instance, export) = self.lookup_export(store, name)?; 262 match export { 263 Export::Type(TypeDef::Resource(id)) => { 264 Some(InstanceType::new(instance).resource_type(*id)) 265 } 266 Export::Type(_) 267 | Export::LiftedFunction { .. } 268 | Export::ModuleStatic { .. } 269 | Export::ModuleImport { .. } 270 | Export::Instance { .. } => None, 271 } 272 } 273 274 /// A methods similar to [`Component::get_export`] except for this 275 /// instance. 276 /// 277 /// This method will lookup the `name` provided within the `instance` 278 /// provided and return a [`ComponentItem`] describing the export, 279 /// and [`ComponentExportIndex`] which can be passed other `get_*` 280 /// functions like [`Instance::get_func`]. 281 /// 282 /// The [`ComponentItem`] is more expensive to compute than the 283 /// [`ComponentExportIndex`]. If you are not consuming the 284 /// [`ComponentItem`], use [`Instance::get_export_index`] instead. 285 /// 286 /// # Panics 287 /// 288 /// Panics if `store` does not own this instance. 289 pub fn get_export( 290 &self, 291 mut store: impl AsContextMut, 292 instance: Option<&ComponentExportIndex>, 293 name: &str, 294 ) -> Option<(ComponentItem, ComponentExportIndex)> { 295 self._get_export(store.as_context_mut().0, instance, name) 296 } 297 298 fn _get_export( 299 &self, 300 store: &StoreOpaque, 301 instance: Option<&ComponentExportIndex>, 302 name: &str, 303 ) -> Option<(ComponentItem, ComponentExportIndex)> { 304 let data = self.id().get(store); 305 let component = data.component(); 306 let index = component.lookup_export_index(instance, name)?; 307 let item = ComponentItem::from_export( 308 &store.engine(), 309 &component.env_component().export_items[index], 310 &InstanceType::new(data), 311 ); 312 Some(( 313 item, 314 ComponentExportIndex { 315 id: data.component().id(), 316 index, 317 }, 318 )) 319 } 320 321 /// A methods similar to [`Component::get_export_index`] except for this 322 /// instance. 323 /// 324 /// This method will lookup the `name` provided within the `instance` 325 /// provided and return a [`ComponentExportIndex`] which can be passed 326 /// other `get_*` functions like [`Instance::get_func`]. 327 /// 328 /// If you need the [`ComponentItem`] corresponding to this export, use 329 /// the [`Instance::get_export`] instead. 330 /// 331 /// # Panics 332 /// 333 /// Panics if `store` does not own this instance. 334 pub fn get_export_index( 335 &self, 336 mut store: impl AsContextMut, 337 instance: Option<&ComponentExportIndex>, 338 name: &str, 339 ) -> Option<ComponentExportIndex> { 340 let data = self.id().get(store.as_context_mut().0); 341 let index = data.component().lookup_export_index(instance, name)?; 342 Some(ComponentExportIndex { 343 id: data.component().id(), 344 index, 345 }) 346 } 347 348 fn lookup_export<'a>( 349 &self, 350 store: &'a StoreOpaque, 351 name: impl InstanceExportLookup, 352 ) -> Option<(&'a ComponentInstance, &'a Export)> { 353 let data = self.id().get(store); 354 let index = name.lookup(data.component())?; 355 Some((data, &data.component().env_component().export_items[index])) 356 } 357 358 /// Returns the [`InstancePre`] that was used to create this instance. 359 pub fn instance_pre<T>(&self, store: impl AsContext<Data = T>) -> InstancePre<T> { 360 // This indexing operation asserts the Store owns the Instance. 361 // Therefore, the InstancePre<T> must match the Store<T>. 362 let data = self.id().get(store.as_context().0); 363 364 // SAFETY: calling this method safely here relies on matching the `T` 365 // in `InstancePre<T>` to the store itself, which is happening in the 366 // type signature just above by ensuring the store's data is `T` which 367 // matches the return value. 368 unsafe { data.instance_pre() } 369 } 370 371 pub(crate) fn id(&self) -> StoreComponentInstanceId { 372 self.id 373 } 374 375 /// Implementation of the `resource.new` intrinsic for `i32` 376 /// representations. 377 pub(crate) fn resource_new32( 378 self, 379 store: &mut StoreOpaque, 380 ty: TypeResourceTableIndex, 381 rep: u32, 382 ) -> Result<u32> { 383 store 384 .component_resource_tables(Some(self)) 385 .resource_new(TypedResource::Component { ty, rep }) 386 } 387 388 /// Implementation of the `resource.rep` intrinsic for `i32` 389 /// representations. 390 pub(crate) fn resource_rep32( 391 self, 392 store: &mut StoreOpaque, 393 ty: TypeResourceTableIndex, 394 index: u32, 395 ) -> Result<u32> { 396 store 397 .component_resource_tables(Some(self)) 398 .resource_rep(TypedResourceIndex::Component { ty, index }) 399 } 400 401 /// Implementation of the `resource.drop` intrinsic. 402 pub(crate) fn resource_drop( 403 self, 404 store: &mut StoreOpaque, 405 ty: TypeResourceTableIndex, 406 index: u32, 407 ) -> Result<Option<u32>> { 408 store 409 .component_resource_tables(Some(self)) 410 .resource_drop(TypedResourceIndex::Component { ty, index }) 411 } 412 413 pub(crate) fn resource_transfer_own( 414 self, 415 store: &mut StoreOpaque, 416 index: u32, 417 src: TypeResourceTableIndex, 418 dst: TypeResourceTableIndex, 419 ) -> Result<u32> { 420 let mut tables = store.component_resource_tables(Some(self)); 421 let rep = tables.resource_lift_own(TypedResourceIndex::Component { ty: src, index })?; 422 tables.resource_lower_own(TypedResource::Component { ty: dst, rep }) 423 } 424 425 pub(crate) fn resource_transfer_borrow( 426 self, 427 store: &mut StoreOpaque, 428 index: u32, 429 src: TypeResourceTableIndex, 430 dst: TypeResourceTableIndex, 431 ) -> Result<u32> { 432 let dst_owns_resource = self.id().get(store).resource_owned_by_own_instance(dst); 433 let mut tables = store.component_resource_tables(Some(self)); 434 let rep = tables.resource_lift_borrow(TypedResourceIndex::Component { ty: src, index })?; 435 // Implement `lower_borrow`'s special case here where if a borrow's 436 // resource type is owned by `dst` then the destination receives the 437 // representation directly rather than a handle to the representation. 438 // 439 // This can perhaps become a different libcall in the future to avoid 440 // this check at runtime since we know at compile time whether the 441 // destination type owns the resource, but that's left as a future 442 // refactoring if truly necessary. 443 if dst_owns_resource { 444 return Ok(rep); 445 } 446 tables.resource_lower_borrow(TypedResource::Component { ty: dst, rep }) 447 } 448 449 pub(crate) fn lookup_vmdef(&self, store: &mut StoreOpaque, def: &CoreDef) -> vm::Export { 450 lookup_vmdef(store, self.id.instance(), def) 451 } 452 453 pub(crate) fn options<'a>( 454 &self, 455 store: &'a StoreOpaque, 456 options: OptionsIndex, 457 ) -> &'a CanonicalOptions { 458 &self.id.get(store).component().env_component().options[options] 459 } 460 461 fn options_memory_raw( 462 &self, 463 store: &StoreOpaque, 464 options: OptionsIndex, 465 ) -> Option<NonNull<vm::VMMemoryDefinition>> { 466 let instance = self.id.get(store); 467 let options = &instance.component().env_component().options[options]; 468 let memory = match options.data_model { 469 CanonicalOptionsDataModel::Gc { .. } => return None, 470 CanonicalOptionsDataModel::LinearMemory(o) => match o.memory { 471 Some(m) => m, 472 None => return None, 473 }, 474 }; 475 476 Some(instance.runtime_memory(memory)) 477 } 478 479 pub(crate) fn options_memory<'a>( 480 &self, 481 store: &'a StoreOpaque, 482 options: OptionsIndex, 483 ) -> &'a [u8] { 484 let memory = match self.options_memory_raw(store, options) { 485 Some(m) => m, 486 None => return &[], 487 }; 488 // SAFETY: we're borrowing the entire `StoreOpaque` which owns the 489 // memory allocation to return the result of memory. That means that the 490 // lifetime connection here should be safe and the actual ptr/length are 491 // trusted parts of the runtime here. 492 unsafe { 493 let memory = memory.as_ref(); 494 core::slice::from_raw_parts(memory.base.as_ptr(), memory.current_length()) 495 } 496 } 497 498 pub(crate) fn options_memory_mut<'a>( 499 &self, 500 store: &'a mut StoreOpaque, 501 options: OptionsIndex, 502 ) -> &'a mut [u8] { 503 let memory = match self.options_memory_raw(store, options) { 504 Some(m) => m, 505 None => return &mut [], 506 }; 507 // SAFETY: See `options_memory` comment above, and note that this is 508 // taking `&mut StoreOpaque` to thread the lifetime through instead. 509 unsafe { 510 let memory = memory.as_ref(); 511 core::slice::from_raw_parts_mut(memory.base.as_ptr(), memory.current_length()) 512 } 513 } 514 515 /// Helper function to simultaneously get a borrow to this instance's 516 /// component as well as the store that this component is contained within. 517 /// 518 /// Note that this function signature is not possible with safe Rust, so 519 /// this is using `unsafe` internally. 520 pub(crate) fn component_and_store_mut<'a, S>( 521 &self, 522 store: &'a mut S, 523 ) -> (&'a Component, &'a mut S) 524 where 525 S: AsStoreOpaque, 526 { 527 let store_opaque = store.as_store_opaque(); 528 let instance = self.id.get_mut(store_opaque); 529 let component = instance.component(); 530 531 // SAFETY: the goal of this function is to derive a pointer from 532 // `&mut S`, here `&Component`, and then return both so they can both be 533 // used at the same time. In general this is not safe operation since 534 // the original mutable pointer could be mutated or overwritten which 535 // would invalidate the derived pointer. 536 // 537 // In this case though we have a few guarantees which should make this 538 // safe: 539 // 540 // * Embedders never have the ability to overwrite a `StoreOpaque`. For 541 // example the closest thing of `StoreContextMut` wraps up the 542 // reference internally so it's inaccessible to the outside world. 543 // This means that while mutations can still happen it's not possible 544 // to overwrite a `StoreOpaque` directly. 545 // 546 // * Components are referred to by `vm::ComponentInstance` which holds a 547 // strong reference. All `ComponentInstance` structures are allocated 548 // within the store and unconditionally live as long as the entire 549 // store itself. This means that there's no worry of the rooting 550 // container going away or otherwise getting deallocated. 551 // 552 // * The `ComponentInstance` container has an invariant that after 553 // creation the component used to create it cannot be changed. This is 554 // enforced through `Pin<&mut ComponentInstance>` which disallows 555 // mutable access to the `component` field, instead only allowing 556 // read-only access. 557 // 558 // Putting all of this together it's not possible for a component, 559 // within a component instance, within a store, to be deallocated or mutated while 560 // a store is in use. Consequently it should be safe to simultaneously 561 // have a borrow to both at the same time, even if the store has a 562 // mutable borrow itself. 563 unsafe { 564 let component: *const Component = component; 565 (&*component, store) 566 } 567 } 568 } 569 570 /// Translates a `CoreDef`, a definition of a core wasm item, to an 571 /// [`Export`] which is the runtime core wasm definition. 572 pub(crate) fn lookup_vmdef( 573 store: &mut StoreOpaque, 574 id: ComponentInstanceId, 575 def: &CoreDef, 576 ) -> vm::Export { 577 match def { 578 CoreDef::Export(e) => lookup_vmexport(store, id, e), 579 CoreDef::Trampoline(idx) => { 580 let funcref = store 581 .store_data_mut() 582 .component_instance_mut(id) 583 .trampoline_func_ref(*idx); 584 // SAFETY: the `funcref` is owned by `store` and is valid within 585 // that store, so it's safe to create a `Func`. 586 vm::Export::Function(unsafe { crate::Func::from_vm_func_ref(store.id(), funcref) }) 587 } 588 CoreDef::InstanceFlags(idx) => { 589 let id = StoreComponentInstanceId::new(store.id(), id); 590 vm::Export::Global(crate::Global::from_component_flags(id, *idx)) 591 } 592 CoreDef::UnsafeIntrinsic(intrinsic) => { 593 let funcref = store 594 .store_data_mut() 595 .component_instance_mut(id) 596 .unsafe_intrinsic_func_ref(*intrinsic); 597 // SAFETY: as above, the `funcref` is owned by `store` and is valid 598 // within that store, so it's safe to create a `Func`. 599 vm::Export::Function(unsafe { crate::Func::from_vm_func_ref(store.id(), funcref) }) 600 } 601 CoreDef::TaskMayBlock => vm::Export::Global(crate::Global::from_task_may_block( 602 StoreComponentInstanceId::new(store.id(), id), 603 )), 604 } 605 } 606 607 /// Translates a `CoreExport<T>`, an export of some core instance within 608 /// this component, to the actual runtime definition of that item. 609 pub(crate) fn lookup_vmexport<T>( 610 store: &mut StoreOpaque, 611 id: ComponentInstanceId, 612 item: &CoreExport<T>, 613 ) -> vm::Export 614 where 615 T: Copy + Into<EntityIndex>, 616 { 617 let store_id = store.id(); 618 let id = store 619 .store_data_mut() 620 .component_instance_mut(id) 621 .instance(item.instance); 622 let (instance, registry) = store.instance_and_module_registry_mut(id); 623 let idx = match &item.item { 624 ExportItem::Index(idx) => (*idx).into(), 625 626 // FIXME: ideally at runtime we don't actually do any name lookups 627 // here. This will only happen when the host supplies an imported 628 // module so while the structure can't be known at compile time we 629 // do know at `InstancePre` time, for example, what all the host 630 // imports are. In theory we should be able to, as part of 631 // `InstancePre` construction, perform all name=>index mappings 632 // during that phase so the actual instantiation of an `InstancePre` 633 // skips all string lookups. This should probably only be 634 // investigated if this becomes a performance issue though. 635 ExportItem::Name(name) => instance.env_module().exports[name], 636 }; 637 // SAFETY: the `store_id` owns this instance and all exports contained 638 // within. 639 unsafe { instance.get_export_by_index_mut(registry, store_id, idx) } 640 } 641 642 /// Trait used to lookup the export of a component instance. 643 /// 644 /// This trait is used as an implementation detail of [`Instance::get_func`] 645 /// and related `get_*` methods. Notable implementors of this trait are: 646 /// 647 /// * `str` 648 /// * `String` 649 /// * [`ComponentExportIndex`] 650 /// 651 /// Note that this is intended to be a `wasmtime`-sealed trait so it shouldn't 652 /// need to be implemented externally. 653 pub trait InstanceExportLookup { 654 #[doc(hidden)] 655 fn lookup(&self, component: &Component) -> Option<ExportIndex>; 656 } 657 658 impl<T> InstanceExportLookup for &T 659 where 660 T: InstanceExportLookup + ?Sized, 661 { 662 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 663 T::lookup(self, component) 664 } 665 } 666 667 impl InstanceExportLookup for str { 668 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 669 component 670 .env_component() 671 .exports 672 .get(self, &NameMapNoIntern) 673 .copied() 674 } 675 } 676 677 impl InstanceExportLookup for String { 678 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 679 str::lookup(self, component) 680 } 681 } 682 683 struct Instantiator<'a> { 684 component: &'a Component, 685 id: ComponentInstanceId, 686 core_imports: OwnedImports, 687 imports: &'a PrimaryMap<RuntimeImportIndex, RuntimeImport>, 688 } 689 690 pub(crate) enum RuntimeImport { 691 Func(Arc<HostFunc>), 692 Module(Module), 693 Resource { 694 ty: ResourceType, 695 696 // A strong reference to the host function that represents the 697 // destructor for this resource. At this time all resources here are 698 // host-defined resources. Note that this is itself never read because 699 // the funcref below points to it. 700 // 701 // Also note that the `Arc` here is used to support the same host 702 // function being used across multiple instances simultaneously. Or 703 // otherwise this makes `InstancePre::instantiate` possible to create 704 // separate instances all sharing the same host function. 705 dtor: Arc<crate::func::HostFunc>, 706 707 // A raw function which is filled out (including `wasm_call`) which 708 // points to the internals of the `_dtor` field. This is read and 709 // possibly executed by wasm. 710 dtor_funcref: VMFuncRef, 711 }, 712 } 713 714 pub type ImportedResources = PrimaryMap<ResourceIndex, ResourceType>; 715 716 impl<'a> Instantiator<'a> { 717 fn new( 718 component: &'a Component, 719 store: &mut StoreOpaque, 720 imports: &'a Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 721 ) -> Result<Instantiator<'a>> { 722 let env_component = component.env_component(); 723 let (modules, engine) = store.modules_and_engine_mut(); 724 modules.register_component(component, engine)?; 725 let imported_resources: ImportedResources = 726 PrimaryMap::with_capacity(env_component.imported_resources.len()); 727 728 let instance = ComponentInstance::new( 729 store.store_data().components.next_component_instance_id(), 730 component, 731 Arc::new(imported_resources), 732 imports, 733 store.traitobj(), 734 )?; 735 let id = store.store_data_mut().push_component_instance(instance); 736 737 Ok(Instantiator { 738 component, 739 imports, 740 core_imports: OwnedImports::empty(), 741 id, 742 }) 743 } 744 745 async fn run<T>( 746 &mut self, 747 store: &mut StoreContextMut<'_, T>, 748 asyncness: Asyncness, 749 ) -> Result<()> { 750 let env_component = self.component.env_component(); 751 752 // Before all initializers are processed configure all destructors for 753 // host-defined resources. No initializer will correspond to these and 754 // it's required to happen before they're needed, so execute this first. 755 for (idx, import) in env_component.imported_resources.iter() { 756 let (ty, func_ref) = match &self.imports[*import] { 757 RuntimeImport::Resource { 758 ty, dtor_funcref, .. 759 } => (*ty, NonNull::from(dtor_funcref)), 760 _ => unreachable!(), 761 }; 762 let i = self.instance_resource_types_mut(store.0).push(ty); 763 assert_eq!(i, idx); 764 self.instance_mut(store.0) 765 .set_resource_destructor(idx, Some(func_ref)); 766 } 767 768 // Next configure all `VMFuncRef`s for trampolines that this component 769 // will require. These functions won't actually get used until their 770 // associated state has been initialized through the global initializers 771 // below, but the funcrefs can all be configured here. 772 for (idx, sig) in env_component.trampolines.iter() { 773 let ptrs = self.component.trampoline_ptrs(idx); 774 let signature = match self.component.signatures().shared_type(*sig) { 775 Some(s) => s, 776 None => panic!("found unregistered signature: {sig:?}"), 777 }; 778 779 self.instance_mut(store.0).set_trampoline( 780 idx, 781 ptrs.wasm_call, 782 ptrs.array_call, 783 signature, 784 ); 785 } 786 787 // Initialize the unsafe intrinsics used by this component, if any. 788 for (i, module_ty) in env_component 789 .unsafe_intrinsics 790 .iter() 791 .enumerate() 792 .filter_map(|(i, ty)| ty.expand().map(|ty| (i, ty))) 793 { 794 let i = u32::try_from(i).unwrap(); 795 let intrinsic = UnsafeIntrinsic::from_u32(i); 796 let ptrs = self.component.unsafe_intrinsic_ptrs(intrinsic).expect( 797 "should have intrinsic pointers given that we assigned the intrinsic a type", 798 ); 799 let shared_ty = self 800 .component 801 .signatures() 802 .shared_type(module_ty) 803 .expect("should have a shared type"); 804 self.instance_mut(store.0).set_intrinsic( 805 intrinsic, 806 ptrs.wasm_call, 807 ptrs.array_call, 808 shared_ty, 809 ); 810 } 811 812 for initializer in env_component.initializers.iter() { 813 match initializer { 814 GlobalInitializer::InstantiateModule(m, component_instance) => { 815 let instance = self.id; 816 let module; 817 let imports = match m { 818 // Since upvars are statically know we know that the 819 // `args` list is already in the right order. 820 InstantiateModule::Static(idx, args) => { 821 module = self.component.static_module(*idx); 822 self.build_imports(store.0, module, args.iter()) 823 } 824 825 // With imports, unlike upvars, we need to do runtime 826 // lookups with strings to determine the order of the 827 // imports since it's whatever the actual module 828 // requires. 829 // 830 // FIXME: see the note in `ExportItem::Name` handling 831 // above for how we ideally shouldn't do string lookup 832 // here. 833 InstantiateModule::Import(idx, args) => { 834 module = match &self.imports[*idx] { 835 RuntimeImport::Module(m) => m, 836 _ => unreachable!(), 837 }; 838 let args = module 839 .imports() 840 .map(|import| &args[import.module()][import.name()]); 841 self.build_imports(store.0, module, args) 842 } 843 }; 844 845 let exit = if let Some(component_instance) = *component_instance { 846 store.0.enter_guest_sync_call( 847 None, 848 false, 849 RuntimeInstance { 850 instance, 851 index: component_instance, 852 }, 853 )?; 854 true 855 } else { 856 false 857 }; 858 859 // Note that the unsafety here should be ok because the 860 // validity of the component means that type-checks have 861 // already been performed. This means that the unsafety due 862 // to imports having the wrong type should not happen here. 863 // 864 // Also note we are calling new_started_impl because we have 865 // already checked for asyncness and are running on a fiber 866 // if required. 867 868 let i = unsafe { 869 crate::Instance::new_started(store, module, imports.as_ref(), asyncness) 870 .await? 871 }; 872 873 if exit { 874 store.0.exit_guest_sync_call(false)?; 875 } 876 877 self.instance_mut(store.0).push_instance_id(i.id()); 878 } 879 880 GlobalInitializer::LowerImport { import, index } => { 881 let func = match &self.imports[*import] { 882 RuntimeImport::Func(func) => func, 883 _ => unreachable!(), 884 }; 885 self.instance_mut(store.0) 886 .set_lowering(*index, func.lowering()); 887 } 888 889 GlobalInitializer::ExtractTable(table) => self.extract_table(store.0, table), 890 891 GlobalInitializer::ExtractMemory(mem) => self.extract_memory(store.0, mem), 892 893 GlobalInitializer::ExtractRealloc(realloc) => { 894 self.extract_realloc(store.0, realloc) 895 } 896 897 GlobalInitializer::ExtractCallback(callback) => { 898 self.extract_callback(store.0, callback) 899 } 900 901 GlobalInitializer::ExtractPostReturn(post_return) => { 902 self.extract_post_return(store.0, post_return) 903 } 904 905 GlobalInitializer::Resource(r) => self.resource(store.0, r), 906 } 907 } 908 Ok(()) 909 } 910 911 fn resource(&mut self, store: &mut StoreOpaque, resource: &Resource) { 912 let dtor = resource 913 .dtor 914 .as_ref() 915 .map(|dtor| lookup_vmdef(store, self.id, dtor)); 916 let dtor = dtor.map(|export| match export { 917 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 918 _ => unreachable!(), 919 }); 920 let index = self 921 .component 922 .env_component() 923 .resource_index(resource.index); 924 let instance = self.instance(store); 925 let ty = ResourceType::guest(store.id(), instance, resource.index); 926 self.instance_mut(store) 927 .set_resource_destructor(index, dtor); 928 let i = self.instance_resource_types_mut(store).push(ty); 929 debug_assert_eq!(i, index); 930 } 931 932 fn extract_memory(&mut self, store: &mut StoreOpaque, memory: &ExtractMemory) { 933 let import = match lookup_vmexport(store, self.id, &memory.export) { 934 crate::runtime::vm::Export::Memory(memory) => memory.vmimport(store), 935 crate::runtime::vm::Export::SharedMemory(_, import) => import, 936 _ => unreachable!(), 937 }; 938 self.instance_mut(store) 939 .set_runtime_memory(memory.index, import.from.as_non_null()); 940 } 941 942 fn extract_realloc(&mut self, store: &mut StoreOpaque, realloc: &ExtractRealloc) { 943 let func_ref = match lookup_vmdef(store, self.id, &realloc.def) { 944 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 945 _ => unreachable!(), 946 }; 947 self.instance_mut(store) 948 .set_runtime_realloc(realloc.index, func_ref); 949 } 950 951 fn extract_callback(&mut self, store: &mut StoreOpaque, callback: &ExtractCallback) { 952 let func_ref = match lookup_vmdef(store, self.id, &callback.def) { 953 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 954 _ => unreachable!(), 955 }; 956 self.instance_mut(store) 957 .set_runtime_callback(callback.index, func_ref); 958 } 959 960 fn extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn) { 961 let func_ref = match lookup_vmdef(store, self.id, &post_return.def) { 962 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 963 _ => unreachable!(), 964 }; 965 self.instance_mut(store) 966 .set_runtime_post_return(post_return.index, func_ref); 967 } 968 969 fn extract_table(&mut self, store: &mut StoreOpaque, table: &ExtractTable) { 970 let export = match lookup_vmexport(store, self.id, &table.export) { 971 crate::runtime::vm::Export::Table(t) => t, 972 _ => unreachable!(), 973 }; 974 let import = export.vmimport(store); 975 self.instance_mut(store) 976 .set_runtime_table(table.index, import); 977 } 978 979 fn build_imports<'b>( 980 &mut self, 981 store: &mut StoreOpaque, 982 module: &Module, 983 args: impl Iterator<Item = &'b CoreDef>, 984 ) -> &OwnedImports { 985 self.core_imports.clear(); 986 self.core_imports.reserve(module); 987 let mut imports = module.compiled_module().module().imports(); 988 989 for arg in args { 990 // The general idea of Wasmtime is that at runtime type-checks for 991 // core wasm instantiations internally within a component are 992 // unnecessary and superfluous. Naturally though mistakes may be 993 // made, so double-check this property of wasmtime in debug mode. 994 995 if cfg!(debug_assertions) { 996 let (imp_module, imp_name, expected) = imports.next().unwrap(); 997 self.assert_type_matches(store, module, arg, imp_module, imp_name, expected); 998 } 999 1000 // The unsafety here should be ok since the `export` is loaded 1001 // directly from an instance which should only give us valid export 1002 // items. 1003 let export = lookup_vmdef(store, self.id, arg); 1004 self.core_imports.push_export(store, &export); 1005 } 1006 debug_assert!(imports.next().is_none()); 1007 1008 &self.core_imports 1009 } 1010 1011 fn assert_type_matches( 1012 &self, 1013 store: &mut StoreOpaque, 1014 module: &Module, 1015 arg: &CoreDef, 1016 imp_module: &str, 1017 imp_name: &str, 1018 expected: EntityType, 1019 ) { 1020 let export = lookup_vmdef(store, self.id, arg); 1021 1022 // If this value is a core wasm function then the type check is inlined 1023 // here. This can otherwise fail `Extern::from_wasmtime_export` because 1024 // there's no guarantee that there exists a trampoline for `f` so this 1025 // can't fall through to the case below 1026 if let crate::runtime::vm::Export::Function(f) = &export { 1027 let expected = match expected.unwrap_func() { 1028 EngineOrModuleTypeIndex::Engine(e) => Some(e), 1029 EngineOrModuleTypeIndex::Module(m) => module.signatures().shared_type(m), 1030 EngineOrModuleTypeIndex::RecGroup(_) => unreachable!(), 1031 }; 1032 let actual = unsafe { f.vm_func_ref(store).as_ref().type_index }; 1033 assert_eq!( 1034 expected, 1035 Some(actual), 1036 "type mismatch for import {imp_module:?} {imp_name:?}!!!\n\n\ 1037 expected {:#?}\n\n\ 1038 found {:#?}", 1039 expected.and_then(|e| store.engine().signatures().borrow(e)), 1040 store.engine().signatures().borrow(actual) 1041 ); 1042 return; 1043 } 1044 1045 let val = crate::Extern::from_wasmtime_export(export, store); 1046 let ty = DefinitionType::from(store, &val); 1047 crate::types::matching::MatchCx::new(module.engine()) 1048 .definition(&expected, &ty) 1049 .expect("unexpected typecheck failure"); 1050 } 1051 1052 /// Convenience helper to return the `&ComponentInstance` that's being 1053 /// instantiated. 1054 fn instance<'b>(&self, store: &'b StoreOpaque) -> &'b ComponentInstance { 1055 store.store_data().component_instance(self.id) 1056 } 1057 1058 /// Same as [`Self::instance`], but for mutability. 1059 fn instance_mut<'b>(&self, store: &'b mut StoreOpaque) -> Pin<&'b mut ComponentInstance> { 1060 store.store_data_mut().component_instance_mut(self.id) 1061 } 1062 1063 // NB: This method is only intended to be called during the instantiation 1064 // process because the `Arc::get_mut` here is fallible and won't generally 1065 // succeed once the instance has been handed to the embedder. Before that 1066 // though it should be guaranteed that the single owning reference currently 1067 // lives within the `ComponentInstance` that's being built. 1068 fn instance_resource_types_mut<'b>( 1069 &self, 1070 store: &'b mut StoreOpaque, 1071 ) -> &'b mut ImportedResources { 1072 Arc::get_mut(self.instance_mut(store).resource_types_mut()).unwrap() 1073 } 1074 } 1075 1076 /// A "pre-instantiated" [`Instance`] which has all of its arguments already 1077 /// supplied and is ready to instantiate. 1078 /// 1079 /// This structure represents an efficient form of instantiation where import 1080 /// type-checking and import lookup has all been resolved by the time that this 1081 /// type is created. This type is primarily created through the 1082 /// [`Linker::instantiate_pre`](crate::component::Linker::instantiate_pre) 1083 /// method. 1084 pub struct InstancePre<T: 'static> { 1085 component: Component, 1086 imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 1087 resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>, 1088 asyncness: Asyncness, 1089 _marker: marker::PhantomData<fn() -> T>, 1090 } 1091 1092 // `InstancePre`'s clone does not require `T: Clone` 1093 impl<T: 'static> Clone for InstancePre<T> { 1094 fn clone(&self) -> Self { 1095 Self { 1096 component: self.component.clone(), 1097 imports: self.imports.clone(), 1098 resource_types: self.resource_types.clone(), 1099 asyncness: self.asyncness, 1100 _marker: self._marker, 1101 } 1102 } 1103 } 1104 1105 impl<T: 'static> InstancePre<T> { 1106 /// This function is `unsafe` since there's no guarantee that the 1107 /// `RuntimeImport` items provided are guaranteed to work with the `T` of 1108 /// the store. 1109 /// 1110 /// Additionally there is no static guarantee that the `imports` provided 1111 /// satisfy the imports of the `component` provided. 1112 pub(crate) unsafe fn new_unchecked( 1113 component: Component, 1114 imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 1115 resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>, 1116 ) -> InstancePre<T> { 1117 let mut asyncness = Asyncness::No; 1118 for (_, import) in imports.iter() { 1119 asyncness = asyncness 1120 | match import { 1121 RuntimeImport::Func(f) => f.asyncness(), 1122 RuntimeImport::Module(_) => Asyncness::No, 1123 RuntimeImport::Resource { dtor, .. } => dtor.asyncness(), 1124 }; 1125 } 1126 InstancePre { 1127 component, 1128 imports, 1129 resource_types, 1130 asyncness, 1131 _marker: marker::PhantomData, 1132 } 1133 } 1134 1135 /// Returns the underlying component that will be instantiated. 1136 pub fn component(&self) -> &Component { 1137 &self.component 1138 } 1139 1140 #[doc(hidden)] 1141 /// Returns the type at which the underlying component will be 1142 /// instantiated. This contains the instantiated type information which 1143 /// was determined by the Linker. 1144 pub fn instance_type(&self) -> InstanceType<'_> { 1145 InstanceType { 1146 types: &self.component.types(), 1147 resources: &self.resource_types, 1148 } 1149 } 1150 1151 /// Returns the underlying engine. 1152 pub fn engine(&self) -> &Engine { 1153 self.component.engine() 1154 } 1155 1156 /// Performs the instantiation process into the store specified. 1157 // 1158 // TODO: needs more docs 1159 pub fn instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> { 1160 let store = store.as_context_mut(); 1161 1162 // If this instance requires an async host, set that flag in the store, 1163 // and then afterwards assert nothing else in the store, nor this 1164 // instance, required async. 1165 store.0.set_async_required(self.asyncness); 1166 store.0.validate_sync_call()?; 1167 1168 vm::assert_ready(self._instantiate(store, Asyncness::No)) 1169 } 1170 /// Performs the instantiation process into the store specified. 1171 /// 1172 /// Exactly like [`Self::instantiate`] except for use on async stores. 1173 // 1174 // TODO: needs more docs 1175 #[cfg(feature = "async")] 1176 pub async fn instantiate_async(&self, store: impl AsContextMut<Data = T>) -> Result<Instance> { 1177 self._instantiate(store, Asyncness::Yes).await 1178 } 1179 1180 async fn _instantiate( 1181 &self, 1182 mut store: impl AsContextMut<Data = T>, 1183 asyncness: Asyncness, 1184 ) -> Result<Instance> { 1185 let mut store = store.as_context_mut(); 1186 store.0.set_async_required(self.asyncness); 1187 store 1188 .engine() 1189 .allocator() 1190 .increment_component_instance_count()?; 1191 let mut instantiator = Instantiator::new(&self.component, store.0, &self.imports)?; 1192 instantiator.run(&mut store, asyncness).await.map_err(|e| { 1193 store 1194 .engine() 1195 .allocator() 1196 .decrement_component_instance_count(); 1197 e 1198 })?; 1199 1200 let instance = Instance::from_wasmtime(store.0, instantiator.id); 1201 store.0.push_component_instance(instance); 1202 Ok(instance) 1203 } 1204 } 1205