1 use crate::component::func::HostFunc; 2 use crate::component::matching::InstanceType; 3 use crate::component::{ 4 Component, ComponentExportIndex, ComponentNamedList, Func, Lift, Lower, ResourceType, TypedFunc, 5 }; 6 use crate::instance::OwnedImports; 7 use crate::linker::DefinitionType; 8 use crate::prelude::*; 9 use crate::runtime::vm::component::{ComponentInstance, OwnedComponentInstance}; 10 use crate::runtime::vm::{CompiledModuleId, VMFuncRef}; 11 use crate::store::{StoreOpaque, Stored}; 12 use crate::{AsContextMut, Engine, Module, StoreContextMut}; 13 use alloc::sync::Arc; 14 use core::marker; 15 use core::ptr::NonNull; 16 use wasmtime_environ::{component::*, EngineOrModuleTypeIndex}; 17 use wasmtime_environ::{EntityIndex, EntityType, Global, PrimaryMap, WasmValType}; 18 19 /// An instantiated component. 20 /// 21 /// This type represents an instantiated [`Component`](super::Component). 22 /// Instances have exports which can be accessed through functions such as 23 /// [`Instance::get_func`] or [`Instance::get_export`]. Instances are owned by a 24 /// [`Store`](crate::Store) and all methods require a handle to the store. 25 /// 26 /// Component instances are created through 27 /// [`Linker::instantiate`](super::Linker::instantiate) and its family of 28 /// methods. 29 /// 30 /// This type is similar to the core wasm version 31 /// [`wasmtime::Instance`](crate::Instance) except that it represents an 32 /// instantiated component instead of an instantiated module. 33 #[derive(Copy, Clone)] 34 pub struct Instance(pub(crate) Stored<Option<Box<InstanceData>>>); 35 36 pub(crate) struct InstanceData { 37 instances: PrimaryMap<RuntimeInstanceIndex, crate::Instance>, 38 39 // NB: in the future if necessary it would be possible to avoid storing an 40 // entire `Component` here and instead storing only information such as: 41 // 42 // * Some reference to `Arc<ComponentTypes>` 43 // * Necessary references to closed-over modules which are exported from the 44 // component itself. 45 // 46 // Otherwise the full guts of this component should only ever be used during 47 // the instantiation of this instance, meaning that after instantiation much 48 // of the component can be thrown away (theoretically). 49 component: Component, 50 51 state: OwnedComponentInstance, 52 53 /// Arguments that this instance used to be instantiated. 54 /// 55 /// Strong references are stored to these arguments since pointers are saved 56 /// into the structures such as functions within the 57 /// `OwnedComponentInstance` but it's our job to keep them alive. 58 /// 59 /// One purpose of this storage is to enable embedders to drop a `Linker`, 60 /// for example, after a component is instantiated. In that situation if the 61 /// arguments weren't held here then they might be dropped, and structures 62 /// such as `.lowering()` which point back into the original function would 63 /// become stale and use-after-free conditions when used. By preserving the 64 /// entire list here though we're guaranteed that nothing is lost for the 65 /// duration of the lifetime of this instance. 66 imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 67 } 68 69 impl Instance { 70 /// Looks up an exported function by name within this [`Instance`]. 71 /// 72 /// The `store` argument provided must be the store that this instance 73 /// lives within and the `name` argument is the lookup key by which to find 74 /// the exported function. If the function is found then `Some` is returned 75 /// and otherwise `None` is returned. 76 /// 77 /// The `name` here can be a string such as `&str` or it can be a 78 /// [`ComponentExportIndex`] which is loaded prior from a [`Component`]. 79 /// 80 /// # Panics 81 /// 82 /// Panics if `store` does not own this instance. 83 /// 84 /// # Examples 85 /// 86 /// Looking up a function which is exported from the root of a component: 87 /// 88 /// ``` 89 /// use wasmtime::{Engine, Store}; 90 /// use wasmtime::component::{Component, Linker}; 91 /// 92 /// # fn main() -> wasmtime::Result<()> { 93 /// let engine = Engine::default(); 94 /// let component = Component::new( 95 /// &engine, 96 /// r#" 97 /// (component 98 /// (core module $m 99 /// (func (export "f")) 100 /// ) 101 /// (core instance $i (instantiate $m)) 102 /// (func (export "f") 103 /// (canon lift (core func $i "f"))) 104 /// ) 105 /// "#, 106 /// )?; 107 /// 108 /// // Look up the function by name 109 /// let mut store = Store::new(&engine, ()); 110 /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 111 /// let func = instance.get_func(&mut store, "f").unwrap(); 112 /// 113 /// // The function can also be looked up by an index via a precomputed index. 114 /// let (_, export) = component.export_index(None, "f").unwrap(); 115 /// let func = instance.get_func(&mut store, &export).unwrap(); 116 /// # Ok(()) 117 /// # } 118 /// ``` 119 /// 120 /// Looking up a function which is exported from a nested instance: 121 /// 122 /// ``` 123 /// use wasmtime::{Engine, Store}; 124 /// use wasmtime::component::{Component, Linker}; 125 /// 126 /// # fn main() -> wasmtime::Result<()> { 127 /// let engine = Engine::default(); 128 /// let component = Component::new( 129 /// &engine, 130 /// r#" 131 /// (component 132 /// (core module $m 133 /// (func (export "f")) 134 /// ) 135 /// (core instance $i (instantiate $m)) 136 /// (func $f 137 /// (canon lift (core func $i "f"))) 138 /// 139 /// (instance $i 140 /// (export "f" (func $f))) 141 /// (export "i" (instance $i)) 142 /// ) 143 /// "#, 144 /// )?; 145 /// 146 /// // First look up the exported instance, then use that to lookup the 147 /// // exported function. 148 /// let (_, instance_index) = component.export_index(None, "i").unwrap(); 149 /// let (_, func_index) = component.export_index(Some(&instance_index), "f").unwrap(); 150 /// 151 /// // Then use `func_index` at runtime. 152 /// let mut store = Store::new(&engine, ()); 153 /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?; 154 /// let func = instance.get_func(&mut store, &func_index).unwrap(); 155 /// 156 /// // Alternatively the `instance` can be used directly in conjunction with 157 /// // the `get_export` method. 158 /// let instance_index = instance.get_export(&mut store, None, "i").unwrap(); 159 /// let func_index = instance.get_export(&mut store, Some(&instance_index), "f").unwrap(); 160 /// let func = instance.get_func(&mut store, &func_index).unwrap(); 161 /// # Ok(()) 162 /// # } 163 /// ``` 164 pub fn get_func( 165 &self, 166 mut store: impl AsContextMut, 167 name: impl InstanceExportLookup, 168 ) -> Option<Func> { 169 let store = store.as_context_mut().0; 170 let data = store[self.0].take().unwrap(); 171 let ret = name.lookup(&data.component).and_then(|index| { 172 match &data.component.env_component().export_items[index] { 173 Export::LiftedFunction { ty, func, options } => Some(Func::from_lifted_func( 174 store, self, &data, *ty, func, options, 175 )), 176 _ => None, 177 } 178 }); 179 store[self.0] = Some(data); 180 ret 181 } 182 183 /// Looks up an exported [`Func`] value by name and with its type. 184 /// 185 /// This function is a convenience wrapper over [`Instance::get_func`] and 186 /// [`Func::typed`]. For more information see the linked documentation. 187 /// 188 /// Returns an error if `name` isn't a function export or if the export's 189 /// type did not match `Params` or `Results` 190 /// 191 /// # Panics 192 /// 193 /// Panics if `store` does not own this instance. 194 pub fn get_typed_func<Params, Results>( 195 &self, 196 mut store: impl AsContextMut, 197 name: impl InstanceExportLookup, 198 ) -> Result<TypedFunc<Params, Results>> 199 where 200 Params: ComponentNamedList + Lower, 201 Results: ComponentNamedList + Lift, 202 { 203 let f = self 204 .get_func(store.as_context_mut(), name) 205 .ok_or_else(|| anyhow!("failed to find function export"))?; 206 Ok(f.typed::<Params, Results>(store) 207 .with_context(|| format!("failed to convert function to given type"))?) 208 } 209 210 /// Looks up an exported module by name within this [`Instance`]. 211 /// 212 /// The `store` argument provided must be the store that this instance 213 /// lives within and the `name` argument is the lookup key by which to find 214 /// the exported module. If the module is found then `Some` is returned 215 /// and otherwise `None` is returned. 216 /// 217 /// The `name` here can be a string such as `&str` or it can be a 218 /// [`ComponentExportIndex`] which is loaded prior from a [`Component`]. 219 /// 220 /// For some examples see [`Instance::get_func`] for loading values from a 221 /// component. 222 /// 223 /// # Panics 224 /// 225 /// Panics if `store` does not own this instance. 226 pub fn get_module( 227 &self, 228 mut store: impl AsContextMut, 229 name: impl InstanceExportLookup, 230 ) -> Option<Module> { 231 let store = store.as_context_mut().0; 232 let (data, export, _) = self.lookup_export(store, name)?; 233 match export { 234 Export::ModuleStatic { index, .. } => { 235 Some(data.component.static_module(*index).clone()) 236 } 237 Export::ModuleImport { import, .. } => match &data.imports[*import] { 238 RuntimeImport::Module(m) => Some(m.clone()), 239 _ => unreachable!(), 240 }, 241 _ => None, 242 } 243 } 244 245 /// Looks up an exported resource type by name within this [`Instance`]. 246 /// 247 /// The `store` argument provided must be the store that this instance 248 /// lives within and the `name` argument is the lookup key by which to find 249 /// the exported resource. If the resource is found then `Some` is returned 250 /// and otherwise `None` is returned. 251 /// 252 /// The `name` here can be a string such as `&str` or it can be a 253 /// [`ComponentExportIndex`] which is loaded prior from a [`Component`]. 254 /// 255 /// For some examples see [`Instance::get_func`] for loading values from a 256 /// component. 257 /// 258 /// # Panics 259 /// 260 /// Panics if `store` does not own this instance. 261 pub fn get_resource( 262 &self, 263 mut store: impl AsContextMut, 264 name: impl InstanceExportLookup, 265 ) -> Option<ResourceType> { 266 let store = store.as_context_mut().0; 267 let (data, export, _) = self.lookup_export(store, name)?; 268 match export { 269 Export::Type(TypeDef::Resource(id)) => Some(data.ty().resource_type(*id)), 270 Export::Type(_) 271 | Export::LiftedFunction { .. } 272 | Export::ModuleStatic { .. } 273 | Export::ModuleImport { .. } 274 | Export::Instance { .. } => None, 275 } 276 } 277 278 /// A methods similar to [`Component::export_index`] except for this 279 /// instance. 280 /// 281 /// This method will lookup the `name` provided within the `instance` 282 /// provided and return a [`ComponentExportIndex`] which can be used to 283 /// pass to other `get_*` functions like [`Instance::get_func`]. 284 /// 285 /// # Panics 286 /// 287 /// Panics if `store` does not own this instance. 288 pub fn get_export( 289 &self, 290 mut store: impl AsContextMut, 291 instance: Option<&ComponentExportIndex>, 292 name: &str, 293 ) -> Option<ComponentExportIndex> { 294 self._get_export(store.as_context_mut().0, instance, name) 295 } 296 297 fn _get_export( 298 &self, 299 store: &StoreOpaque, 300 instance: Option<&ComponentExportIndex>, 301 name: &str, 302 ) -> Option<ComponentExportIndex> { 303 let data = store[self.0].as_ref().unwrap(); 304 let index = data.component.lookup_export_index(instance, name)?; 305 Some(ComponentExportIndex { 306 id: data.component_id(), 307 index, 308 }) 309 } 310 311 fn lookup_export<'a>( 312 &self, 313 store: &'a StoreOpaque, 314 name: impl InstanceExportLookup, 315 ) -> Option<(&'a InstanceData, &'a Export, ExportIndex)> { 316 let data = store[self.0].as_ref().unwrap(); 317 let index = name.lookup(&data.component)?; 318 Some(( 319 data, 320 &data.component.env_component().export_items[index], 321 index, 322 )) 323 } 324 } 325 326 /// Trait used to lookup the export of a component instance. 327 /// 328 /// This trait is used as an implementation detail of [`Instance::get_func`] 329 /// and related `get_*` methods. Notable implementors of this trait are: 330 /// 331 /// * `str` 332 /// * `String` 333 /// * [`ComponentExportIndex`] 334 /// 335 /// Note that this is intended to be a `wasmtime`-sealed trait so it shouldn't 336 /// need to be implemented externally. 337 pub trait InstanceExportLookup { 338 #[doc(hidden)] 339 fn lookup(&self, component: &Component) -> Option<ExportIndex>; 340 } 341 342 impl<T> InstanceExportLookup for &T 343 where 344 T: InstanceExportLookup + ?Sized, 345 { 346 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 347 T::lookup(self, component) 348 } 349 } 350 351 impl InstanceExportLookup for str { 352 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 353 component 354 .env_component() 355 .exports 356 .get(self, &NameMapNoIntern) 357 .copied() 358 } 359 } 360 361 impl InstanceExportLookup for String { 362 fn lookup(&self, component: &Component) -> Option<ExportIndex> { 363 str::lookup(self, component) 364 } 365 } 366 367 impl InstanceData { 368 pub fn lookup_def(&self, store: &mut StoreOpaque, def: &CoreDef) -> crate::runtime::vm::Export { 369 match def { 370 CoreDef::Export(e) => self.lookup_export(store, e), 371 CoreDef::Trampoline(idx) => { 372 crate::runtime::vm::Export::Function(crate::runtime::vm::ExportFunction { 373 func_ref: self.state.trampoline_func_ref(*idx), 374 }) 375 } 376 CoreDef::InstanceFlags(idx) => { 377 crate::runtime::vm::Export::Global(crate::runtime::vm::ExportGlobal { 378 definition: self.state.instance_flags(*idx).as_raw(), 379 vmctx: None, 380 global: Global { 381 wasm_ty: WasmValType::I32, 382 mutability: true, 383 }, 384 }) 385 } 386 } 387 } 388 389 pub fn lookup_export<T>( 390 &self, 391 store: &mut StoreOpaque, 392 item: &CoreExport<T>, 393 ) -> crate::runtime::vm::Export 394 where 395 T: Copy + Into<EntityIndex>, 396 { 397 let instance = &self.instances[item.instance]; 398 let id = instance.id(store); 399 let instance = store.instance_mut(id); 400 let idx = match &item.item { 401 ExportItem::Index(idx) => (*idx).into(), 402 403 // FIXME: ideally at runtime we don't actually do any name lookups 404 // here. This will only happen when the host supplies an imported 405 // module so while the structure can't be known at compile time we 406 // do know at `InstancePre` time, for example, what all the host 407 // imports are. In theory we should be able to, as part of 408 // `InstancePre` construction, perform all name=>index mappings 409 // during that phase so the actual instantiation of an `InstancePre` 410 // skips all string lookups. This should probably only be 411 // investigated if this becomes a performance issue though. 412 ExportItem::Name(name) => instance.module().exports[name], 413 }; 414 instance.get_export_by_index(idx) 415 } 416 417 #[inline] 418 pub fn instance(&self) -> &ComponentInstance { 419 &self.state 420 } 421 422 #[inline] 423 pub fn instance_ptr(&self) -> *mut ComponentInstance { 424 self.state.instance_ptr() 425 } 426 427 #[inline] 428 pub fn component_types(&self) -> &Arc<ComponentTypes> { 429 self.component.types() 430 } 431 432 #[inline] 433 pub fn component_id(&self) -> CompiledModuleId { 434 self.component.id() 435 } 436 437 #[inline] 438 pub fn ty(&self) -> InstanceType<'_> { 439 InstanceType::new(self.instance()) 440 } 441 442 // NB: This method is only intended to be called during the instantiation 443 // process because the `Arc::get_mut` here is fallible and won't generally 444 // succeed once the instance has been handed to the embedder. Before that 445 // though it should be guaranteed that the single owning reference currently 446 // lives within the `ComponentInstance` that's being built. 447 fn resource_types_mut(&mut self) -> &mut ImportedResources { 448 Arc::get_mut(self.state.resource_types_mut()) 449 .unwrap() 450 .downcast_mut() 451 .unwrap() 452 } 453 } 454 455 struct Instantiator<'a> { 456 component: &'a Component, 457 data: InstanceData, 458 core_imports: OwnedImports, 459 imports: &'a PrimaryMap<RuntimeImportIndex, RuntimeImport>, 460 } 461 462 pub(crate) enum RuntimeImport { 463 Func(Arc<HostFunc>), 464 Module(Module), 465 Resource { 466 ty: ResourceType, 467 468 // A strong reference to the host function that represents the 469 // destructor for this resource. At this time all resources here are 470 // host-defined resources. Note that this is itself never read because 471 // the funcref below points to it. 472 // 473 // Also note that the `Arc` here is used to support the same host 474 // function being used across multiple instances simultaneously. Or 475 // otherwise this makes `InstancePre::instantiate` possible to create 476 // separate instances all sharing the same host function. 477 _dtor: Arc<crate::func::HostFunc>, 478 479 // A raw function which is filled out (including `wasm_call`) which 480 // points to the internals of the `_dtor` field. This is read and 481 // possibly executed by wasm. 482 dtor_funcref: VMFuncRef, 483 }, 484 } 485 486 pub type ImportedResources = PrimaryMap<ResourceIndex, ResourceType>; 487 488 impl<'a> Instantiator<'a> { 489 fn new( 490 component: &'a Component, 491 store: &mut StoreOpaque, 492 imports: &'a Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 493 ) -> Instantiator<'a> { 494 let env_component = component.env_component(); 495 store.modules_mut().register_component(component); 496 let imported_resources: ImportedResources = 497 PrimaryMap::with_capacity(env_component.imported_resources.len()); 498 Instantiator { 499 component, 500 imports, 501 core_imports: OwnedImports::empty(), 502 data: InstanceData { 503 instances: PrimaryMap::with_capacity(env_component.num_runtime_instances as usize), 504 component: component.clone(), 505 state: OwnedComponentInstance::new( 506 component.runtime_info(), 507 Arc::new(imported_resources), 508 store.traitobj(), 509 ), 510 imports: imports.clone(), 511 }, 512 } 513 } 514 515 fn run<T>(&mut self, store: &mut StoreContextMut<'_, T>) -> Result<()> { 516 let env_component = self.component.env_component(); 517 518 // Before all initializers are processed configure all destructors for 519 // host-defined resources. No initializer will correspond to these and 520 // it's required to happen before they're needed, so execute this first. 521 for (idx, import) in env_component.imported_resources.iter() { 522 let (ty, func_ref) = match &self.imports[*import] { 523 RuntimeImport::Resource { 524 ty, dtor_funcref, .. 525 } => (*ty, NonNull::from(dtor_funcref)), 526 _ => unreachable!(), 527 }; 528 let i = self.data.resource_types_mut().push(ty); 529 assert_eq!(i, idx); 530 self.data.state.set_resource_destructor(idx, Some(func_ref)); 531 } 532 533 // Next configure all `VMFuncRef`s for trampolines that this component 534 // will require. These functions won't actually get used until their 535 // associated state has been initialized through the global initializers 536 // below, but the funcrefs can all be configured here. 537 for (idx, sig) in env_component.trampolines.iter() { 538 let ptrs = self.component.trampoline_ptrs(idx); 539 let signature = match self.component.signatures().shared_type(*sig) { 540 Some(s) => s, 541 None => panic!("found unregistered signature: {sig:?}"), 542 }; 543 544 self.data 545 .state 546 .set_trampoline(idx, ptrs.wasm_call, ptrs.array_call, signature); 547 } 548 549 for initializer in env_component.initializers.iter() { 550 match initializer { 551 GlobalInitializer::InstantiateModule(m) => { 552 let module; 553 let imports = match m { 554 // Since upvars are statically know we know that the 555 // `args` list is already in the right order. 556 InstantiateModule::Static(idx, args) => { 557 module = self.component.static_module(*idx); 558 self.build_imports(store.0, module, args.iter()) 559 } 560 561 // With imports, unlike upvars, we need to do runtime 562 // lookups with strings to determine the order of the 563 // imports since it's whatever the actual module 564 // requires. 565 // 566 // FIXME: see the note in `ExportItem::Name` handling 567 // above for how we ideally shouldn't do string lookup 568 // here. 569 InstantiateModule::Import(idx, args) => { 570 module = match &self.imports[*idx] { 571 RuntimeImport::Module(m) => m, 572 _ => unreachable!(), 573 }; 574 let args = module 575 .imports() 576 .map(|import| &args[import.module()][import.name()]); 577 self.build_imports(store.0, module, args) 578 } 579 }; 580 581 // Note that the unsafety here should be ok because the 582 // validity of the component means that type-checks have 583 // already been performed. This means that the unsafety due 584 // to imports having the wrong type should not happen here. 585 // 586 // Also note we are calling new_started_impl because we have 587 // already checked for asyncness and are running on a fiber 588 // if required. 589 590 let i = unsafe { 591 crate::Instance::new_started_impl(store, module, imports.as_ref())? 592 }; 593 self.data.instances.push(i); 594 } 595 596 GlobalInitializer::LowerImport { import, index } => { 597 let func = match &self.imports[*import] { 598 RuntimeImport::Func(func) => func, 599 _ => unreachable!(), 600 }; 601 self.data.state.set_lowering(*index, func.lowering()); 602 } 603 604 GlobalInitializer::ExtractMemory(mem) => self.extract_memory(store.0, mem), 605 606 GlobalInitializer::ExtractRealloc(realloc) => { 607 self.extract_realloc(store.0, realloc) 608 } 609 610 GlobalInitializer::ExtractCallback(callback) => { 611 self.extract_callback(store.0, callback) 612 } 613 614 GlobalInitializer::ExtractPostReturn(post_return) => { 615 self.extract_post_return(store.0, post_return) 616 } 617 618 GlobalInitializer::Resource(r) => self.resource(store.0, r), 619 } 620 } 621 Ok(()) 622 } 623 624 fn resource(&mut self, store: &mut StoreOpaque, resource: &Resource) { 625 let dtor = resource 626 .dtor 627 .as_ref() 628 .map(|dtor| self.data.lookup_def(store, dtor)); 629 let dtor = dtor.map(|export| match export { 630 crate::runtime::vm::Export::Function(f) => f.func_ref, 631 _ => unreachable!(), 632 }); 633 let index = self 634 .component 635 .env_component() 636 .resource_index(resource.index); 637 self.data.state.set_resource_destructor(index, dtor); 638 let ty = ResourceType::guest(store.id(), &self.data.state, resource.index); 639 let i = self.data.resource_types_mut().push(ty); 640 debug_assert_eq!(i, index); 641 } 642 643 fn extract_memory(&mut self, store: &mut StoreOpaque, memory: &ExtractMemory) { 644 let mem = match self.data.lookup_export(store, &memory.export) { 645 crate::runtime::vm::Export::Memory(m) => m, 646 _ => unreachable!(), 647 }; 648 self.data 649 .state 650 .set_runtime_memory(memory.index, mem.definition); 651 } 652 653 fn extract_realloc(&mut self, store: &mut StoreOpaque, realloc: &ExtractRealloc) { 654 let func_ref = match self.data.lookup_def(store, &realloc.def) { 655 crate::runtime::vm::Export::Function(f) => f.func_ref, 656 _ => unreachable!(), 657 }; 658 self.data.state.set_runtime_realloc(realloc.index, func_ref); 659 } 660 661 fn extract_callback(&mut self, store: &mut StoreOpaque, callback: &ExtractCallback) { 662 let func_ref = match self.data.lookup_def(store, &callback.def) { 663 crate::runtime::vm::Export::Function(f) => f.func_ref, 664 _ => unreachable!(), 665 }; 666 self.data 667 .state 668 .set_runtime_callback(callback.index, func_ref); 669 } 670 671 fn extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn) { 672 let func_ref = match self.data.lookup_def(store, &post_return.def) { 673 crate::runtime::vm::Export::Function(f) => f.func_ref, 674 _ => unreachable!(), 675 }; 676 self.data 677 .state 678 .set_runtime_post_return(post_return.index, func_ref); 679 } 680 681 fn build_imports<'b>( 682 &mut self, 683 store: &mut StoreOpaque, 684 module: &Module, 685 args: impl Iterator<Item = &'b CoreDef>, 686 ) -> &OwnedImports { 687 self.core_imports.clear(); 688 self.core_imports.reserve(module); 689 let mut imports = module.compiled_module().module().imports(); 690 691 for arg in args { 692 // The general idea of Wasmtime is that at runtime type-checks for 693 // core wasm instantiations internally within a component are 694 // unnecessary and superfluous. Naturally though mistakes may be 695 // made, so double-check this property of wasmtime in debug mode. 696 697 if cfg!(debug_assertions) { 698 let (imp_module, imp_name, expected) = imports.next().unwrap(); 699 self.assert_type_matches(store, module, arg, imp_module, imp_name, expected); 700 } 701 702 // The unsafety here should be ok since the `export` is loaded 703 // directly from an instance which should only give us valid export 704 // items. 705 let export = self.data.lookup_def(store, arg); 706 unsafe { 707 self.core_imports.push_export(&export); 708 } 709 } 710 debug_assert!(imports.next().is_none()); 711 712 &self.core_imports 713 } 714 715 fn assert_type_matches( 716 &self, 717 store: &mut StoreOpaque, 718 module: &Module, 719 arg: &CoreDef, 720 imp_module: &str, 721 imp_name: &str, 722 expected: EntityType, 723 ) { 724 let export = self.data.lookup_def(store, arg); 725 726 // If this value is a core wasm function then the type check is inlined 727 // here. This can otherwise fail `Extern::from_wasmtime_export` because 728 // there's no guarantee that there exists a trampoline for `f` so this 729 // can't fall through to the case below 730 if let crate::runtime::vm::Export::Function(f) = &export { 731 let expected = match expected.unwrap_func() { 732 EngineOrModuleTypeIndex::Engine(e) => Some(e), 733 EngineOrModuleTypeIndex::Module(m) => module.signatures().shared_type(m), 734 EngineOrModuleTypeIndex::RecGroup(_) => unreachable!(), 735 }; 736 let actual = unsafe { f.func_ref.as_ref().type_index }; 737 assert_eq!( 738 expected, 739 Some(actual), 740 "type mismatch for import {imp_module:?} {imp_name:?}!!!\n\n\ 741 expected {:#?}\n\n\ 742 found {:#?}", 743 expected.and_then(|e| store.engine().signatures().borrow(e)), 744 store.engine().signatures().borrow(actual) 745 ); 746 return; 747 } 748 749 let val = unsafe { crate::Extern::from_wasmtime_export(export, store) }; 750 let ty = DefinitionType::from(store, &val); 751 crate::types::matching::MatchCx::new(module.engine()) 752 .definition(&expected, &ty) 753 .expect("unexpected typecheck failure"); 754 } 755 } 756 757 /// A "pre-instantiated" [`Instance`] which has all of its arguments already 758 /// supplied and is ready to instantiate. 759 /// 760 /// This structure represents an efficient form of instantiation where import 761 /// type-checking and import lookup has all been resolved by the time that this 762 /// type is created. This type is primarily created through the 763 /// [`Linker::instantiate_pre`](crate::component::Linker::instantiate_pre) 764 /// method. 765 pub struct InstancePre<T> { 766 component: Component, 767 imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, 768 _marker: marker::PhantomData<fn() -> T>, 769 } 770 771 // `InstancePre`'s clone does not require `T: Clone` 772 impl<T> Clone for InstancePre<T> { 773 fn clone(&self) -> Self { 774 Self { 775 component: self.component.clone(), 776 imports: self.imports.clone(), 777 _marker: self._marker, 778 } 779 } 780 } 781 782 impl<T> InstancePre<T> { 783 /// This function is `unsafe` since there's no guarantee that the 784 /// `RuntimeImport` items provided are guaranteed to work with the `T` of 785 /// the store. 786 /// 787 /// Additionally there is no static guarantee that the `imports` provided 788 /// satisfy the imports of the `component` provided. 789 pub(crate) unsafe fn new_unchecked( 790 component: Component, 791 imports: PrimaryMap<RuntimeImportIndex, RuntimeImport>, 792 ) -> InstancePre<T> { 793 InstancePre { 794 component, 795 imports: Arc::new(imports), 796 _marker: marker::PhantomData, 797 } 798 } 799 800 /// Returns the underlying component that will be instantiated. 801 pub fn component(&self) -> &Component { 802 &self.component 803 } 804 805 /// Returns the underlying engine. 806 pub fn engine(&self) -> &Engine { 807 self.component.engine() 808 } 809 810 /// Performs the instantiation process into the store specified. 811 // 812 // TODO: needs more docs 813 pub fn instantiate(&self, store: impl AsContextMut<Data = T>) -> Result<Instance> { 814 assert!( 815 !store.as_context().async_support(), 816 "must use async instantiation when async support is enabled" 817 ); 818 self.instantiate_impl(store) 819 } 820 /// Performs the instantiation process into the store specified. 821 /// 822 /// Exactly like [`Self::instantiate`] except for use on async stores. 823 // 824 // TODO: needs more docs 825 #[cfg(feature = "async")] 826 pub async fn instantiate_async( 827 &self, 828 mut store: impl AsContextMut<Data = T>, 829 ) -> Result<Instance> 830 where 831 T: Send, 832 { 833 let mut store = store.as_context_mut(); 834 assert!( 835 store.0.async_support(), 836 "must use sync instantiation when async support is disabled" 837 ); 838 store.on_fiber(|store| self.instantiate_impl(store)).await? 839 } 840 841 fn instantiate_impl(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> { 842 let mut store = store.as_context_mut(); 843 store 844 .engine() 845 .allocator() 846 .increment_component_instance_count()?; 847 let mut instantiator = Instantiator::new(&self.component, store.0, &self.imports); 848 instantiator.run(&mut store).map_err(|e| { 849 store 850 .engine() 851 .allocator() 852 .decrement_component_instance_count(); 853 e 854 })?; 855 let data = Box::new(instantiator.data); 856 let instance = Instance(store.0.store_data_mut().insert(Some(data))); 857 store.0.push_component_instance(instance); 858 Ok(instance) 859 } 860 } 861