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) => { 636 let module = instance.env_module(); 637 let name = module.strings.get_atom(name).unwrap(); 638 module.exports[&name] 639 } 640 }; 641 // SAFETY: the `store_id` owns this instance and all exports contained 642 // within. 643 unsafe { instance.get_export_by_index_mut(registry, store_id, idx) } 644 } 645 646 /// Trait used to lookup the export of a component instance. 647 /// 648 /// This trait is used as an implementation detail of [`Instance::get_func`] 649 /// and related `get_*` methods. Notable implementors of this trait are: 650 /// 651 /// * `str` 652 /// * `String` 653 /// * [`ComponentExportIndex`] 654 /// 655 /// Note that this is intended to be a `wasmtime`-sealed trait so it shouldn't 656 /// need to be implemented externally. 657 pub trait InstanceExportLookup { 658 #[doc(hidden)] 659 fn lookup(&self, component: &Component) -> Option<ExportIndex>; 660 } 661 662 impl<T> InstanceExportLookup for &T 663 where 664 T: InstanceExportLookup + ?Sized, 665 { 666 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 667 T::lookup(self, component) 668 } 669 } 670 671 impl InstanceExportLookup for str { 672 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 673 component 674 .env_component() 675 .exports 676 .get(self, &NameMapNoIntern) 677 .copied() 678 } 679 } 680 681 impl InstanceExportLookup for String { 682 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 683 str::lookup(self, component) 684 } 685 } 686 687 struct Instantiator<'a> { 688 component: &'a Component, 689 id: ComponentInstanceId, 690 core_imports: OwnedImports, 691 imports: &'a PrimaryMap<RuntimeImportIndex, RuntimeImport>, 692 } 693 694 pub(crate) enum RuntimeImport { 695 Func(Arc<HostFunc>), 696 Module(Module), 697 Resource { 698 ty: ResourceType, 699 700 // A strong reference to the host function that represents the 701 // destructor for this resource. At this time all resources here are 702 // host-defined resources. Note that this is itself never read because 703 // the funcref below points to it. 704 // 705 // Also note that the `Arc` here is used to support the same host 706 // function being used across multiple instances simultaneously. Or 707 // otherwise this makes `InstancePre::instantiate` possible to create 708 // separate instances all sharing the same host function. 709 dtor: Arc<crate::func::HostFunc>, 710 711 // A raw function which is filled out (including `wasm_call`) which 712 // points to the internals of the `_dtor` field. This is read and 713 // possibly executed by wasm. 714 dtor_funcref: VMFuncRef, 715 }, 716 } 717 718 pub type ImportedResources = PrimaryMap<ResourceIndex, ResourceType>; 719 720 impl<'a> Instantiator<'a> { 721 fn new( 722 component: &'a Component, 723 store: &mut StoreOpaque, 724 imports: &'a Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 725 ) -> Result<Instantiator<'a>> { 726 let env_component = component.env_component(); 727 let (modules, engine, breakpoints) = store.modules_and_engine_and_breakpoints_mut(); 728 modules.register_component(component, engine, breakpoints)?; 729 let imported_resources: ImportedResources = 730 PrimaryMap::with_capacity(env_component.imported_resources.len()); 731 732 let instance = ComponentInstance::new( 733 store.store_data().components.next_component_instance_id(), 734 component, 735 Arc::new(imported_resources), 736 imports, 737 store.traitobj(), 738 )?; 739 let id = store.store_data_mut().push_component_instance(instance); 740 741 Ok(Instantiator { 742 component, 743 imports, 744 core_imports: OwnedImports::empty(), 745 id, 746 }) 747 } 748 749 async fn run<T>( 750 &mut self, 751 store: &mut StoreContextMut<'_, T>, 752 asyncness: Asyncness, 753 ) -> Result<()> { 754 let env_component = self.component.env_component(); 755 756 // Before all initializers are processed configure all destructors for 757 // host-defined resources. No initializer will correspond to these and 758 // it's required to happen before they're needed, so execute this first. 759 for (idx, import) in env_component.imported_resources.iter() { 760 let (ty, func_ref) = match &self.imports[*import] { 761 RuntimeImport::Resource { 762 ty, dtor_funcref, .. 763 } => (*ty, NonNull::from(dtor_funcref)), 764 _ => unreachable!(), 765 }; 766 let i = self.instance_resource_types_mut(store.0).push(ty); 767 assert_eq!(i, idx); 768 self.instance_mut(store.0) 769 .set_resource_destructor(idx, Some(func_ref)); 770 } 771 772 // Next configure all `VMFuncRef`s for trampolines that this component 773 // will require. These functions won't actually get used until their 774 // associated state has been initialized through the global initializers 775 // below, but the funcrefs can all be configured here. 776 for (idx, sig) in env_component.trampolines.iter() { 777 let ptrs = self.component.trampoline_ptrs(idx); 778 let signature = match self.component.signatures().shared_type(*sig) { 779 Some(s) => s, 780 None => panic!("found unregistered signature: {sig:?}"), 781 }; 782 783 self.instance_mut(store.0).set_trampoline( 784 idx, 785 ptrs.wasm_call, 786 ptrs.array_call, 787 signature, 788 ); 789 } 790 791 // Initialize the unsafe intrinsics used by this component, if any. 792 for (i, module_ty) in env_component 793 .unsafe_intrinsics 794 .iter() 795 .enumerate() 796 .filter_map(|(i, ty)| ty.expand().map(|ty| (i, ty))) 797 { 798 let i = u32::try_from(i).unwrap(); 799 let intrinsic = UnsafeIntrinsic::from_u32(i); 800 let ptrs = self.component.unsafe_intrinsic_ptrs(intrinsic).expect( 801 "should have intrinsic pointers given that we assigned the intrinsic a type", 802 ); 803 let shared_ty = self 804 .component 805 .signatures() 806 .shared_type(module_ty) 807 .expect("should have a shared type"); 808 self.instance_mut(store.0).set_intrinsic( 809 intrinsic, 810 ptrs.wasm_call, 811 ptrs.array_call, 812 shared_ty, 813 ); 814 } 815 816 for initializer in env_component.initializers.iter() { 817 match initializer { 818 GlobalInitializer::InstantiateModule(m, component_instance) => { 819 let instance = self.id; 820 let module; 821 let imports = match m { 822 // Since upvars are statically know we know that the 823 // `args` list is already in the right order. 824 InstantiateModule::Static(idx, args) => { 825 module = self.component.static_module(*idx); 826 self.build_imports(store.0, module, args.iter())? 827 } 828 829 // With imports, unlike upvars, we need to do runtime 830 // lookups with strings to determine the order of the 831 // imports since it's whatever the actual module 832 // requires. 833 // 834 // FIXME: see the note in `ExportItem::Name` handling 835 // above for how we ideally shouldn't do string lookup 836 // here. 837 InstantiateModule::Import(idx, args) => { 838 module = match &self.imports[*idx] { 839 RuntimeImport::Module(m) => m, 840 _ => unreachable!(), 841 }; 842 let args = module 843 .imports() 844 .map(|import| &args[import.module()][import.name()]); 845 self.build_imports(store.0, module, args)? 846 } 847 }; 848 849 let exit = if let Some(component_instance) = *component_instance { 850 store.0.enter_guest_sync_call( 851 None, 852 false, 853 RuntimeInstance { 854 instance, 855 index: component_instance, 856 }, 857 )?; 858 true 859 } else { 860 false 861 }; 862 863 // Note that the unsafety here should be ok because the 864 // validity of the component means that type-checks have 865 // already been performed. This means that the unsafety due 866 // to imports having the wrong type should not happen here. 867 // 868 // Also note we are calling new_started_impl because we have 869 // already checked for asyncness and are running on a fiber 870 // if required. 871 872 let i = unsafe { 873 crate::Instance::new_started(store, module, imports.as_ref(), asyncness) 874 .await? 875 }; 876 877 if exit { 878 store.0.exit_guest_sync_call()?; 879 } 880 881 self.instance_mut(store.0).push_instance_id(i.id()); 882 } 883 884 GlobalInitializer::LowerImport { import, index } => { 885 let func = match &self.imports[*import] { 886 RuntimeImport::Func(func) => func, 887 _ => unreachable!(), 888 }; 889 self.instance_mut(store.0) 890 .set_lowering(*index, func.lowering()); 891 } 892 893 GlobalInitializer::ExtractTable(table) => self.extract_table(store.0, table), 894 895 GlobalInitializer::ExtractMemory(mem) => self.extract_memory(store.0, mem), 896 897 GlobalInitializer::ExtractRealloc(realloc) => { 898 self.extract_realloc(store.0, realloc) 899 } 900 901 GlobalInitializer::ExtractCallback(callback) => { 902 self.extract_callback(store.0, callback) 903 } 904 905 GlobalInitializer::ExtractPostReturn(post_return) => { 906 self.extract_post_return(store.0, post_return) 907 } 908 909 GlobalInitializer::Resource(r) => self.resource(store.0, r), 910 } 911 } 912 Ok(()) 913 } 914 915 fn resource(&mut self, store: &mut StoreOpaque, resource: &Resource) { 916 let dtor = resource 917 .dtor 918 .as_ref() 919 .map(|dtor| lookup_vmdef(store, self.id, dtor)); 920 let dtor = dtor.map(|export| match export { 921 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 922 _ => unreachable!(), 923 }); 924 let index = self 925 .component 926 .env_component() 927 .resource_index(resource.index); 928 let instance = self.instance(store); 929 let ty = ResourceType::guest(store.id(), instance, resource.index); 930 self.instance_mut(store) 931 .set_resource_destructor(index, dtor); 932 let i = self.instance_resource_types_mut(store).push(ty); 933 debug_assert_eq!(i, index); 934 } 935 936 fn extract_memory(&mut self, store: &mut StoreOpaque, memory: &ExtractMemory) { 937 let import = match lookup_vmexport(store, self.id, &memory.export) { 938 crate::runtime::vm::Export::Memory(memory) => memory.vmimport(store), 939 crate::runtime::vm::Export::SharedMemory(_, import) => import, 940 _ => unreachable!(), 941 }; 942 self.instance_mut(store) 943 .set_runtime_memory(memory.index, import.from.as_non_null()); 944 } 945 946 fn extract_realloc(&mut self, store: &mut StoreOpaque, realloc: &ExtractRealloc) { 947 let func_ref = match lookup_vmdef(store, self.id, &realloc.def) { 948 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 949 _ => unreachable!(), 950 }; 951 self.instance_mut(store) 952 .set_runtime_realloc(realloc.index, func_ref); 953 } 954 955 fn extract_callback(&mut self, store: &mut StoreOpaque, callback: &ExtractCallback) { 956 let func_ref = match lookup_vmdef(store, self.id, &callback.def) { 957 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 958 _ => unreachable!(), 959 }; 960 self.instance_mut(store) 961 .set_runtime_callback(callback.index, func_ref); 962 } 963 964 fn extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn) { 965 let func_ref = match lookup_vmdef(store, self.id, &post_return.def) { 966 crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store), 967 _ => unreachable!(), 968 }; 969 self.instance_mut(store) 970 .set_runtime_post_return(post_return.index, func_ref); 971 } 972 973 fn extract_table(&mut self, store: &mut StoreOpaque, table: &ExtractTable) { 974 let export = match lookup_vmexport(store, self.id, &table.export) { 975 crate::runtime::vm::Export::Table(t) => t, 976 _ => unreachable!(), 977 }; 978 let import = export.vmimport(store); 979 self.instance_mut(store) 980 .set_runtime_table(table.index, import); 981 } 982 983 fn build_imports<'b>( 984 &mut self, 985 store: &mut StoreOpaque, 986 module: &Module, 987 args: impl Iterator<Item = &'b CoreDef>, 988 ) -> Result<&OwnedImports, OutOfMemory> { 989 self.core_imports.clear(); 990 self.core_imports.reserve(module)?; 991 let mut imports = module.compiled_module().module().imports(); 992 993 for arg in args { 994 // The general idea of Wasmtime is that at runtime type-checks for 995 // core wasm instantiations internally within a component are 996 // unnecessary and superfluous. Naturally though mistakes may be 997 // made, so double-check this property of wasmtime in debug mode. 998 999 if cfg!(debug_assertions) { 1000 let (imp_module, imp_name, expected) = imports.next().unwrap(); 1001 self.assert_type_matches(store, module, arg, imp_module, imp_name, expected); 1002 } 1003 1004 // The unsafety here should be ok since the `export` is loaded 1005 // directly from an instance which should only give us valid export 1006 // items. 1007 let export = lookup_vmdef(store, self.id, arg); 1008 self.core_imports.push_export(store, &export)?; 1009 } 1010 debug_assert!(imports.next().is_none()); 1011 1012 Ok(&self.core_imports) 1013 } 1014 1015 fn assert_type_matches( 1016 &self, 1017 store: &mut StoreOpaque, 1018 module: &Module, 1019 arg: &CoreDef, 1020 imp_module: &str, 1021 imp_name: &str, 1022 expected: EntityType, 1023 ) { 1024 let export = lookup_vmdef(store, self.id, arg); 1025 1026 // If this value is a core wasm function then the type check is inlined 1027 // here. This can otherwise fail `Extern::from_wasmtime_export` because 1028 // there's no guarantee that there exists a trampoline for `f` so this 1029 // can't fall through to the case below 1030 if let crate::runtime::vm::Export::Function(f) = &export { 1031 let expected = match expected.unwrap_func() { 1032 EngineOrModuleTypeIndex::Engine(e) => Some(e), 1033 EngineOrModuleTypeIndex::Module(m) => module.signatures().shared_type(m), 1034 EngineOrModuleTypeIndex::RecGroup(_) => unreachable!(), 1035 }; 1036 let actual = unsafe { f.vm_func_ref(store).as_ref().type_index }; 1037 assert_eq!( 1038 expected, 1039 Some(actual), 1040 "type mismatch for import {imp_module:?} {imp_name:?}!!!\n\n\ 1041 expected {:#?}\n\n\ 1042 found {:#?}", 1043 expected.and_then(|e| store.engine().signatures().borrow(e)), 1044 store.engine().signatures().borrow(actual) 1045 ); 1046 return; 1047 } 1048 1049 let val = crate::Extern::from_wasmtime_export(export, store); 1050 let ty = DefinitionType::from(store, &val); 1051 crate::types::matching::MatchCx::new(module.engine()) 1052 .definition(&expected, &ty) 1053 .expect("unexpected typecheck failure"); 1054 } 1055 1056 /// Convenience helper to return the `&ComponentInstance` that's being 1057 /// instantiated. 1058 fn instance<'b>(&self, store: &'b StoreOpaque) -> &'b ComponentInstance { 1059 store.store_data().component_instance(self.id) 1060 } 1061 1062 /// Same as [`Self::instance`], but for mutability. 1063 fn instance_mut<'b>(&self, store: &'b mut StoreOpaque) -> Pin<&'b mut ComponentInstance> { 1064 store.store_data_mut().component_instance_mut(self.id) 1065 } 1066 1067 // NB: This method is only intended to be called during the instantiation 1068 // process because the `Arc::get_mut` here is fallible and won't generally 1069 // succeed once the instance has been handed to the embedder. Before that 1070 // though it should be guaranteed that the single owning reference currently 1071 // lives within the `ComponentInstance` that's being built. 1072 fn instance_resource_types_mut<'b>( 1073 &self, 1074 store: &'b mut StoreOpaque, 1075 ) -> &'b mut ImportedResources { 1076 Arc::get_mut(self.instance_mut(store).resource_types_mut()).unwrap() 1077 } 1078 } 1079 1080 /// A "pre-instantiated" [`Instance`] which has all of its arguments already 1081 /// supplied and is ready to instantiate. 1082 /// 1083 /// This structure represents an efficient form of instantiation where import 1084 /// type-checking and import lookup has all been resolved by the time that this 1085 /// type is created. This type is primarily created through the 1086 /// [`Linker::instantiate_pre`](crate::component::Linker::instantiate_pre) 1087 /// method. 1088 pub struct InstancePre<T: 'static> { 1089 component: Component, 1090 imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 1091 resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>, 1092 asyncness: Asyncness, 1093 _marker: marker::PhantomData<fn() -> T>, 1094 } 1095 1096 // `InstancePre`'s clone does not require `T: Clone` 1097 impl<T: 'static> Clone for InstancePre<T> { 1098 fn clone(&self) -> Self { 1099 Self { 1100 component: self.component.clone(), 1101 imports: self.imports.clone(), 1102 resource_types: self.resource_types.clone(), 1103 asyncness: self.asyncness, 1104 _marker: self._marker, 1105 } 1106 } 1107 } 1108 1109 impl<T: 'static> InstancePre<T> { 1110 /// This function is `unsafe` since there's no guarantee that the 1111 /// `RuntimeImport` items provided are guaranteed to work with the `T` of 1112 /// the store. 1113 /// 1114 /// Additionally there is no static guarantee that the `imports` provided 1115 /// satisfy the imports of the `component` provided. 1116 pub(crate) unsafe fn new_unchecked( 1117 component: Component, 1118 imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 1119 resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>, 1120 ) -> InstancePre<T> { 1121 let mut asyncness = Asyncness::No; 1122 for (_, import) in imports.iter() { 1123 asyncness = asyncness 1124 | match import { 1125 RuntimeImport::Func(f) => f.asyncness(), 1126 RuntimeImport::Module(_) => Asyncness::No, 1127 RuntimeImport::Resource { dtor, .. } => dtor.asyncness(), 1128 }; 1129 } 1130 InstancePre { 1131 component, 1132 imports, 1133 resource_types, 1134 asyncness, 1135 _marker: marker::PhantomData, 1136 } 1137 } 1138 1139 /// Returns the underlying component that will be instantiated. 1140 pub fn component(&self) -> &Component { 1141 &self.component 1142 } 1143 1144 #[doc(hidden)] 1145 /// Returns the type at which the underlying component will be 1146 /// instantiated. This contains the instantiated type information which 1147 /// was determined by the Linker. 1148 pub fn instance_type(&self) -> InstanceType<'_> { 1149 InstanceType { 1150 types: &self.component.types(), 1151 resources: &self.resource_types, 1152 } 1153 } 1154 1155 /// Returns the underlying engine. 1156 pub fn engine(&self) -> &Engine { 1157 self.component.engine() 1158 } 1159 1160 /// Performs the instantiation process into the store specified. 1161 // 1162 // TODO: needs more docs 1163 pub fn instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> { 1164 let store = store.as_context_mut(); 1165 1166 // If this instance requires an async host, set that flag in the store, 1167 // and then afterwards assert nothing else in the store, nor this 1168 // instance, required async. 1169 store.0.set_async_required(self.asyncness); 1170 store.0.validate_sync_call()?; 1171 1172 vm::assert_ready(self._instantiate(store, Asyncness::No)) 1173 } 1174 /// Performs the instantiation process into the store specified. 1175 /// 1176 /// Exactly like [`Self::instantiate`] except for use on async stores. 1177 // 1178 // TODO: needs more docs 1179 #[cfg(feature = "async")] 1180 pub async fn instantiate_async(&self, store: impl AsContextMut<Data = T>) -> Result<Instance> { 1181 self._instantiate(store, Asyncness::Yes).await 1182 } 1183 1184 async fn _instantiate( 1185 &self, 1186 mut store: impl AsContextMut<Data = T>, 1187 asyncness: Asyncness, 1188 ) -> Result<Instance> { 1189 let mut store = store.as_context_mut(); 1190 store.0.set_async_required(self.asyncness); 1191 store 1192 .engine() 1193 .allocator() 1194 .increment_component_instance_count()?; 1195 let mut instantiator = Instantiator::new(&self.component, store.0, &self.imports)?; 1196 instantiator.run(&mut store, asyncness).await.map_err(|e| { 1197 store 1198 .engine() 1199 .allocator() 1200 .decrement_component_instance_count(); 1201 e 1202 })?; 1203 1204 let instance = Instance::from_wasmtime(store.0, instantiator.id); 1205 store.0.push_component_instance(instance); 1206 Ok(instance) 1207 } 1208 } 1209