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