wasmtime_environ/vmtypes.rs
1//! Centralized definitions of the various `VM*` types whose layout is shared
2//! between the runtime (which uses the actual structures) and the compiler
3//! (which uses the types' offsets and has per-type alias regions).
4//!
5//! To keep these in sync, the shape of each type is defined exactly once here,
6//! via the higher-order [`for_each_vm_type!`] macro, and each consumer
7//! generates its view of the type from that single source of truth.
8
9/// Invoke the given macro `$mac` once, passing it the definitions of each of the
10/// `VM*` types whose layout is shared between the runtime, compilation offsets,
11/// and Cranelift alias regions.
12///
13/// This is a higher-order macro: callers define a `macro_rules!` macro that
14/// matches the grammar defined below and pass its name as an argument to this
15/// macro's invocation, e.g. `for_each_vm_type!(define_vm_types)`.
16///
17/// # Grammar
18///
19/// Each type is emitted as a struct definition preceded by:
20///
21/// * Doc-comment attributes (`#[doc = "..."]`).
22///
23/// * An optional `#[cfg(...)]` attribute, gating the type on the Cargo features
24/// whose code actually uses it.
25///
26/// Only the runtime's `struct` definition (and its layout test) is gated by
27/// it. A type's offsets and alias regions are always generated because the
28/// `wasmtime-environ` and `wasmtime-internal-cranelift` crates do not have
29/// Cargo features for all the various Wasm features.
30///
31/// * An optional `#[derive(...)]` attribute.
32///
33/// * A `#[repr(...)]` attribute.
34///
35/// * A `#[snake_name = <ident>]` attribute giving the type's name in
36/// `snake_case`, used to generate accessor method names.
37///
38/// Each field may be preceded by doc-comment attributes and, optionally, these
39/// marker attributes, in this order:
40///
41/// * `#[aggregate]`: this field is a composite (a nested struct or array)
42/// rather than a single scalar. Compiled Wasm code accesses such a field's
43/// interior piecewise, so there is no one Cranelift type for the field as a
44/// whole and no alias-region accessor is generated for it. The field's offset
45/// is still generated, since that is what interior accesses are computed
46/// relative to.
47///
48/// * `#[indexed]`: this field is a fixed-size array of a scalar type, whose
49/// elements compiled Wasm code accesses individually by a compile-time
50/// constant index. Like `#[aggregate]`, the field has no single Cranelift
51/// type; unlike `#[aggregate]`, its elements all do, so an alias-region
52/// accessor taking that index is generated for it and each element gets its
53/// own alias region.
54///
55/// * `#[readonly]` and/or `#[can_move]`: describe how Cranelift may treat loads
56/// and stores of that field.
57#[macro_export]
58macro_rules! for_each_vm_type {
59 ($mac:ident) => {
60 $mac! {
61 /// The fields compiled code needs to access to utilize a WebAssembly linear
62 /// memory defined within the instance, namely the start address and the
63 /// size in bytes.
64 #[derive(Debug)]
65 #[repr(C)]
66 #[snake_name = vm_memory_definition]
67 pub struct VMMemoryDefinition {
68 /// The start address.
69 pub base: VmPtr<u8>,
70
71 /// The current logical size of this linear memory in bytes.
72 ///
73 /// This is atomic because shared memories must be able to grow their length
74 /// atomically. For relaxed access, see
75 /// [`VMMemoryDefinition::current_length()`].
76 pub current_length: AtomicUsize,
77 }
78
79 /// The fields compiled code needs to access to utilize a WebAssembly table
80 /// defined within the instance.
81 #[derive(Debug, Copy, Clone)]
82 #[repr(C)]
83 #[snake_name = vm_table_definition]
84 pub struct VMTableDefinition {
85 /// Pointer to the table data.
86 pub base: VmPtr<u8>,
87
88 /// The current number of elements in the table.
89 pub current_elements: usize,
90 }
91
92 /// The storage for a WebAssembly global defined within the instance.
93 ///
94 /// TODO: Pack the globals more densely, rather than using the same size
95 /// for every type.
96 #[derive(Debug)]
97 #[repr(C, align(16))]
98 #[snake_name = vm_global_definition]
99 pub struct VMGlobalDefinition {
100 /// The raw storage for a global's value.
101 storage: [u8; 16],
102 }
103
104 /// A WebAssembly tag defined within the instance.
105 #[derive(Debug)]
106 #[repr(C)]
107 #[snake_name = vm_tag_definition]
108 pub struct VMTagDefinition {
109 /// Function signature's type id.
110 pub type_index: VMSharedTypeIndex,
111 }
112
113 /// The VM caller-checked "funcref" record, for caller-side signature checking.
114 ///
115 /// It consists of function pointer(s), a type id to be checked by the
116 /// caller, and the vmctx closure associated with this function.
117 #[derive(Debug, Clone)]
118 #[repr(C)]
119 #[snake_name = vm_func_ref]
120 pub struct VMFuncRef {
121 /// Function pointer for this funcref if being called via the "array"
122 /// calling convention that `Func::new` et al use.
123 pub array_call: VmPtr<VMArrayCallFunction>,
124
125 /// Function pointer for this funcref if being called via the calling
126 /// convention we use when compiling Wasm.
127 ///
128 /// Most functions come with a function pointer that we can use when they
129 /// are called from Wasm. The notable exception is when we `Func::wrap` a
130 /// host function, and we don't have a Wasm compiler on hand to compile a
131 /// Wasm-to-native trampoline for the function. In this case, we leave
132 /// `wasm_call` empty until the function is passed as an import to Wasm (or
133 /// otherwise exposed to Wasm via tables/globals). At this point, we look up
134 /// a Wasm-to-native trampoline for the function in the Wasm's compiled
135 /// module and use that fill in `VMFunctionImport::wasm_call`. **However**
136 /// there is no guarantee that the Wasm module has a trampoline for this
137 /// function's signature. The Wasm module only has trampolines for its
138 /// types, and if this function isn't of one of those types, then the Wasm
139 /// module will not have a trampoline for it. This is actually okay, because
140 /// it means that the Wasm cannot actually call this function. But it does
141 /// mean that this field needs to be an `Option` even though it is non-null
142 /// the vast vast vast majority of the time.
143 ///
144 /// Once a `VMFuncRef` is exposed to compiled code this field
145 /// never changes again, so accesses of it are `readonly`. It is
146 /// not `can_move`, however: the load may be the one that traps
147 /// on a null funcref, and moving it would move that trap.
148 #[readonly]
149 pub wasm_call: Option<VmPtr<VMWasmCallFunction>>,
150
151 /// Function signature's type id.
152 ///
153 /// See the note about `readonly` and not `can_move` on
154 /// `wasm_call`.
155 #[readonly]
156 pub type_index: VMSharedTypeIndex,
157
158 /// The VM state associated with this function.
159 ///
160 /// The actual definition of what this pointer points to depends on the
161 /// function being referenced: for core Wasm functions, this is a `*mut
162 /// VMContext`, for host functions it is a `*mut VMHostFuncContext`, and for
163 /// component functions it is a `*mut VMComponentContext`.
164 ///
165 /// See the note about `readonly` and not `can_move` on
166 /// `wasm_call`.
167 #[readonly]
168 pub vmctx: VmPtr<VMOpaqueContext>,
169 }
170
171 /// An imported function.
172 ///
173 /// Basically the same as `VMFuncRef`, except that `wasm_call` is not optional.
174 #[derive(Debug, Clone)]
175 #[repr(C)]
176 #[snake_name = vm_function_import]
177 pub struct VMFunctionImport {
178 /// Same as `VMFuncRef::array_call`.
179 #[readonly]
180 #[can_move]
181 pub array_call: VmPtr<VMArrayCallFunction>,
182
183 /// Same as `VMFuncRef::wasm_call`, except always non-null. Must be filled
184 /// in by the time Wasm is importing this function!
185 #[readonly]
186 #[can_move]
187 pub wasm_call: VmPtr<VMWasmCallFunction>,
188
189 /// Function signature's _actual_ type id.
190 ///
191 /// This is the type that the function was defined with, not the type that
192 /// it was imported as. These two can be different in the face of subtyping
193 /// and we need the former for to correctly implement dynamic downcasts.
194 #[readonly]
195 #[can_move]
196 pub type_index: VMSharedTypeIndex,
197
198 /// Same as `VMFuncRef::vmctx`.
199 #[readonly]
200 #[can_move]
201 pub vmctx: VmPtr<VMOpaqueContext>,
202 }
203
204 /// The fields compiled code needs to access to utilize a WebAssembly table
205 /// imported from another instance.
206 #[derive(Debug, Copy, Clone)]
207 #[repr(C)]
208 #[snake_name = vm_table_import]
209 pub struct VMTableImport {
210 /// A pointer to the imported table description.
211 #[readonly]
212 #[can_move]
213 pub from: VmPtr<VMTableDefinition>,
214
215 /// A pointer to the `VMContext` that owns the table description.
216 #[readonly]
217 #[can_move]
218 pub vmctx: VmPtr<VMContext>,
219
220 /// The table index, within `vmctx`, this definition resides at.
221 #[readonly]
222 #[can_move]
223 pub index: DefinedTableIndex,
224 }
225
226 /// The fields compiled code needs to access to utilize a WebAssembly linear
227 /// memory imported from another instance.
228 #[derive(Debug, Copy, Clone)]
229 #[repr(C)]
230 #[snake_name = vm_memory_import]
231 pub struct VMMemoryImport {
232 /// A pointer to the imported memory description.
233 #[readonly]
234 #[can_move]
235 pub from: VmPtr<VMMemoryDefinition>,
236
237 /// A pointer to the `VMContext` that owns the memory description.
238 #[readonly]
239 #[can_move]
240 pub vmctx: VmPtr<VMContext>,
241
242 /// The index of the memory in the containing `vmctx`.
243 #[readonly]
244 #[can_move]
245 pub index: DefinedMemoryIndex,
246 }
247
248 /// The fields compiled code needs to access to utilize a WebAssembly global
249 /// variable imported from another instance.
250 ///
251 /// Note that unlike with functions, tables, and memories, `VMGlobalImport`
252 /// doesn't include a `vmctx` pointer. Globals are never resized, and don't
253 /// require a `vmctx` pointer to access.
254 #[derive(Debug, Copy, Clone)]
255 #[repr(C)]
256 #[snake_name = vm_global_import]
257 pub struct VMGlobalImport {
258 /// A pointer to the imported global variable description.
259 #[readonly]
260 #[can_move]
261 pub from: VmPtr<VMGlobalDefinition>,
262
263 /// A pointer to the context that owns the global.
264 ///
265 /// Exactly what's stored here is dictated by `kind` below. This is `None`
266 /// for `VMGlobalKind::Host`, it's a `VMContext` for
267 /// `VMGlobalKind::Instance`, and it's `VMComponentContext` for
268 /// `VMGlobalKind::ComponentFlags`.
269 #[readonly]
270 #[can_move]
271 pub vmctx: Option<VmPtr<VMOpaqueContext>>,
272
273 /// The kind of global, and extra location information in addition to
274 /// `vmctx` above.
275 #[readonly]
276 #[can_move]
277 pub kind: VMGlobalKind,
278 }
279
280 /// The fields compiled code needs to access to utilize a WebAssembly
281 /// tag imported from another instance.
282 #[derive(Debug, Copy, Clone)]
283 #[repr(C)]
284 #[snake_name = vm_tag_import]
285 pub struct VMTagImport {
286 /// A pointer to the imported tag description.
287 #[readonly]
288 #[can_move]
289 pub from: VmPtr<VMTagDefinition>,
290
291 /// The instance that owns this tag.
292 #[readonly]
293 #[can_move]
294 pub vmctx: VmPtr<VMContext>,
295
296 /// The index of the tag in the containing `vmctx`.
297 #[readonly]
298 #[can_move]
299 pub index: DefinedTagIndex,
300 }
301
302 /// Structure that holds all mutable context that is shared across all instances
303 /// in a store, for example data related to fuel or epochs.
304 ///
305 /// `VMStoreContext`s are one-to-one with `wasmtime::Store`s, the same way that
306 /// `VMContext`s are one-to-one with `wasmtime::Instance`s. And the same way
307 /// that multiple `wasmtime::Instance`s may be associated with the same
308 /// `wasmtime::Store`, multiple `VMContext`s hold a pointer to the same
309 /// `VMStoreContext` when they are associated with the same `wasmtime::Store`.
310 #[derive(Debug)]
311 // NB: `align(8)` is forced rather than inferred because the i386
312 // System V ABI aligns 64-bit integers to 4 bytes, and `VMOffsets`
313 // can't tell that target apart from the ones that align them to 8,
314 // since it only knows the target's pointer width.
315 #[repr(C, align(8))]
316 #[snake_name = vm_store_context]
317 pub struct VMStoreContext {
318 // NB: 64-bit integer fields are located first with pointer-sized fields
319 // trailing afterwards. That makes the offsets in this structure easier to
320 // calculate on 32-bit platforms as we don't have to worry about the
321 // alignment of 64-bit integers.
322 //
323 /// Indicator of how much fuel has been consumed and is remaining to
324 /// WebAssembly.
325 ///
326 /// This field is typically negative and increments towards positive. Upon
327 /// turning positive a wasm trap will be generated. This field is only
328 /// modified if wasm is configured to consume fuel.
329 pub fuel_consumed: UnsafeCell<i64>,
330
331 /// Deadline epoch for interruption: if epoch-based interruption
332 /// is enabled and the global (per engine) epoch counter is
333 /// observed to reach or exceed this value, the guest code will
334 /// yield if running asynchronously.
335 pub epoch_deadline: UnsafeCell<u64>,
336
337 /// The "store version".
338 ///
339 /// This is used to test whether stack-frame handles referring to
340 /// suspended stack frames remain valid.
341 ///
342 /// The invariant that this upward-counting number must satisfy
343 /// is: the number must be incremented whenever execution starts
344 /// or resumes in the `Store` or when any stack is
345 /// dropped/freed. That way, if we take a reference to some
346 /// suspended stack frame and track the "version" at the time we
347 /// took that reference, if the version still matches, we can be
348 /// sure that nothing could have unwound the referenced Wasm
349 /// frame.
350 ///
351 /// This version number is incremented in exactly one place: the
352 /// Wasm-to-host trampolines, after return from host code. Note
353 /// that this captures both the normal "return into Wasm" case
354 /// (where Wasm frames can subsequently return normally and thus
355 /// invalidate frames), and the "trap/exception unwinds Wasm
356 /// frames" case, which is done internally via the `raise` libcall
357 /// invoked after the main hostcall returns an error, and after we
358 /// increment this version number.
359 ///
360 /// Note that this also handles the fiber/future-drop case because
361 /// because we *always* return into the trampoline to clean up;
362 /// that trampoline immediately raises an error and uses the
363 /// longjmp-like unwind within Cranelift frames to skip over all
364 /// the guest Wasm frames, but not before it increments the
365 /// store's execution version number.
366 ///
367 /// This field is in use only if guest debugging is enabled.
368 pub execution_version: u64,
369
370 /// Current stack limit of the wasm module.
371 ///
372 /// For more information see `crates/cranelift/src/lib.rs`.
373 pub stack_limit: UnsafeCell<usize>,
374
375 /// The `VMMemoryDefinition` for this store's GC heap.
376 #[aggregate]
377 pub gc_heap: UnsafeCell<VMMemoryDefinition>,
378
379 /// The value of the frame pointer register in the trampoline used
380 /// to call from Wasm to the host.
381 ///
382 /// Maintained by our Wasm-to-host trampoline, and cleared just
383 /// before calling into Wasm in `catch_traps`.
384 ///
385 /// This member is `0` when Wasm is actively running and has not called out
386 /// to the host.
387 ///
388 /// Used to find the start of a contiguous sequence of Wasm frames
389 /// when walking the stack. Note that we record the FP of the
390 /// *trampoline*'s frame, not the last Wasm frame, because we need
391 /// to know the SP (bottom of frame) of the last Wasm frame as
392 /// well in case we need to resume to an exception handler in that
393 /// frame. The FP of the last Wasm frame can be recovered by
394 /// loading the saved FP value at this FP address.
395 pub last_wasm_exit_trampoline_fp: UnsafeCell<usize>,
396
397 /// The last Wasm program counter before we called from Wasm to the host.
398 ///
399 /// Maintained by our Wasm-to-host trampoline, and cleared just before
400 /// calling into Wasm in `catch_traps`.
401 ///
402 /// This member is `0` when Wasm is actively running and has not called out
403 /// to the host.
404 ///
405 /// Used when walking a contiguous sequence of Wasm frames.
406 pub last_wasm_exit_pc: UnsafeCell<usize>,
407
408 /// The last host stack pointer before we called into Wasm from the host.
409 ///
410 /// Maintained by our host-to-Wasm trampoline. This member is `0` when Wasm
411 /// is not running, and it's set to nonzero once a host-to-wasm trampoline
412 /// is executed.
413 ///
414 /// When a host function is wrapped into a `wasmtime::Func`, and is then
415 /// called from the host, then this member is not changed meaning that the
416 /// previous activation in pointed to by `last_wasm_exit_trampoline_fp` is
417 /// still the last wasm set of frames on the stack.
418 ///
419 /// This field is saved/restored during fiber suspension/resumption
420 /// resumption as part of `CallThreadState::swap`.
421 ///
422 /// This field is used to find the end of a contiguous sequence of Wasm
423 /// frames when walking the stack. Additionally it's used when a trap is
424 /// raised as part of the set of parameters used to resume in the entry
425 /// trampoline's "catch" block.
426 pub last_wasm_entry_sp: UnsafeCell<usize>,
427
428 /// Same as `last_wasm_entry_sp`, but for the `fp` of the trampoline.
429 pub last_wasm_entry_fp: UnsafeCell<usize>,
430
431 /// The last trap handler from a host-to-wasm entry trampoline on the stack.
432 ///
433 /// This field is configured when the host calls into wasm by the trampoline
434 /// itself. It stores the `pc` of an exception handler suitable to handle
435 /// all traps (or uncaught exceptions).
436 pub last_wasm_entry_trap_handler: UnsafeCell<usize>,
437
438 /// Stack information used by stack switching instructions. See documentation
439 /// on `VMStackChain` for details.
440 #[aggregate]
441 pub stack_chain: UnsafeCell<VMStackChain>,
442
443 /// A pointer to the embedder's `T` inside a `Store<T>`, for use with the
444 /// `store-data-address` unsafe intrinsic.
445 ///
446 /// This pointer is fixed for the lifetime of the store, so loads
447 /// of it are `readonly` and `can_move`.
448 #[readonly]
449 #[can_move]
450 pub store_data: VmPtr<()>,
451
452 /// The range, in addresses, of the guard page that is currently in use.
453 ///
454 /// This field is used when signal handlers are run to determine whether a
455 /// faulting address lies within the guard page of an async stack for
456 /// example. If this happens then the signal handler aborts with a stack
457 /// overflow message similar to what would happen had the stack overflow
458 /// happened on the main thread. This field is, by default a null..null
459 /// range indicating that no async guard is in use (aka no fiber). In such a
460 /// situation while this field is read it'll never classify a fault as an
461 /// guard page fault.
462 #[aggregate]
463 pub async_guard_range: Range<*mut u8>,
464
465 /// The `context.{get,set}` values for the current thread in the component
466 /// model. This is only used for `component-model-async` and slot[1] is only
467 /// used for `component-model-threading`. Despite the conditional use nature
468 /// this is unconditionally present as it avoids the need to make logic in
469 /// `VMOffsets` conditional.
470 ///
471 /// This is saved/restored when threads are swapped in the component model.
472 ///
473 /// NB: `UnsafeCell` because JIT code writes to the slots.
474 #[indexed]
475 pub component_context: UnsafeCell<[u32; NUM_COMPONENT_CONTEXT_SLOTS]>,
476
477 /// JIT-visible current thread for the component model's sync-to-sync
478 /// adapter fast path.
479 ///
480 /// Like `component_context`, this is unconditionally present to keep
481 /// `VMOffsets` logic unconditional even though it is only used when
482 /// `component-model-async` is enabled.
483 ///
484 /// NB: `UnsafeCell` because JIT code writes to this field.
485 pub current_thread: UnsafeCell<VMLazyThread>,
486 }
487
488 /// JIT-visible representation of the store's current thread for the component
489 /// model, encoded as a single pointer-sized integer so that generated JIT code
490 /// can load, store, and compare it with a handful of instructions.
491 ///
492 /// This is the inline fast-path counterpart to the host-side `CurrentThread`: a
493 /// fused sync-to-sync adapter records a lazy deferred thread here (a pointer to
494 /// a `VMDeferredThread` on its own stack frame) instead of eagerly allocating a
495 /// `GuestTask`/`GuestThread` in the host. Host code promotes the deferred
496 /// thread into a real one only when it actually needs it; see
497 /// `StoreOpaque::force_current_thread`.
498 ///
499 /// This type is a bitpacked equivalent of the following logical `enum`:
500 ///
501 /// ```ignore
502 /// enum VMLazyThread {
503 /// /// No thread.
504 /// None,
505 ///
506 /// /// The lazy thread was promoted and materialized; get it from
507 /// /// `ConcurrentState::current_thread`.
508 /// Forced,
509 ///
510 /// /// The lazy thread has not been materialized, here is a pointer to the
511 /// /// stack-allocated data needed to do force that promotion.
512 /// Deferred(*mut VMDeferredThread),
513 /// }
514 /// ```
515 ///
516 /// Bitpacking details:
517 ///
518 /// * `None`: `0`
519 ///
520 /// * `Forced`: A non-zero value with its low-bit set.
521 ///
522 /// * `Deferred`: A non-zero value with its low-bit clear.
523 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
524 #[repr(transparent)]
525 #[snake_name = vm_lazy_thread]
526 pub struct VMLazyThread {
527 /// The bitpacked thread representation described above.
528 ///
529 /// Private: use the `VMLazyThread::{none,forced,deferred}` constructors
530 /// and the `is_*`/`as_deferred` accessors instead of touching this
531 /// directly.
532 thread: Option<VmPtr<VMDeferredThread>>,
533 }
534
535 /// A deferred component-model thread.
536 ///
537 /// This is an on-stack record pushed by a fused sync-to-sync adapter's fast
538 /// path to defer the work that the `enter_sync_call` libcall would otherwise do
539 /// eagerly.
540 ///
541 /// The adapter allocates one of these in its own stack frame, links the
542 /// previous current-thread value to it via `parent`, and finally points
543 /// `VMStoreContext::current_thread` at it. When host code actually needs the
544 /// real thread, it walks the `parent` chain to materialize thread state (see
545 /// `StoreOpaque::force_current_thread`).
546 #[derive(Debug)]
547 #[repr(C)]
548 #[snake_name = vm_deferred_thread]
549 pub struct VMDeferredThread {
550 /// The previous value of `VMStoreContext::current_thread`.
551 pub parent: VMLazyThread,
552 /// The caller component instance (a deferred `enter_sync_call` argument).
553 pub caller_instance: u32,
554 /// Whether the callee is async-lifted (a deferred `enter_sync_call` arg).
555 pub callee_async: u32,
556 /// The callee component instance (a deferred `enter_sync_call` argument).
557 pub callee_instance: u32,
558 /// The caller thread's `context.{get,set}` slots, saved on entry and
559 /// restored on the fast-path exit (or recovered while forcing).
560 #[indexed]
561 pub saved_context: [u32; NUM_COMPONENT_CONTEXT_SLOTS],
562 }
563
564 /// This type is used to save (and subsequently restore) a subset of
565 /// the data in `VMStoreContext`.
566 ///
567 /// See documentation of `VMStackChain` for the exact uses.
568 #[derive(Debug, Default, Clone)]
569 #[repr(C)]
570 #[snake_name = vm_stack_limits]
571 pub struct VMStackLimits {
572 /// Saved version of the `stack_limit` field of `VMStoreContext`.
573 pub stack_limit: usize,
574 /// Saved version of the `last_wasm_entry_fp` field of
575 /// `VMStoreContext`.
576 pub last_wasm_entry_fp: usize,
577 /// Saved version of the `last_wasm_entry_sp` field of
578 /// `VMStoreContext`.
579 pub last_wasm_entry_sp: usize,
580 /// Saved version of the `last_wasm_entry_trap_handler` field of
581 /// `VMStoreContext`.
582 pub last_wasm_entry_trap_handler: usize,
583 }
584
585 /// A reference to a buffer ("array") allocated on a continuation's
586 /// stack.
587 ///
588 /// The elements are of whatever type the buffer's user expects;
589 /// `data` is an untyped pointer, and the runtime casts it at each
590 /// use site.
591 #[derive(Debug, Clone)]
592 #[repr(C)]
593 #[snake_name = vm_host_array]
594 pub struct VMHostArray {
595 /// Number of currently occupied slots.
596 pub length: u32,
597
598 /// Number of slots in the data buffer. Note that this is *not*
599 /// the size of the buffer in bytes!
600 pub capacity: u32,
601
602 /// The buffer itself, which lives on the continuation's stack
603 /// rather than in this object.
604 pub data: *mut u8,
605 }
606
607 /// The information saved for every stack, whether it is a
608 /// continuation's or the initial stack's.
609 #[derive(Debug, Clone)]
610 #[repr(C)]
611 #[snake_name = vm_common_stack_information]
612 pub struct VMCommonStackInformation {
613 /// The subset of `VMStoreContext` saved for this stack.
614 #[aggregate]
615 pub limits: VMStackLimits,
616
617 /// Where this stack is in its life cycle; a `VMStackState`
618 /// discriminant.
619 pub state: VMStackState,
620
621 /// The tags this stack handles, set while it is a `Parent`.
622 #[aggregate]
623 pub handlers: VMHostArray,
624
625 /// The index within `handlers` of the first `switch` handler.
626 pub first_switch_handler_index: u32,
627 }
628
629 /// A continuation.
630 #[repr(C)]
631 #[snake_name = vm_cont_ref]
632 pub struct VMContRef {
633 /// The information saved for this continuation's stack.
634 #[aggregate]
635 pub common_stack_information: VMCommonStackInformation,
636
637 /// This continuation's parent: another continuation, the
638 /// initial stack, or absent.
639 #[aggregate]
640 pub parent_chain: VMStackChain,
641
642 /// The end of this continuation's parent chain, used only while
643 /// it is `Suspended` or `Fresh`.
644 pub last_ancestor: *mut VMContRef,
645
646 /// Revision counter.
647 pub revision: usize,
648
649 /// The stack this continuation runs on.
650 #[aggregate]
651 pub stack: VMContinuationStack,
652
653 /// The arguments to, and return values of, the function passed
654 /// to `cont.new`.
655 #[aggregate]
656 pub args: VMHostArray,
657
658 /// The payloads passed to and from this continuation once it
659 /// has been suspended.
660 #[aggregate]
661 pub values: VMHostArray,
662
663 /// Tells the compiler that this structure has potential
664 /// self-references, through `last_ancestor`.
665 ///
666 /// This is a zero-sized type in final position, so it affects
667 /// neither this type's size nor its alignment.
668 #[aggregate]
669 pub _marker: PhantomPinned,
670 }
671
672 /// The deferred-reference-counting collector's JIT-accessible heap
673 /// data.
674 ///
675 /// This is a separate allocation, reached through the
676 /// `VMContext::gc_heap_data` pointer. Its fields are not GC heap
677 /// locations, so they get this type's own alias regions rather than
678 /// the GC heap's.
679 ///
680 /// `wasmtime::runtime::vm::gc::enabled::drc` owns one of these,
681 /// wrapped in a cell because compiled Wasm writes to it, and
682 /// accesses it only through that wrapper's methods.
683 #[cfg(feature = "gc-drc")]
684 #[derive(Default)]
685 #[repr(C)]
686 #[snake_name = vm_drc_heap_data]
687 pub struct VMDrcHeapData {
688 /// The head of the over-approximated-stack-roots list.
689 pub over_approximated_stack_roots: Option<VMGcRef>,
690
691 /// The current size of the over-approximated-stack-roots list.
692 pub current_over_approximated_stack_roots_len: u32,
693
694 /// The size of the over-approximated-stack-roots list
695 /// immediately after the last GC.
696 pub over_approximated_stack_roots_len_after_last_gc: u32,
697 }
698
699 /// The copying collector's JIT-accessible bump-allocation state.
700 ///
701 /// Like [`VMDrcHeapData`], this is a separate allocation reached
702 /// through `VMContext::gc_heap_data`, and is owned, wrapped in a
703 /// cell, by `wasmtime::runtime::vm::gc::enabled::copying`.
704 #[cfg(feature = "gc-copying")]
705 #[derive(Default)]
706 #[repr(C)]
707 #[snake_name = vm_copying_heap_data]
708 pub struct VMCopyingHeapData {
709 /// Current bump pointer (an index into the GC heap).
710 pub bump_ptr: u32,
711
712 /// End of the active semi-space.
713 pub active_space_end: u32,
714 }
715
716 /// The null collector's JIT-accessible bump-allocation state.
717 ///
718 /// Unlike the two above, this is not a separate allocation: it is
719 /// the first field of `NullHeap` (in
720 /// `wasmtime::runtime::vm::gc::enabled::null`), again wrapped in a
721 /// cell, and compiled Wasm reaches it through a pointer to that
722 /// field.
723 #[cfg(feature = "gc-null")]
724 #[repr(C)]
725 #[snake_name = vm_null_heap_data]
726 pub struct VMNullHeapData {
727 /// The bump-allocation finger, an index into the GC heap.
728 pub next: NonZeroU32,
729 }
730 }
731 };
732}