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