1# Architecture of Wasmtime 2 3This document is intended to give an overview of the implementation of Wasmtime. 4This will explain the purposes of the various `wasmtime-*` crates that the main 5`wasmtime` crate depends on. For even more detailed information it's recommended 6to review the code itself and find the comments contained within. 7 8## The `wasmtime` crate 9 10The main entry point for Wasmtime is the `wasmtime` crate itself. Wasmtime is 11designed such that the `wasmtime` crate is nearly a 100% safe API (safe in the 12Rust sense) modulo some small and well-documented functions as to why they're 13`unsafe`. The `wasmtime` crate provides features and access to WebAssembly 14primitives and functionality, such as compiling modules, instantiating them, 15calling functions, etc. 16 17At this time the `wasmtime` crate is the first crate that is intended to be 18consumed by users. First in this sense means that everything `wasmtime` depends 19on is thought of as an internal dependency. We publish crates to crates.io but 20put very little effort into having a "nice" API for internal crates or worrying 21about breakage between versions of internal crates. This primarily means that 22all the other crates discussed here are considered internal dependencies of 23Wasmtime and don't show up in the public API of Wasmtime at all. To use some 24Cargo terminology, all the `wasmtime-*` crates that `wasmtime` depends on are 25"private" dependencies. 26 27Additionally at this time the safe/unsafe boundary between Wasmtime's internal 28crates is not the most well-defined. There are methods that should be marked 29`unsafe` which aren't, and `unsafe` methods do not have exhaustive documentation 30as to why they are `unsafe`. This is an ongoing matter of improvement, however, 31where the goal is to have safe methods be actually safe in the Rust sense, 32as well as having documentation for `unsafe` methods which clearly lists why 33they are `unsafe`. 34 35## Important concepts 36 37To preface discussion of more nitty-gritty internals, it's important to have a 38few concepts in the back of your head. These are some of the important types and 39their implications in Wasmtime: 40 41* `wasmtime::Engine` - this is a global compilation context which is sort of the 42 "root context". An `Engine` is typically created once per program and is 43 expected to be shared across many threads (internally it's atomically 44 reference counted). Each `Engine` stores configuration values and other 45 cross-thread data such as type interning for `Module` instances. The main 46 thing to remember for `Engine` is that any mutation of its internals typically 47 involves acquiring a lock, whereas for `Store` below no locks are necessary. 48 49* `wasmtime::Store` - this is the concept of a "store" in WebAssembly. While 50 there's also a formal definition to go off of, it can be thought of as a bag 51 of related WebAssembly objects. This includes instances, globals, memories, 52 tables, etc. A `Store` does not implement any form of garbage collection of 53 the internal items (there is a `gc` function but that's just for `externref` 54 values). This means that once you create an `Instance` or a `Table` the memory 55 is not actually released until the `Store` itself is deallocated. A `Store` is 56 sort of a "context" used for almost all wasm operations. `Store` also contains 57 instance handles which recursively refer back to the `Store`, leading to a 58 good bit of aliasing of pointers within the `Store`. The important thing for 59 now, though, is to know that `Store` is a unit of isolation. WebAssembly 60 objects are always entirely contained within a `Store`, and at this time 61 nothing can cross between stores (except scalars if you manually hook it up). 62 In other words, wasm objects from different stores cannot interact with each 63 other. A `Store` cannot be used simultaneously from multiple threads (almost 64 all operations require `&mut self`). 65 66* `wasmtime::runtime::vm::InstanceHandle` - this is the low-level representation of a 67 WebAssembly instance. At the same time this is also used as the representation 68 for all host-defined objects. For example if you call `wasmtime::Memory::new` 69 it'll create an `InstanceHandle` under the hood. This is a very `unsafe` type 70 that should probably have all of its functions marked `unsafe` or otherwise 71 have more strict guarantees documented about it, but it's an internal type 72 that we don't put much thought into for public consumption at this time. An 73 `InstanceHandle` doesn't know how to deallocate itself and relies on the 74 caller to manage its memory. Currently this is either allocated on-demand 75 (with `malloc`) or in a pooling fashion (using the pooling allocator). The 76 `deallocate` method is different in these two paths (as well as the 77 `allocate` method). 78 79 An `InstanceHandle` is laid out in memory with some Rust-owned values first 80 capturing the dynamic state of memories/tables/etc. Most of these fields are 81 unused for host-defined objects that serve one purpose (e.g. a 82 `wasmtime::Table::new`), but for an instantiated WebAssembly module these 83 fields will have more information. After an `InstanceHandle` in memory is a 84 `VMContext`, which will be discussed next. `InstanceHandle` values are the 85 main internal runtime representation and what the `crate::runtime::vm` code 86 works with. The `wasmtime::Store` holds onto all these `InstanceHandle` values 87 and deallocates them at the appropriate time. From the runtime perspective it 88 simplifies things so the graph of wasm modules communicating to each other is 89 reduced to simply `InstanceHandle` values all talking to themselves. 90 91* `crate::runtime::vm::VMContext` - this is a raw pointer, within an allocation of 92 an `InstanceHandle`, that is passed around in JIT code. A `VMContext` does not 93 have a structure defined in Rust (it's a 0-sized structure) because its 94 contents are dynamically determined based on the `VMOffsets`, or the source 95 wasm module it came from. Each `InstanceHandle` has a "shape" of a `VMContext` 96 corresponding with it. For example a `VMContext` stores all values of 97 WebAssembly globals, but if a wasm module has no globals then the size of this 98 array will be 0 and it won't be allocated. The intention of a `VMContext` is 99 to be an efficient in-memory representation of all wasm module state that JIT 100 code may access. The layout of `VMContext` is dynamically determined by a 101 module and JIT code is specialized for this one structure. This means that the 102 structure is efficiently accessed by JIT code, but less efficiently accessed 103 by native host code. A non-exhaustive list of purposes of the `VMContext` is 104 to: 105 106 * Store WebAssembly instance state such as global values, pointers to tables, 107 pointers to memory, and pointers to other JIT functions. 108 * Separate wasm imports and local state. Imported values have pointers stored 109 to their actual values, and local state has the state defined inline. 110 * Hold a pointer to the stack limit at which point JIT code will trigger a 111 stack overflow. 112 * Hold a pointer to a `VMExternRefActivationsTable` for fast-path insertion of 113 `externref` values into the table. 114 * Hold a pointer to a `*mut dyn crate::runtime::vm::Store` so store-level 115 operations can be performed in libcalls. 116 117 A comment about the layout of a `VMContext` can be found in the `vmoffsets.rs` 118 file. 119 120* `wasmtime::Module` - this is the representation of a compiled WebAssembly 121 module. At this time Wasmtime always assumes that a wasm module is always 122 compiled to native JIT code. `Module` holds the results of said compilation, 123 and currently Cranelift can be used for compiling. It is a goal of 124 Wasmtime to support other modes of representing modules but those are not 125 implemented today just yet, only Cranelift is implemented and supported. 126 127* `wasmtime_environ::Module` - this is a descriptor of a wasm module's type and 128 structure without holding any actual JIT code. An instance of this type is 129 created very early on in the compilation process, and it is not modified when 130 functions themselves are actually compiled. This holds the internal type 131 representation and state about functions, globals, etc. In a sense this can be 132 thought of as the result of validation or typechecking a wasm module, although 133 it doesn't have information such as the types of each opcode or minute 134 function-level details like that. 135 136## Compiling a module 137 138With a high-level overview and some background information of types, this will 139next walk through the steps taken to compile a WebAssembly module. The main 140entry point for this is the `wasmtime::Module::from_binary` API. There are a 141number of other entry points that deal with surface-level details like 142translation from text-to-binary, loading from the filesystem, etc. 143 144Compilation is roughly broken down into a few phases: 145 1461. First compilation walks over the WebAssembly module validating everything 147 except function bodies. This synchronous pass over a wasm module creates a 148 `wasmtime_environ::Module` instance and additionally prepares for function 149 compilation. Note that with the module linking proposal one input module may 150 end up creating a number of output modules to process. Each module is 151 processed independently and all further steps are parallelized on a 152 per-module basis. Note that parsing and validation of the WebAssembly module 153 happens with the `wasmparser` crate. Validation is interleaved with parsing, 154 validating parsed values before using them. 155 1562. Next all functions within a module are validated and compiled in parallel. 157 No inter-procedural analysis is done and each function is compiled as its 158 own little island of code at this time. This is the point where the meat of 159 Cranelift is invoked on a per-function basis. 160 1613. The compilation results at this point are all woven into a 162 `wasmtime_jit::CompilationArtifacts` structure. This holds module information 163 (`wasmtime_environ::Module`), compiled JIT code (stored as an ELF image), and 164 miscellaneous other information about functions such as platform-agnostic 165 unwinding information, per-function trap tables (indicating which JIT 166 instructions can trap and what the trap means), per-function address maps 167 (mapping from JIT addresses back to wasm offsets), and debug information 168 (parsed from DWARF information in the wasm module). These results are inert 169 and can't actually be executed, but they're appropriate at this point to 170 serialize to disk or begin the next phase... 171 1724. The final step is to actually place all code into a form that's ready to get 173 executed. This starts from the `CompilationArtifacts` of the previous step. 174 Here a new memory mapping is allocated and the JIT code is copied into this 175 memory mapping. This memory mapping is then switched from read/write to 176 read/execute so it's actually executable JIT code at this point. This is 177 where various hooks like loading debuginfo, informing JIT profilers of new 178 code, etc, all happens. At this point a `wasmtime_jit::CompiledModule` is 179 produced and this is itself wrapped up in a `wasmtime::Module`. At this 180 point the module is ready to be instantiated. 181 182A `wasmtime::Module` is an atomically-reference-counted object where upon 183instantiation into a `Store`, the `Store` will hold a strong reference to the 184internals of the module. This means that all instances of a `wasmtime::Module` 185share the same compiled code. Additionally a `wasmtime::Module` is one of the 186few objects that lives outside of a `wasmtime::Store`. This means that 187`wasmtime::Module`'s reference counting is its own form of memory management. 188 189Note that the property of sharing a module's compiled code across all 190instantiations has interesting implications on what the compiled code can 191assume. For example Wasmtime implements a form of type interning, but the 192interned types happen at a few different levels. Within a module we deduplicate 193function types, but across modules in a `Store` types need to be represented 194with the same value. This means that if the same module is instantiated into 195many stores its same function type may take on many values, so the compiled 196code can't assume a particular value for a function type. (more on type 197information later). The general gist though is that compiled code leans 198relatively heavily on the `VMContext` for contextual input because the JIT code 199is intended to be so widely reusable. 200 201### Trampolines 202 203An important aspect to also cover for compilation is the creation of 204trampolines. Trampolines in this case refer to code executed by Wasmtime to 205enter WebAssembly code. The host may not always have prior knowledge about the 206signature of the WebAssembly function that it wants to call. Wasmtime JIT code 207is compiled with native ABIs (e.g. params/results in registers according to 208System V on Unix), which means that a Wasmtime embedding doesn't have an easy 209way to enter JIT code. 210 211This problem is what the trampolines compiled into a module solve, which is to 212provide a function with a known ABI that will call into a function with a 213specific other type signature/ABI. Wasmtime collects all the exported functions 214of a module and creates a set of their type signatures. Note that exported in 215this context actually means "possibly exported" which includes things like 216insertion into a global/function table, conversion to a `funcref`, etc. A 217trampoline is generated for each of these type signatures and stored along with 218the JIT code for the rest of the module. 219 220These trampolines are then used with the `wasmtime::Func::call` API where in 221that specific case because we don't know the ABI of the target function the 222trampoline (with a known ABI) is used and has all the parameters/results passed 223through the stack. 224 225Another point of note is that trampolines are not deduplicated at this time. 226Each compiled module contains its own set of trampolines, and if two compiled 227modules have the same types then they'll have different copies of the same 228trampoline. 229 230### Type Interning and `VMSharedSignatureIndex` 231 232One important point to talk about with compilation is the 233`VMSharedSignatureIndex` type and how it's used. The `call_indirect` opcode in 234wasm compares an actual function's signature against the function signature of 235the instruction, trapping if the signatures mismatch. This is implemented in 236Wasmtime as an integer comparison, and the comparison happens on a 237`VMSharedSignatureIndex` value. This index is an intern'd representation of a 238function type. 239 240The scope of interning for `VMSharedSignatureIndex` happens at the 241`wasmtime::Engine` level. Modules are compiled into an `Engine`. Insertion of a 242`Module` into an `Engine` will assign a `VMSharedSignatureIndex` to all of the 243types found within the module. 244 245The `VMSharedSignatureIndex` values for a module are local to that one 246instantiation of a `Module` (and they may change on each insertion of a 247`Module` into a different `Engine`). These are used during the instantiation 248process by the runtime to assign a type ID effectively to all functions for 249imports and such. 250 251## Instantiating a module 252 253Once a module has been compiled it's typically then instantiated to actually 254get access to the exports and call wasm code. Instantiation always happens 255within a `wasmtime::Store` and the created instance (plus all exports) are tied 256to the `Store`. 257 258Instantiation itself (`crates/wasmtime/src/instance.rs`) may look complicated, 259but this is primarily due to the implementation of the Module Linking proposal. 260The rough flow of instantiation looks like: 261 2621. First all imports are type-checked. The provided list of imports is 263 cross-referenced with the list of imports recorded in the 264 `wasmtime_environ::Module` and all types are verified to line up and match 265 (according to the core wasm specification's definition of type matching). 266 2672. Each `wasmtime_environ::Module` has a list of initializers that need to be 268 completed before instantiation is finished. For MVP wasm this only involves 269 loading the import into the correct index array, but for module linking this 270 could involve instantiating other modules, handling `alias` fields, etc. In 271 any case the result of this step is a `crate::runtime::vm::Imports` array 272 which has the values for all imported items into the wasm module. Note that 273 in this case an import is typically some sort of raw pointer to the actual 274 state plus the `VMContext` of the instance that was imported from. The final 275 result of this step is an `InstanceAllocationRequest`, which is then 276 submitted to the configured instance allocator, either on-demand or pooling. 277 2783. The `InstanceHandle` corresponding to this instance is allocated. How this 279 is allocated depends on the strategy (malloc for on-demand, slab allocation 280 for pooling). In addition to initialization of the fields of `InstanceHandle` 281 this also initializes all the fields of the `VMContext` for this handle 282 (which as mentioned above is adjacent to the `InstanceHandle` allocation 283 after it in memory). This does not process any data segments, element 284 segments, or the `start` function at this time. 285 2864. At this point the `InstanceHandle` is stored within the `Store`. This is 287 the "point of no return" where the handle must be kept alive for the same 288 lifetime as the `Store` itself. If an initialization step fails then the 289 instance may still have had its functions, for example, inserted into an 290 imported table via an element segment. This means that even if we fail to 291 initialize this instance its state could still be visible to other 292 instances/objects so we need to keep it alive regardless. 293 2945. The final step is performing wasm-defined instantiation. This involves 295 processing element segments, data segments, the `start` function, etc. Most 296 of this is just translating from Wasmtime's internal representation to the 297 specification's required behavior. 298 299Another part worth pointing out for instantiating a module is that a 300`ModuleRegistry` is maintained within a `Store` of all instantiated modules 301into the store. The purpose of this registry is to retain a strong reference to 302items in the module needed to run instances. This includes the JIT code 303primarily but also has information such as the `VMSharedSignatureIndex` 304registration, metadata about function addresses and such, etc. Much of this 305data is stored into a `GLOBAL_MODULES` map for later access during traps. 306 307## Traps 308 309Once instances have been created and wasm starts running most things are fairly 310standard. Trampolines are used to enter wasm and JIT code generally does what it 311does to execute wasm. An important aspect of the implementation to cover, 312however, is traps. 313 314Wasmtime today implements traps with the support for exceptions in Cranelift. 315Notably the entry trampoline into WebAssembly sets up an "base handler" used to 316catch all traps, and when a trap happens this is resumed to. The exception 317handler itself takes care of, for example, restoring registers. 318 319Traps can happen from a few different sources: 320 321* Explicit traps - these can happen when a host call returns a trap, for 322 example. These bottom out in `raise_user_trap` or `raise_lib_trap`, both of 323 which immediately call `longjmp` to go back to the wasm starting point. Note 324 that these, like when calling wasm, have to have callers be very careful to 325 not have any destructors on the stack. 326 327* Signals - this is the main vector for trap. Basically we use segfault and 328 illegal instructions to implement traps in wasm code itself. Segfaults arise 329 when linear memory accesses go out of bounds and illegal instructions are how 330 the wasm `unreachable` instruction is implemented. In both of these cases 331 Wasmtime installs a platform-specific signal handler to catch the signal, 332 inspect the state of the signal, and then handle it. Note that Wasmtime tries 333 to only catch signals that happen from JIT code itself as to not accidentally 334 cover up other bugs. Exiting a signal handler happens via `longjmp` to get 335 back to the original wasm call-site. 336 337The general idea is that Wasmtime has very tight control over the stack frames 338of wasm (naturally via Cranelift), and just after we reenter back into wasm (aka 339trampolines on entry/exit). 340 341The signal handler for Wasmtime uses the `GLOBAL_MODULES` map populated during 342instantiation to determine whether a program counter that triggered a signal is 343indeed a valid wasm trap. This should be true except for cases where the host 344program has another bug that triggered the signal. 345 346A final note worth mentioning is that Wasmtime uses the Rust `backtrace` crate 347to capture a stack trace when a wasm exception occurs. This forces Wasmtime to 348generate native platform-specific unwinding information to correctly unwind the 349stack and generate a stack trace for wasm code. This does have other benefits as 350well such as improving generic sampling profilers when used with Wasmtime. 351 352## Linear Memory 353 354Linear memory in Wasmtime is implemented effectively with `mmap` (or the 355platform equivalent thereof), but there are some subtle nuances that are worth 356pointing out here too. The implementation of linear memory is relatively 357configurable which gives rise to a number of situations that both the runtime 358and generated code need to handle. 359 360First there are a number of properties about linear memory which can be 361configured: 362 363* `wasmtime::Config::memory_reservation` 364* `wasmtime::Config::memory_may_move` 365* `wasmtime::Config::memory_guard_size` 366* `wasmtime::Config::memory_reservation_for_growth` 367* `wasmtime::Config::memory_init_cow` 368* `wasmtime::Config::guard_before_linear_memory` 369* `wasmtime::Config::signals_based_traps` 370 371The methods on `Config` have a good bit of documentation to go over some 372nitty-gritty. Wasmtime also has some `#[cfg]` directives which are calculated by 373`crates/wasmtime/build.rs` which affects the defaults of various strategies. For 374example `has_native_signals` means that segfaults are allowed to happen at 375runtime and are caught in a signal handler. Additionally `has_virtual_memory` 376means that `mmap` is available and will be used (otherwise a fallback to 377`malloc` is implemented). The matrix of all of these combinations is then used 378to implement a linear memory for a WebAssembly instance. 379 380It's generally best to consult the documentation of `Config` for the most 381up-to-date information. Additionally code comments throughout the codebase can 382also be useful for understanding the impact of some of these options. Some 383example scenarios though are: 384 385* **`(memory 1)` on 64-bit platforms** - by default this WebAssembly memory has 386 unlimited size, meaning it's only limited by its index type (`i32`) meaning it 387 can grow up to 4GiB if the host/embedder allows it. This is implemented with a 388 8GiB virtual memory reservation -- 2GiB unmapped before linear memory, 4GiB 389 for linear memory itself (but only 1 wasm page, 64KiB, read/write at the 390 start), and 2GiB unmapped afterwards. The guard region before linear memory is 391 a defense-in-depth measure and should never be hit under any operation. The 392 guard region after linear memory is present to eliminate bounds checks in the 393 wasm module (WebAssembly addresses are effective 33-bit addresses when the 394 static `offset` is taken into account). 395 396* **`(memory i64 1)` on 64-bit platforms** - this WebAssembly memory uses 64-bit 397 indexes instead of 32-bit indexes. This means that the configuration looks 398 similar to `(memory 1)` above except that growth beyond 4GiB will copy all the 399 contents of linear memory to a new location. Embedders might want to raise 400 `Config::memory_reservation` in this situation. This configuration mode cannot 401 remove any bounds checks, but guard pages are still used to deduplicate bounds 402 checks where possible (so segfaults may still be caught at runtime for 403 out-of-bounds accesses). 404 405* **`(memory 1)` on 64-bit platforms with the pooling allocator** - the pooling 406 allocator has a few important differences than the default settings. First is 407 that the pooling allocator is able to "overlap" the before/after guard regions 408 meaning that the virtual memory cost per-linear-memory is 6GiB by default 409 instead of 8GiB. Additionally the pooling allocator cannot resize memory so if 410 `Config::memory_reservation` is less than 4GiB then that's a hard limit on the 411 size of linear memory rather than being able to copy to a new location. 412 413* **`(memory 1)` on 64-bit platforms with a smaller reservation** - if the 414 `Config::memory_reservation` option is configured less than the default (the 415 default is 4GiB) then the virtual memory allocated for all linear memories 416 will be less than the 8GiB default. This means that linear memories may move 417 over time if they grow beyond their initial limit (assuming such growth is 418 allowed) and additionally bounds checks will be required for memory accesses. 419 420* **`(memory 1)` on 32-bit platforms** - unlike 64-bit platforms this memory 421 cannot have a 4GiB virtual memory reservation. Instead the linear memory is 422 allocated with `Config::memory_reservation_for_growth` unmapped bytes after it 423 to amortize the reallocation overhead of copying bytes. Guard pages are still 424 used and signals are used where available to deduplicate bounds checks. 425 426* **`(memory 1 (pagesize 1))` on any platforms** - this WebAssembly linear 427 memory, with a page size of 1 byte, means that virtual memory cannot be used 428 to catch traps. Instead explicit bounds checks are always required on all 429 accesses. This is still allocated with virtual memory where possible, however. 430 431There's quite a few possible combinations for how all of these options interact 432with each other. The high-level design goal of Wasmtime is such that each option 433is independent from all the others and is a knob for just its behavior. In this 434way it should be possible to customize the needs of embedders. Wasmtime 435additionally has different default behavior across platforms, such as 32-bit and 43664-bit platforms. Some platforms additionally don't have `mmap` by default and 437Wasmtime will adapt to that as well. The intention, however, is that it should 438be possible to mirror the default configuration on any platform into a 439"full-featured" platform such as 64-bit to assist with testing, fuzzing, and 440debugging. 441 442## Tables and `externref` 443 444WebAssembly tables contain reference types, currently either `funcref` or 445`externref`. A `funcref` in Wasmtime is represented as `*mut 446VMCallerCheckedFuncRef` and an `externref` is represented as `VMExternRef` 447(which is internally `*mut VMExternData`). Tables are consequently represented 448as vectors of pointers. Table storage memory management by default goes through 449Rust's `Vec` which uses `malloc` and friends for memory. With the pooling 450allocator this uses preallocated memory for storage. 451 452As mentioned previously `Store` has no form of internal garbage 453collection for wasm objects themselves so a `funcref` table in wasm is pretty 454simple in that there's no lifetime management of any of the pointers stored 455within, they're simply assumed to be valid for as long as the table is in use. 456 457For tables of `externref` the story is more complicated. The `VMExternRef` is a 458version of `Arc<dyn Any>` but specialized in Wasmtime so JIT code knows where 459the offset of the reference count field to directly manipulate it is. 460Furthermore tables of `externref` values need to manage the reference count 461field themselves, since the pointer stored in the table is required to have a 462strong reference count allocated to it. 463 464## GC and `externref` 465 466Wasmtime implements the `externref` type of WebAssembly with an 467atomically-reference-counted pointer. Note that the atomic part is not needed 468by wasm itself but rather from the Rust embedding environment where it must be 469safe to send `ExternRef` values to other threads. Wasmtime also does not 470come with a cycle collector so cycles of host-allocated `ExternRef` objects 471will leak. 472 473Despite reference counting, though, a `Store::gc` method exists. This is an 474implementation detail of how reference counts are managed while wasm code is 475executing. Instead of managing the reference count of an `externref` value 476individually as it moves around on the stack Wasmtime implements "deferred 477reference counting" where there's an overly conservative list of `ExternRef` 478values that may be in use, and periodically a GC is performed to make this 479overly conservative list a precise one. This leverages the stack map support 480of Cranelift plus the backtracing support of `backtrace` to determine live 481roots on the stack. The `Store::gc` method forces the 482possibly-overly-conservative list to become a precise list of `externref` 483values that are actively in use on the stack. 484 485## Index of crates 486 487The main Wasmtime internal crates are: 488 489* `wasmtime` - the safe public API of `wasmtime`. 490 * `wasmtime::runtime::vm` - low-level runtime implementation of Wasmtime. This 491 is where `VMContext` and `InstanceHandle` live. This module used to be a 492 crate, but has since been folding into `wasmtime`. 493* `wasmtime-environ` - low-level compilation support. This is where translation 494 of the `Module` and its environment happens, although no compilation actually 495 happens in this crate (although it defines an interface for compilers). The 496 results of this crate are handed off to other crates for actual compilation. 497* `wasmtime-cranelift` - implementation of function-level compilation using 498 Cranelift. 499 500Note that at this time Cranelift is a required dependency of wasmtime. Most of 501the types exported from `wasmtime-environ` use cranelift types in their API. One 502day it's a goal, though, to remove the required cranelift dependency and have 503`wasmtime-environ` be a relatively standalone crate. 504 505In addition to the above crates there are some other miscellaneous crates that 506`wasmtime` depends on: 507 508* `wasmtime-cache` - optional dependency to manage default caches on the 509 filesystem. This is enabled in the CLI by default but not enabled in the 510 `wasmtime` crate by default. 511* `wasmtime-fiber` - implementation of stack-switching used by `async` support 512 in Wasmtime 513* `wasmtime-debug` - implementation of mapping wasm dwarf debug information to 514 native dwarf debug information. 515* `wasmtime-profiling` - implementation of hooking up generated JIT code to 516 standard profiling runtimes. 517* `wasmtime-obj` - implementation of creating an ELF image from compiled 518 functions. 519