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