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