1 use crate::linker::{Definition, DefinitionType}; 2 use crate::prelude::*; 3 use crate::runtime::vm::{ 4 self, Imports, ModuleRuntimeInfo, VMFuncRef, VMFunctionImport, VMGlobalImport, VMMemoryImport, 5 VMTableImport, VMTagImport, 6 }; 7 use crate::store::{AllocateInstanceKind, InstanceId, StoreInstanceId, StoreOpaque}; 8 use crate::types::matching; 9 use crate::{ 10 AsContextMut, Engine, Export, Extern, Func, Global, Memory, Module, ModuleExport, SharedMemory, 11 StoreContext, StoreContextMut, Table, Tag, TypedFunc, 12 }; 13 use alloc::sync::Arc; 14 use core::ptr::NonNull; 15 use wasmparser::WasmFeatures; 16 use wasmtime_environ::{ 17 EntityIndex, EntityType, FuncIndex, GlobalIndex, MemoryIndex, PrimaryMap, TableIndex, TagIndex, 18 TypeTrace, 19 }; 20 21 /// An instantiated WebAssembly module. 22 /// 23 /// This type represents the instantiation of a [`Module`]. Once instantiated 24 /// you can access the [`exports`](Instance::exports) which are of type 25 /// [`Extern`] and provide the ability to call functions, set globals, read 26 /// memory, etc. When interacting with any wasm code you'll want to make an 27 /// [`Instance`] to call any code or execute anything. 28 /// 29 /// Instances are owned by a [`Store`](crate::Store) which is passed in at 30 /// creation time. It's recommended to create instances with 31 /// [`Linker::instantiate`](crate::Linker::instantiate) or similar 32 /// [`Linker`](crate::Linker) methods, but a more low-level constructor is also 33 /// available as [`Instance::new`]. 34 #[derive(Copy, Clone, Debug)] 35 #[repr(C)] 36 pub struct Instance { 37 id: StoreInstanceId, 38 } 39 40 // Double-check that the C representation in `instance.h` matches our in-Rust 41 // representation here in terms of size/alignment/etc. 42 const _: () = { 43 #[repr(C)] 44 struct C(u64, usize); 45 assert!(core::mem::size_of::<C>() == core::mem::size_of::<Instance>()); 46 assert!(core::mem::align_of::<C>() == core::mem::align_of::<Instance>()); 47 assert!(core::mem::offset_of!(Instance, id) == 0); 48 }; 49 50 impl Instance { 51 /// Creates a new [`Instance`] from the previously compiled [`Module`] and 52 /// list of `imports` specified. 53 /// 54 /// This method instantiates the `module` provided with the `imports`, 55 /// following the procedure in the [core specification][inst] to 56 /// instantiate. Instantiation can fail for a number of reasons (many 57 /// specified below), but if successful the `start` function will be 58 /// automatically run (if specified in the `module`) and then the 59 /// [`Instance`] will be returned. 60 /// 61 /// Per the WebAssembly spec, instantiation includes running the module's 62 /// start function, if it has one (not to be confused with the `_start` 63 /// function, which is not run). 64 /// 65 /// Note that this is a low-level function that just performs an 66 /// instantiation. See the [`Linker`](crate::Linker) struct for an API which 67 /// provides a convenient way to link imports and provides automatic Command 68 /// and Reactor behavior. 69 /// 70 /// ## Providing Imports 71 /// 72 /// The entries in the list of `imports` are intended to correspond 1:1 73 /// with the list of imports returned by [`Module::imports`]. Before 74 /// calling [`Instance::new`] you'll want to inspect the return value of 75 /// [`Module::imports`] and, for each import type, create an [`Extern`] 76 /// which corresponds to that type. These [`Extern`] values are all then 77 /// collected into a list and passed to this function. 78 /// 79 /// Note that this function is intentionally relatively low level. For an 80 /// easier time passing imports by doing name-based resolution it's 81 /// recommended to instead use the [`Linker`](crate::Linker) type. 82 /// 83 /// ## Errors 84 /// 85 /// This function can fail for a number of reasons, including, but not 86 /// limited to: 87 /// 88 /// * The number of `imports` provided doesn't match the number of imports 89 /// returned by the `module`'s [`Module::imports`] method. 90 /// * The type of any [`Extern`] doesn't match the corresponding 91 /// [`ExternType`] entry that it maps to. 92 /// * The `start` function in the instance, if present, traps. 93 /// * Module/instance resource limits are exceeded. 94 /// 95 /// When instantiation fails it's recommended to inspect the return value to 96 /// see why it failed, or bubble it upwards. If you'd like to specifically 97 /// check for trap errors, you can use `error.downcast::<Trap>()`. For more 98 /// about error handling see the [`Trap`] documentation. 99 /// 100 /// [`Trap`]: crate::Trap 101 /// 102 /// # Panics 103 /// 104 /// This function will panic if called with a store associated with a 105 /// [`asynchronous config`](crate::Config::async_support). This function 106 /// will also panic if any [`Extern`] supplied is not owned by `store`. 107 /// 108 /// [inst]: https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation 109 /// [`ExternType`]: crate::ExternType 110 pub fn new( 111 mut store: impl AsContextMut, 112 module: &Module, 113 imports: &[Extern], 114 ) -> Result<Instance> { 115 let mut store = store.as_context_mut(); 116 let imports = Instance::typecheck_externs(store.0, module, imports)?; 117 // Note that the unsafety here should be satisfied by the call to 118 // `typecheck_externs` above which satisfies the condition that all 119 // the imports are valid for this module. 120 assert!(!store.0.async_support()); 121 vm::assert_ready(unsafe { Instance::new_started(&mut store, module, imports.as_ref()) }) 122 } 123 124 /// Same as [`Instance::new`], except for usage in [asynchronous stores]. 125 /// 126 /// For more details about this function see the documentation on 127 /// [`Instance::new`]. The only difference between these two methods is that 128 /// this one will asynchronously invoke the wasm start function in case it 129 /// calls any imported function which is an asynchronous host function (e.g. 130 /// created with [`Func::new_async`](crate::Func::new_async). 131 /// 132 /// # Panics 133 /// 134 /// This function will panic if called with a store associated with a 135 /// [`synchronous config`](crate::Config::new). This is only compatible with 136 /// stores associated with an [`asynchronous 137 /// config`](crate::Config::async_support). 138 /// 139 /// This function will also panic, like [`Instance::new`], if any [`Extern`] 140 /// specified does not belong to `store`. 141 /// 142 /// # Examples 143 /// 144 /// An example of using this function: 145 /// 146 /// ``` 147 /// use wasmtime::{Result, Store, Engine, Config, Module, Instance}; 148 /// 149 /// #[tokio::main] 150 /// async fn main() -> Result<()> { 151 /// let mut config = Config::new(); 152 /// config.async_support(true); 153 /// let engine = Engine::new(&config)?; 154 /// 155 /// // For this example, a module with no imports is being used hence 156 /// // the empty array to `Instance::new_async`. 157 /// let module = Module::new(&engine, "(module)")?; 158 /// let mut store = Store::new(&engine, ()); 159 /// let instance = Instance::new_async(&mut store, &module, &[]).await?; 160 /// 161 /// // ... use `instance` and exports and such ... 162 /// 163 /// Ok(()) 164 /// } 165 /// ``` 166 /// 167 /// Note, though, that the future returned from this function is only 168 /// `Send` if the store's own data is `Send` meaning that this does not 169 /// compile for example: 170 /// 171 /// ```compile_fail 172 /// use wasmtime::{Result, Store, Engine, Config, Module, Instance}; 173 /// use std::rc::Rc; 174 /// 175 /// #[tokio::main] 176 /// async fn main() -> Result<()> { 177 /// let mut config = Config::new(); 178 /// config.async_support(true); 179 /// let engine = Engine::new(&config)?; 180 /// 181 /// let module = Module::new(&engine, "(module)")?; 182 /// 183 /// // Note that `Rc<()>` is NOT `Send`, which is what many future 184 /// // runtimes require and below will cause a failure. 185 /// let mut store = Store::new(&engine, Rc::new(())); 186 /// 187 /// // Compile failure because `Store<Rc<()>>` is not `Send` 188 /// assert_send(Instance::new_async(&mut store, &module, &[])).await?; 189 /// 190 /// Ok(()) 191 /// } 192 /// 193 /// fn assert_send<T: Send>(t: T) -> T { t } 194 /// ``` 195 #[cfg(feature = "async")] 196 pub async fn new_async( 197 mut store: impl AsContextMut, 198 module: &Module, 199 imports: &[Extern], 200 ) -> Result<Instance> { 201 let mut store = store.as_context_mut(); 202 let imports = Instance::typecheck_externs(store.0, module, imports)?; 203 // See `new` for notes on this unsafety 204 unsafe { Instance::new_started(&mut store, module, imports.as_ref()).await } 205 } 206 207 fn typecheck_externs( 208 store: &mut StoreOpaque, 209 module: &Module, 210 imports: &[Extern], 211 ) -> Result<OwnedImports> { 212 for import in imports { 213 if !import.comes_from_same_store(store) { 214 bail!("cross-`Store` instantiation is not currently supported"); 215 } 216 } 217 218 typecheck(module, imports, |cx, ty, item| { 219 let item = DefinitionType::from(store, item); 220 cx.definition(ty, &item) 221 })?; 222 223 // When pushing functions into `OwnedImports` it's required that their 224 // `wasm_call` fields are all filled out. This `module` is guaranteed 225 // to have any trampolines necessary for functions so register the 226 // module with the store and then attempt to fill out any outstanding 227 // holes. 228 // 229 // Note that under normal operation this shouldn't do much as the list 230 // of funcs-with-holes should generally be empty. As a result the 231 // process of filling this out is not super optimized at this point. 232 store.modules_mut().register_module(module); 233 let (funcrefs, modules) = store.func_refs_and_modules(); 234 funcrefs.fill(modules); 235 236 let mut owned_imports = OwnedImports::new(module); 237 for import in imports { 238 owned_imports.push(import, store); 239 } 240 Ok(owned_imports) 241 } 242 243 /// Internal function to create an instance and run the start function. 244 /// 245 /// This function's unsafety is the same as `Instance::new_raw`. 246 pub(crate) async unsafe fn new_started<T>( 247 store: &mut StoreContextMut<'_, T>, 248 module: &Module, 249 imports: Imports<'_>, 250 ) -> Result<Instance> { 251 // SAFETY: the safety contract of `new_raw` is the same as this 252 // function. 253 let (instance, start) = unsafe { Instance::new_raw(store.0, module, imports).await? }; 254 if let Some(start) = start { 255 if store.0.async_support() { 256 #[cfg(feature = "async")] 257 { 258 store 259 .on_fiber(|store| instance.start_raw(store, start)) 260 .await??; 261 } 262 #[cfg(not(feature = "async"))] 263 unreachable!(); 264 } else { 265 instance.start_raw(store, start)?; 266 } 267 } 268 Ok(instance) 269 } 270 271 /// Internal function to create an instance which doesn't have its `start` 272 /// function run yet. 273 /// 274 /// This is not intended to be exposed from Wasmtime, it's intended to 275 /// refactor out common code from `new_started` and `new_started_async`. 276 /// 277 /// Note that this step needs to be run on a fiber in async mode even 278 /// though it doesn't do any blocking work because an async resource 279 /// limiter may need to yield. 280 /// 281 /// # Unsafety 282 /// 283 /// This method is unsafe because it does not type-check the `imports` 284 /// provided. The `imports` provided must be suitable for the module 285 /// provided as well. 286 async unsafe fn new_raw( 287 store: &mut StoreOpaque, 288 module: &Module, 289 imports: Imports<'_>, 290 ) -> Result<(Instance, Option<FuncIndex>)> { 291 if !Engine::same(store.engine(), module.engine()) { 292 bail!("cross-`Engine` instantiation is not currently supported"); 293 } 294 store.bump_resource_counts(module)?; 295 296 // Allocate the GC heap, if necessary. 297 if module.env_module().needs_gc_heap { 298 store.ensure_gc_store().await?; 299 } 300 301 let compiled_module = module.compiled_module(); 302 303 // Register the module just before instantiation to ensure we keep the module 304 // properly referenced while in use by the store. 305 let module_id = store.modules_mut().register_module(module); 306 307 // The first thing we do is issue an instance allocation request 308 // to the instance allocator. This, on success, will give us an 309 // instance handle. 310 // 311 // SAFETY: this module, by construction, was already validated within 312 // the store. 313 let id = unsafe { 314 store 315 .allocate_instance( 316 AllocateInstanceKind::Module(module_id), 317 &ModuleRuntimeInfo::Module(module.clone()), 318 imports, 319 ) 320 .await? 321 }; 322 323 // Additionally, before we start doing fallible instantiation, we 324 // do one more step which is to insert an `InstanceData` 325 // corresponding to this instance. This `InstanceData` can be used 326 // via `Caller::get_export` if our instance's state "leaks" into 327 // other instances, even if we don't return successfully from this 328 // function. 329 // 330 // We don't actually load all exports from the instance at this 331 // time, instead preferring to lazily load them as they're demanded. 332 // For module/instance exports, though, those aren't actually 333 // stored in the instance handle so we need to immediately handle 334 // those here. 335 let instance = Instance::from_wasmtime(id, store); 336 337 // Now that we've recorded all information we need to about this 338 // instance within a `Store` we can start performing fallible 339 // initialization. Note that we still defer the `start` function to 340 // later since that may need to run asynchronously. 341 // 342 // If this returns an error (or if the start function traps) then 343 // any other initialization which may have succeeded which placed 344 // items from this instance into other instances should be ok when 345 // those items are loaded and run we'll have all the metadata to 346 // look at them. 347 let bulk_memory = store 348 .engine() 349 .features() 350 .contains(WasmFeatures::BULK_MEMORY); 351 352 vm::initialize_instance(store, id, compiled_module.module(), bulk_memory).await?; 353 354 Ok((instance, compiled_module.module().start_func)) 355 } 356 357 pub(crate) fn from_wasmtime(id: InstanceId, store: &mut StoreOpaque) -> Instance { 358 Instance { 359 id: StoreInstanceId::new(store.id(), id), 360 } 361 } 362 363 fn start_raw<T>(&self, store: &mut StoreContextMut<'_, T>, start: FuncIndex) -> Result<()> { 364 // If a start function is present, invoke it. Make sure we use all the 365 // trap-handling configuration in `store` as well. 366 let store_id = store.0.id(); 367 let mut instance = self.id.get_mut(store.0); 368 // SAFETY: the `store_id` is the id of the store that owns this 369 // instance and any function stored within the instance. 370 let f = unsafe { instance.as_mut().get_exported_func(store_id, start) }; 371 let caller_vmctx = instance.vmctx(); 372 unsafe { 373 let funcref = f.vm_func_ref(store.0); 374 super::func::invoke_wasm_and_catch_traps(store, |_default_caller, vm| { 375 VMFuncRef::array_call(funcref, vm, caller_vmctx, NonNull::from(&mut [])) 376 })?; 377 } 378 Ok(()) 379 } 380 381 /// Get this instance's module. 382 pub fn module<'a, T: 'static>(&self, store: impl Into<StoreContext<'a, T>>) -> &'a Module { 383 self._module(store.into().0) 384 } 385 386 fn _module<'a>(&self, store: &'a StoreOpaque) -> &'a Module { 387 store.module_for_instance(self.id).unwrap() 388 } 389 390 /// Returns the list of exported items from this [`Instance`]. 391 /// 392 /// # Panics 393 /// 394 /// Panics if `store` does not own this instance. 395 pub fn exports<'a, T: 'static>( 396 &'a self, 397 store: impl Into<StoreContextMut<'a, T>>, 398 ) -> impl ExactSizeIterator<Item = Export<'a>> + 'a { 399 self._exports(store.into().0) 400 } 401 402 fn _exports<'a>( 403 &'a self, 404 store: &'a mut StoreOpaque, 405 ) -> impl ExactSizeIterator<Item = Export<'a>> + 'a { 406 let module = store[self.id].env_module().clone(); 407 let mut items = Vec::new(); 408 for (_name, entity) in module.exports.iter() { 409 items.push(self._get_export(store, *entity)); 410 } 411 store[self.id] 412 .env_module() 413 .exports 414 .iter() 415 .zip(items) 416 .map(|((name, _), item)| Export::new(name, item)) 417 } 418 419 /// Looks up an exported [`Extern`] value by name. 420 /// 421 /// This method will search the module for an export named `name` and return 422 /// the value, if found. 423 /// 424 /// Returns `None` if there was no export named `name`. 425 /// 426 /// # Panics 427 /// 428 /// Panics if `store` does not own this instance. 429 /// 430 /// # Why does `get_export` take a mutable context? 431 /// 432 /// This method requires a mutable context because an instance's exports are 433 /// lazily populated, and we cache them as they are accessed. This makes 434 /// instantiating a module faster, but also means this method requires a 435 /// mutable context. 436 pub fn get_export(&self, mut store: impl AsContextMut, name: &str) -> Option<Extern> { 437 let store = store.as_context_mut().0; 438 let entity = *store[self.id].env_module().exports.get(name)?; 439 Some(self._get_export(store, entity)) 440 } 441 442 /// Looks up an exported [`Extern`] value by a [`ModuleExport`] value. 443 /// 444 /// This is similar to [`Instance::get_export`] but uses a [`ModuleExport`] value to avoid 445 /// string lookups where possible. [`ModuleExport`]s can be obtained by calling 446 /// [`Module::get_export_index`] on the [`Module`] that this instance was instantiated with. 447 /// 448 /// This method will search the module for an export with a matching entity index and return 449 /// the value, if found. 450 /// 451 /// Returns `None` if there was no export with a matching entity index. 452 /// 453 /// # Panics 454 /// 455 /// Panics if `store` does not own this instance. 456 pub fn get_module_export( 457 &self, 458 mut store: impl AsContextMut, 459 export: &ModuleExport, 460 ) -> Option<Extern> { 461 let store = store.as_context_mut().0; 462 463 // Verify the `ModuleExport` matches the module used in this instance. 464 if self._module(store).id() != export.module { 465 return None; 466 } 467 468 Some(self._get_export(store, export.entity)) 469 } 470 471 fn _get_export(&self, store: &mut StoreOpaque, entity: EntityIndex) -> Extern { 472 let id = store.id(); 473 // SAFETY: the store `id` owns this instance and all exports contained 474 // within. 475 let export = unsafe { self.id.get_mut(store).get_export_by_index_mut(id, entity) }; 476 unsafe { Extern::from_wasmtime_export(export, store) } 477 } 478 479 /// Looks up an exported [`Func`] value by name. 480 /// 481 /// Returns `None` if there was no export named `name`, or if there was but 482 /// it wasn't a function. 483 /// 484 /// # Panics 485 /// 486 /// Panics if `store` does not own this instance. 487 pub fn get_func(&self, store: impl AsContextMut, name: &str) -> Option<Func> { 488 self.get_export(store, name)?.into_func() 489 } 490 491 /// Looks up an exported [`Func`] value by name and with its type. 492 /// 493 /// This function is a convenience wrapper over [`Instance::get_func`] and 494 /// [`Func::typed`]. For more information see the linked documentation. 495 /// 496 /// Returns an error if `name` isn't a function export or if the export's 497 /// type did not match `Params` or `Results` 498 /// 499 /// # Panics 500 /// 501 /// Panics if `store` does not own this instance. 502 pub fn get_typed_func<Params, Results>( 503 &self, 504 mut store: impl AsContextMut, 505 name: &str, 506 ) -> Result<TypedFunc<Params, Results>> 507 where 508 Params: crate::WasmParams, 509 Results: crate::WasmResults, 510 { 511 let f = self 512 .get_export(store.as_context_mut(), name) 513 .and_then(|f| f.into_func()) 514 .ok_or_else(|| anyhow!("failed to find function export `{}`", name))?; 515 Ok(f.typed::<Params, Results>(store) 516 .with_context(|| format!("failed to convert function `{name}` to given type"))?) 517 } 518 519 /// Looks up an exported [`Table`] value by name. 520 /// 521 /// Returns `None` if there was no export named `name`, or if there was but 522 /// it wasn't a table. 523 /// 524 /// # Panics 525 /// 526 /// Panics if `store` does not own this instance. 527 pub fn get_table(&self, store: impl AsContextMut, name: &str) -> Option<Table> { 528 self.get_export(store, name)?.into_table() 529 } 530 531 /// Looks up an exported [`Memory`] value by name. 532 /// 533 /// Returns `None` if there was no export named `name`, or if there was but 534 /// it wasn't a memory. 535 /// 536 /// # Panics 537 /// 538 /// Panics if `store` does not own this instance. 539 pub fn get_memory(&self, store: impl AsContextMut, name: &str) -> Option<Memory> { 540 self.get_export(store, name)?.into_memory() 541 } 542 543 /// Looks up an exported [`SharedMemory`] value by name. 544 /// 545 /// Returns `None` if there was no export named `name`, or if there was but 546 /// it wasn't a shared memory. 547 /// 548 /// # Panics 549 /// 550 /// Panics if `store` does not own this instance. 551 pub fn get_shared_memory( 552 &self, 553 mut store: impl AsContextMut, 554 name: &str, 555 ) -> Option<SharedMemory> { 556 let mut store = store.as_context_mut(); 557 self.get_export(&mut store, name)?.into_shared_memory() 558 } 559 560 /// Looks up an exported [`Global`] value by name. 561 /// 562 /// Returns `None` if there was no export named `name`, or if there was but 563 /// it wasn't a global. 564 /// 565 /// # Panics 566 /// 567 /// Panics if `store` does not own this instance. 568 pub fn get_global(&self, store: impl AsContextMut, name: &str) -> Option<Global> { 569 self.get_export(store, name)?.into_global() 570 } 571 572 /// Looks up a tag [`Tag`] by name. 573 /// 574 /// Returns `None` if there was no export named `name`, or if there was but 575 /// it wasn't a tag. 576 /// 577 /// # Panics 578 /// 579 /// Panics if `store` does not own this instance. 580 pub fn get_tag(&self, store: impl AsContextMut, name: &str) -> Option<Tag> { 581 self.get_export(store, name)?.into_tag() 582 } 583 584 #[allow( 585 dead_code, 586 reason = "c-api crate does not yet support exnrefs and causes this method to be dead." 587 )] 588 pub(crate) fn id(&self) -> InstanceId { 589 self.id.instance() 590 } 591 592 /// Get all globals within this instance. 593 /// 594 /// Returns both import and defined globals. 595 /// 596 /// Returns both exported and non-exported globals. 597 /// 598 /// Gives access to the full globals space. 599 #[cfg(feature = "coredump")] 600 pub(crate) fn all_globals<'a>( 601 &'a self, 602 store: &'a mut StoreOpaque, 603 ) -> impl ExactSizeIterator<Item = (GlobalIndex, Global)> + 'a { 604 let store_id = store.id(); 605 store[self.id].all_globals(store_id) 606 } 607 608 /// Get all memories within this instance. 609 /// 610 /// Returns both import and defined memories. 611 /// 612 /// Returns both exported and non-exported memories. 613 /// 614 /// Gives access to the full memories space. 615 #[cfg(feature = "coredump")] 616 pub(crate) fn all_memories<'a>( 617 &'a self, 618 store: &'a StoreOpaque, 619 ) -> impl ExactSizeIterator<Item = (MemoryIndex, Memory)> + 'a { 620 let store_id = store.id(); 621 store[self.id].all_memories(store_id) 622 } 623 } 624 625 pub(crate) struct OwnedImports { 626 functions: PrimaryMap<FuncIndex, VMFunctionImport>, 627 tables: PrimaryMap<TableIndex, VMTableImport>, 628 memories: PrimaryMap<MemoryIndex, VMMemoryImport>, 629 globals: PrimaryMap<GlobalIndex, VMGlobalImport>, 630 tags: PrimaryMap<TagIndex, VMTagImport>, 631 } 632 633 impl OwnedImports { 634 fn new(module: &Module) -> OwnedImports { 635 let mut ret = OwnedImports::empty(); 636 ret.reserve(module); 637 return ret; 638 } 639 640 pub(crate) fn empty() -> OwnedImports { 641 OwnedImports { 642 functions: PrimaryMap::new(), 643 tables: PrimaryMap::new(), 644 memories: PrimaryMap::new(), 645 globals: PrimaryMap::new(), 646 tags: PrimaryMap::new(), 647 } 648 } 649 650 pub(crate) fn reserve(&mut self, module: &Module) { 651 let raw = module.compiled_module().module(); 652 self.functions.reserve(raw.num_imported_funcs); 653 self.tables.reserve(raw.num_imported_tables); 654 self.memories.reserve(raw.num_imported_memories); 655 self.globals.reserve(raw.num_imported_globals); 656 self.tags.reserve(raw.num_imported_tags); 657 } 658 659 #[cfg(feature = "component-model")] 660 pub(crate) fn clear(&mut self) { 661 self.functions.clear(); 662 self.tables.clear(); 663 self.memories.clear(); 664 self.globals.clear(); 665 self.tags.clear(); 666 } 667 668 fn push(&mut self, item: &Extern, store: &mut StoreOpaque) { 669 match item { 670 Extern::Func(i) => { 671 self.functions.push(i.vmimport(store)); 672 } 673 Extern::Global(i) => { 674 self.globals.push(i.vmimport(store)); 675 } 676 Extern::Table(i) => { 677 self.tables.push(i.vmimport(store)); 678 } 679 Extern::Memory(i) => { 680 self.memories.push(i.vmimport(store)); 681 } 682 Extern::SharedMemory(i) => { 683 self.memories.push(i.vmimport(store)); 684 } 685 Extern::Tag(i) => { 686 self.tags.push(i.vmimport(store)); 687 } 688 } 689 } 690 691 /// Note that this is unsafe as the validity of `item` is not verified and 692 /// it contains a bunch of raw pointers. 693 #[cfg(feature = "component-model")] 694 pub(crate) fn push_export(&mut self, store: &StoreOpaque, item: &crate::runtime::vm::Export) { 695 match item { 696 crate::runtime::vm::Export::Function(f) => { 697 // SAFETY: the funcref associated with a `Func` is valid to use 698 // under the `store` that owns the function. 699 let f = unsafe { f.vm_func_ref(store).as_ref() }; 700 self.functions.push(VMFunctionImport { 701 wasm_call: f.wasm_call.unwrap(), 702 array_call: f.array_call, 703 vmctx: f.vmctx, 704 }); 705 } 706 crate::runtime::vm::Export::Global(g) => { 707 self.globals.push(g.vmimport(store)); 708 } 709 crate::runtime::vm::Export::Table(t) => { 710 self.tables.push(t.vmimport(store)); 711 } 712 crate::runtime::vm::Export::Memory { memory, .. } => { 713 self.memories.push(memory.vmimport(store)); 714 } 715 crate::runtime::vm::Export::Tag(t) => { 716 self.tags.push(t.vmimport(store)); 717 } 718 } 719 } 720 721 pub(crate) fn as_ref(&self) -> Imports<'_> { 722 Imports { 723 tables: self.tables.values().as_slice(), 724 globals: self.globals.values().as_slice(), 725 memories: self.memories.values().as_slice(), 726 functions: self.functions.values().as_slice(), 727 tags: self.tags.values().as_slice(), 728 } 729 } 730 } 731 732 /// An instance, pre-instantiation, that is ready to be instantiated. 733 /// 734 /// This structure represents an instance *just before* it was instantiated, 735 /// after all type-checking and imports have been resolved. The only thing left 736 /// to do for this instance is to actually run the process of instantiation. 737 /// 738 /// Note that an `InstancePre` may not be tied to any particular [`Store`] if 739 /// none of the imports it closed over are tied to any particular [`Store`]. 740 /// 741 /// This structure is created through the [`Linker::instantiate_pre`] method, 742 /// which also has some more information and examples. 743 /// 744 /// [`Store`]: crate::Store 745 /// [`Linker::instantiate_pre`]: crate::Linker::instantiate_pre 746 pub struct InstancePre<T> { 747 module: Module, 748 749 /// The items which this `InstancePre` use to instantiate the `module` 750 /// provided, passed to `Instance::new_started` after inserting them into a 751 /// `Store`. 752 /// 753 /// Note that this is stored as an `Arc<[T]>` to quickly move a strong 754 /// reference to everything internally into a `Store<T>` without having to 755 /// clone each individual item. 756 items: Arc<[Definition]>, 757 758 /// A count of `Definition::HostFunc` entries in `items` above to 759 /// preallocate space in a `Store` up front for all entries to be inserted. 760 host_funcs: usize, 761 762 /// The `VMFuncRef`s for the functions in `items` that do not 763 /// have a `wasm_call` trampoline. We pre-allocate and pre-patch these 764 /// `VMFuncRef`s so that we don't have to do it at 765 /// instantiation time. 766 /// 767 /// This is an `Arc<[T]>` for the same reason as `items`. 768 func_refs: Arc<[VMFuncRef]>, 769 770 _marker: core::marker::PhantomData<fn() -> T>, 771 } 772 773 /// InstancePre's clone does not require T: Clone 774 impl<T> Clone for InstancePre<T> { 775 fn clone(&self) -> Self { 776 Self { 777 module: self.module.clone(), 778 items: self.items.clone(), 779 host_funcs: self.host_funcs, 780 func_refs: self.func_refs.clone(), 781 _marker: self._marker, 782 } 783 } 784 } 785 786 impl<T: 'static> InstancePre<T> { 787 /// Creates a new `InstancePre` which type-checks the `items` provided and 788 /// on success is ready to instantiate a new instance. 789 /// 790 /// # Unsafety 791 /// 792 /// This method is unsafe as the `T` of the `InstancePre<T>` is not 793 /// guaranteed to be the same as the `T` within the `Store`, the caller must 794 /// verify that. 795 pub(crate) unsafe fn new(module: &Module, items: Vec<Definition>) -> Result<InstancePre<T>> { 796 typecheck(module, &items, |cx, ty, item| cx.definition(ty, &item.ty()))?; 797 798 let mut func_refs = vec![]; 799 let mut host_funcs = 0; 800 for item in &items { 801 match item { 802 Definition::Extern(_, _) => {} 803 Definition::HostFunc(f) => { 804 host_funcs += 1; 805 if f.func_ref().wasm_call.is_none() { 806 // `f` needs its `VMFuncRef::wasm_call` patched with a 807 // Wasm-to-native trampoline. 808 debug_assert!(matches!(f.host_ctx(), crate::HostContext::Array(_))); 809 func_refs.push(VMFuncRef { 810 wasm_call: module 811 .wasm_to_array_trampoline(f.sig_index()) 812 .map(|f| f.into()), 813 ..*f.func_ref() 814 }); 815 } 816 } 817 } 818 } 819 820 Ok(InstancePre { 821 module: module.clone(), 822 items: items.into(), 823 host_funcs, 824 func_refs: func_refs.into(), 825 _marker: core::marker::PhantomData, 826 }) 827 } 828 829 /// Returns a reference to the module that this [`InstancePre`] will be 830 /// instantiating. 831 pub fn module(&self) -> &Module { 832 &self.module 833 } 834 835 /// Instantiates this instance, creating a new instance within the provided 836 /// `store`. 837 /// 838 /// This function will run the actual process of instantiation to 839 /// completion. This will use all of the previously-closed-over items as 840 /// imports to instantiate the module that this was originally created with. 841 /// 842 /// For more information about instantiation see [`Instance::new`]. 843 /// 844 /// # Panics 845 /// 846 /// Panics if any import closed over by this [`InstancePre`] isn't owned by 847 /// `store`, or if `store` has async support enabled. Additionally this 848 /// function will panic if the `store` provided comes from a different 849 /// [`Engine`] than the [`InstancePre`] originally came from. 850 pub fn instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> { 851 let mut store = store.as_context_mut(); 852 let imports = pre_instantiate_raw( 853 &mut store.0, 854 &self.module, 855 &self.items, 856 self.host_funcs, 857 &self.func_refs, 858 )?; 859 860 // This unsafety should be handled by the type-checking performed by the 861 // constructor of `InstancePre` to assert that all the imports we're passing 862 // in match the module we're instantiating. 863 assert!(!store.0.async_support()); 864 vm::assert_ready(unsafe { 865 Instance::new_started(&mut store, &self.module, imports.as_ref()) 866 }) 867 } 868 869 /// Creates a new instance, running the start function asynchronously 870 /// instead of inline. 871 /// 872 /// For more information about asynchronous instantiation see the 873 /// documentation on [`Instance::new_async`]. 874 /// 875 /// # Panics 876 /// 877 /// Panics if any import closed over by this [`InstancePre`] isn't owned by 878 /// `store`, or if `store` does not have async support enabled. 879 #[cfg(feature = "async")] 880 pub async fn instantiate_async( 881 &self, 882 mut store: impl AsContextMut<Data = T>, 883 ) -> Result<Instance> { 884 let mut store = store.as_context_mut(); 885 let imports = pre_instantiate_raw( 886 &mut store.0, 887 &self.module, 888 &self.items, 889 self.host_funcs, 890 &self.func_refs, 891 )?; 892 893 // This unsafety should be handled by the type-checking performed by the 894 // constructor of `InstancePre` to assert that all the imports we're passing 895 // in match the module we're instantiating. 896 unsafe { Instance::new_started(&mut store, &self.module, imports.as_ref()).await } 897 } 898 } 899 900 /// Helper function shared between 901 /// `InstancePre::{instantiate,instantiate_async}` 902 /// 903 /// This is an out-of-line function to avoid the generic on `InstancePre` and 904 /// get this compiled into the `wasmtime` crate to avoid having it monomorphized 905 /// elsewhere. 906 fn pre_instantiate_raw( 907 store: &mut StoreOpaque, 908 module: &Module, 909 items: &Arc<[Definition]>, 910 host_funcs: usize, 911 func_refs: &Arc<[VMFuncRef]>, 912 ) -> Result<OwnedImports> { 913 // Register this module and use it to fill out any funcref wasm_call holes 914 // we can. For more comments on this see `typecheck_externs`. 915 store.modules_mut().register_module(module); 916 let (funcrefs, modules) = store.func_refs_and_modules(); 917 funcrefs.fill(modules); 918 919 if host_funcs > 0 { 920 // Any linker-defined function of the `Definition::HostFunc` variant 921 // will insert a function into the store automatically as part of 922 // instantiation, so reserve space here to make insertion more efficient 923 // as it won't have to realloc during the instantiation. 924 funcrefs.reserve_storage(host_funcs); 925 926 // The usage of `to_extern_store_rooted` requires that the items are 927 // rooted via another means, which happens here by cloning the list of 928 // items into the store once. This avoids cloning each individual item 929 // below. 930 funcrefs.push_instance_pre_definitions(items.clone()); 931 funcrefs.push_instance_pre_func_refs(func_refs.clone()); 932 } 933 934 let mut func_refs = func_refs.iter().map(|f| NonNull::from(f)); 935 let mut imports = OwnedImports::new(module); 936 for import in items.iter() { 937 if !import.comes_from_same_store(store) { 938 bail!("cross-`Store` instantiation is not currently supported"); 939 } 940 // This unsafety should be encapsulated in the constructor of 941 // `InstancePre` where the `T` of the original item should match the 942 // `T` of the store. Additionally the rooting necessary has happened 943 // above. 944 let item = match import { 945 Definition::Extern(e, _) => e.clone(), 946 Definition::HostFunc(func) => unsafe { 947 func.to_func_store_rooted( 948 store, 949 if func.func_ref().wasm_call.is_none() { 950 Some(func_refs.next().unwrap()) 951 } else { 952 None 953 }, 954 ) 955 .into() 956 }, 957 }; 958 imports.push(&item, store); 959 } 960 961 Ok(imports) 962 } 963 964 fn typecheck<I>( 965 module: &Module, 966 import_args: &[I], 967 check: impl Fn(&matching::MatchCx<'_>, &EntityType, &I) -> Result<()>, 968 ) -> Result<()> { 969 let env_module = module.compiled_module().module(); 970 let expected_len = env_module.imports().count(); 971 let actual_len = import_args.len(); 972 if expected_len != actual_len { 973 bail!("expected {expected_len} imports, found {actual_len}"); 974 } 975 let cx = matching::MatchCx::new(module.engine()); 976 for ((name, field, expected_ty), actual) in env_module.imports().zip(import_args) { 977 debug_assert!(expected_ty.is_canonicalized_for_runtime_usage()); 978 check(&cx, &expected_ty, actual) 979 .with_context(|| format!("incompatible import type for `{name}::{field}`"))?; 980 } 981 Ok(()) 982 } 983