| dad8432d | 02-Apr-2026 |
Nick Fitzgerald <[email protected]> |
Add GC zeal assertions (#12933)
* Add GC zeal assertions
- Poison freed GC objects and new heap memory - Assert newly-allocated objects are filled with poison pattern - Add `gc_assert!` checks for
Add GC zeal assertions (#12933)
* Add GC zeal assertions
- Poison freed GC objects and new heap memory - Assert newly-allocated objects are filled with poison pattern - Add `gc_assert!` checks for valid `VMGcKind` on `GcHeap::index[_mut]` - Add `gc_assert!` checks for valid `VMGcKind` during tracing - Add `VMGcKind::try_from_u32()` for fallible kind validation - Add over-approximated stack roots list integrity checks, called before and after trace and sweep. Validates kind, in-list bit, ref count, and that the list is not cyclic. - Add assertion that all free blocks of memory contain the poison pattern, before and after trace and sweep
* review feedback
show more ...
|
| e5b127cc | 02-Apr-2026 |
Nick Fitzgerald <[email protected]> |
Add missing stack map declaration for `array.new_elem` (#12936)
`translate_array_new_elem` created a GC reference (array ref) via a libcall but did not call `builder.declare_value_needs_stack_map()`
Add missing stack map declaration for `array.new_elem` (#12936)
`translate_array_new_elem` created a GC reference (array ref) via a libcall but did not call `builder.declare_value_needs_stack_map()` on the result. This meant the reference was not included in stack maps at subsequent safepoints, so if a GC occurred, the reference became stale (leading to use-after-free within the GC heap sandbox).
show more ...
|
| 9500c417 | 31-Mar-2026 |
Chris Fallin <[email protected]> |
Several fixes to debugging infrastructure: component vs. module PCs and gdbstub wasm module names. (#12901)
* Debugging: fix module-relative vs component-relative PCs and unique library names.
Two
Several fixes to debugging infrastructure: component vs. module PCs and gdbstub wasm module names. (#12901)
* Debugging: fix module-relative vs component-relative PCs and unique library names.
Two bugfixes for guest debugging with components:
1. Convert component-relative source locations to module-relative PCs in the frame table. The guest-debug API presents a core-Wasm view where components are deconstructed into individual modules, so all PCs must be module-relative. This adds a `wasm_module_offset` field to `ModuleTranslation` and `FuncEnvironment`, set during component translation, and subtracts it in `debug_tags()`.
2. Give unique names to "library" entries in the gdbstub XML response. LLDB's DynamicLoader deduplicates by name, so using "wasm" for all modules caused only the first to be loaded.
* Debugging: add ModulePC and ComponentPC newtypes for Wasm PC offsets.
Introduce `ModulePC` (module-relative) and `ComponentPC` (component-relative) newtype wrappers around u32 Wasm bytecode offsets. These replace raw u32 values throughout the frame table, breakpoint, and debug systems to prevent confusion between the two offset spaces.
* Debugging: add regression test for component module-relative PCs.
show more ...
|
| f345ee70 | 21-Mar-2026 |
Chris Fallin <[email protected]> |
Debugging: fix panic in align_atomic_addr when guest-debug is enabled. (#12815)
We have an invariant that the `stack_shape` and `stack` stacks are the same length whenever we emit debug tags. The in
Debugging: fix panic in align_atomic_addr when guest-debug is enabled. (#12815)
We have an invariant that the `stack_shape` and `stack` stacks are the same length whenever we emit debug tags. The invariant is temporarily broken when any result is pushed (the value stack becomes longer) but then restored between each instruction.
Now that traps take debug tags too, we have to be careful to maintain the invariant. Usually no new results are pushed before checking for trap-conditions. However `align_atomic_addr` popped then re-pushed a value on the value stack before a trap check; this could cause the invariant to be violated and hence lead to a panic.
This PR instead uses the `peek1` helper to maintain the shape stack entry.
Fixes #12808.
show more ...
|
| d9038ed0 | 12-Feb-2026 |
Chris Fallin <[email protected]> |
Cranelift/Wasmtime/Pulley/Debugging: use little-endian mode to spill/reload vectors in guest-debugging slot and ABI clobbers. (#12585)
* Cranelift/Wasmtime/Pulley/Debugging: use little-endian mode t
Cranelift/Wasmtime/Pulley/Debugging: use little-endian mode to spill/reload vectors in guest-debugging slot and ABI clobbers. (#12585)
* Cranelift/Wasmtime/Pulley/Debugging: use little-endian mode to spill/reload vectors in guest-debugging slot and ABI clobbers.
When running Pulley on an s390x (or other big-endian) host, and enabling guest-debugging instrumentation, a very strange confluence of events occurs:
- Pulley uses "native endian" of the host by default for loads and stores. - Patchable calls to debug hooks use the `preserve_all` ABI, which spills all registers in the trampoline adapter (callee in this ABI), including vector registers. - Saving vector-typed locals/operand stack values to the debugger state slot also uses vector stores. - All of these stores were thus big-endian on big-endian hosts. - Pulley's bytecode only supports little-endian vector loads/stores.
We were thus hitting an assert in Pulley codegen (the Cranelift backend) when encountering a `VStore` VCode instruction with a big-endian mode.
This PR makes two changes that avoid this issue:
- The ABI code for Pulley is careful to specify little-endian mode explicitly for any vector load/store. - The debug instrumentation code is refactored to use little-endian explicitly for vector types *only*. - (Why not for all types? Because we GC-root GC ref values, and these need to be provided to the collector as mutable storage cells, so need to be in native endianness.)
Test will come as part of #12575 incorporating a Pulley-with-guest-debugging test and running on s390x amongst our platforms.
prtest:full
* Review feedback.
* Re-bless Cranelift tests (explicit `little` flags on `preserve_all` tests).
show more ...
|
| 3764e757 | 10-Feb-2026 |
Alex Crichton <[email protected]> |
Refactor borrow state tracking for async tasks (#12550)
* Refactor borrow state tracking for async tasks
This commit is a somewhat deep refactoring of how the state of `borrow<T>` is managed for b
Refactor borrow state tracking for async tasks (#12550)
* Refactor borrow state tracking for async tasks
This commit is a somewhat deep refactoring of how the state of `borrow<T>` is managed for both the host and the guest with respect to async tasks. This additionally refactors how some async task management is done for host-called functions.
The fundamental problem being tackled here is #12510. In that issue it was discovered that the way `CallContext`, the borrow tracking mechanism in Wasmtime, is managed is incompatible with async tasks. Specifically the previous assumption of the scope being mutated for a borrow is somewhere on the call stack is no longer true. It's possible for an async task to be suspended, for example, and then a sibling task drops a borrow which should update the scope of the suspended task. There were a number of other small issues I noticed here and there which this PR additionally has tests for, all of which failed before this change and pass afterwards.
The manner in which borrow state is manipulated is a pretty old part of the component model implementation dating back to the original implementation of resources. I decided to forgo any possible quick fix and have attempted to more deeply refactor and integrate async tasks into all of this infrastructure. A list of the changes made here are:
* The `CallContexts` structure, a stack of `CallContext`, was removed. Tasks now directly store a `CallContext` which is the source of truth for borrow tracking for that call, and it does not move from this location. The store `CallContexts` is now deleted in favor of updating the `Option<ConcurrentState>` in the store to be an `enum` of either concurrent state or a stack. In this manner the old stack-based structure is still used sometimes, but it's impossible to reach when concurrency is enabled.
* Entry to the host from guests now reliably pushes a `HostTask` into the store. Previously where a frame were always pushed into a `CallContext` a `HostTask` is pushed into the store. This is still expected to be a bit too expensive for cheap host calls, but it doesn't meaningfully change the performance profile of before.
* The `resource_enter_call` and `resource_exit_call` libcalls have been removed. These are now folded into the `enter_sync_call` and `exit_sync_call` libcalls. Emission of these hooks has been updated accordingly. The concept of entering a call more generally has been removed. This is more formally known in the async world as a task starting, so the task creation is now responsible for the demarcation of entering a call. Additionally this means that the concept of exiting a call has somewhat gone away. Instead this method was renamed to `validate_scope_exit` which double-checks that a borrow-scope can be exited but doesn't actually remove the task. Task removal is deferred to preexisting mechanisms.
* Management of a `GuestTask`'s previous `Option<CallContext>` field, for example taking/restoring and pushing/popping onto `CallContexts` is now all gone. All related code is outright deleted as the `GuestTask`'s now non-optional `CallContext` field is the source of truth.
* The `ConcurrentState` structure now stores a `CurrentThread` enum instead of `Option<QualifiedThreadId>`. This represents how the currently executing thread could be a host thread, not just a guest thread, which is required for borrow-tracking.
* `HostTask` creation in `poll_and_block` and `first_poll`, the two main entrypoints of async host tasks when called by the guest, is now externalized from these functions. Instead these functions assume that the currently running thread is already a `HostTask` of some kind.
* In `poll_and_block` the host's result is no longer stored in the guest task but in the host task instead.
Overall this enables the `*.wast` test for #12510 to fix the original issue. This then adds new tests to ensure that cleanup of various constructs happens appropriately, such as cancelling a host task should clean up its associated resources. Additionally synchronously calling an async host task no longer leaks resources in a `Store` and should properly clean up everything.
There is still more work to do in this area (e.g. #12544) but that's going to be deferred to a future PR at this point.
Closes #12510
prtest:full
* Review comments/CI fixes
show more ...
|
| c4a38d67 | 26-Jan-2026 |
Philip Craig <[email protected]> |
Use `gimli::write::Dwarf::convert_with_filter` for DWARF transform (#12428)
Replace parts of the transform code with `gimli`'s generic DWARF transformation support. Most of the remaining code is spe
Use `gimli::write::Dwarf::convert_with_filter` for DWARF transform (#12428)
Replace parts of the transform code with `gimli`'s generic DWARF transformation support. Most of the remaining code is specific to the needs of Wasmtime.
The overall behaviour is the same as the previous implementation. We build a graph of the DIE dependencies, and prune DIEs that don't have valid code ranges. Then we traverse the DIE tree again and transform the DIEs. However, there are some differences.
Previously, unresolved references to DIEs were stored in `PendingUnitRefs` and `PendingDebugInfoRefs`, then at the end of the transformation we went back and fixed up these references. The new behaviour reserves IDs for all of the DIEs in the dependency tree before transformation, which avoids the need to fix up references later. It also allows gimli to correctly handle references in DWARF expressions, although that doesn't currently matter for Wasmtime because it doesn't handle references in expressions yet. The visible effect of this in Wasmtime is that the order of transformed attributes will now always match the original DWARF.
The DIE tree pruning is slightly different. We no longer add back-edges pointing to namespace DIEs or the root DIE, which previously caused some DIEs to be reachable when they should not have been. In particular, this affects DW_TAG_variable DIEs for global variables. Wasmtime can't currently translate the location for globals, so they were added without a valid DW_AT_location. These DIEs are now omitted from the transformed DWARF. In the future when global variables can be translated correctly, they can be included by calling `ReserveUnitSection::require_entry`.
Performance measurements for `wasmtime compile -D debug-info=y` show minimal change.
show more ...
|