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