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