Skip to content

Preserve instruction origins in rewritten DWARF line tables - #9194

Open
cpunion wants to merge 6 commits into
WebAssembly:mainfrom
cpunion:codex/asyncify-dwarf-generated-code
Open

cpunion wants to merge 6 commits into
WebAssembly:mainfrom
cpunion:codex/asyncify-dwarf-generated-code

Conversation

@cpunion

@cpunion cpunion commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Depends on #9196 (which depends on #9192). The standalone diff contains only instruction-origin handling. Start with the implementation and tests; five mechanically regenerated snapshots are in a separate commit. GitHub's main-based comparison still includes the unmerged prerequisites.

Fix

Asyncify's inserted rewind/unwind code must not inherit a neighboring user's source line. Surviving instructions must also retain their location when the instruction starting the original line-table row is removed.

Record origins while writing actual instructions, including instructions introduced by the binary/Stack IR writer. Treat input line rows as address intervals: recover original instructions' file/line/column/discriminator, give inserted code line = 0, column = 0, is_stmt = false, and restore source attribution when original code resumes.

Emit rows directly in writer order, coalescing unchanged attribution once. Only function-header/end-sequence records are retained separately; there is no second IR walk, full output-row map, sequence-normalization pass, or second coalescing pass. Functions without input line metadata, including Asyncify helpers, are not assigned fabricated source DWARF.

Generic line-program compression and discriminator serialization are now isolated in #9196. This PR does not handle local re-indexing, generated helper DIEs, or TinyGo's missing metadata, and does not fully resolve tinygo-org/tinygo#5736.

Validation and cost

  • Imported-call tests cover deleted row starts, Asyncify with/without -O1 and Stack IR, original/generated instruction boundaries, discriminator and row flags, unrelated functions without line metadata, and a second roundtrip. A separate loop fixture distinguishes original traps from writer-inserted unreachable instructions. Both regression tests fail on Correct and compact DWARF line-program encoding #9196 and pass here.
  • All 12 DWARF unit tests, 95 Python unit tests, and the full wasm-opt --no-torture suite pass locally. C++: 437 passed, one existing macOS size-test skip. Ruff and changed-line clang-format checks pass. V8-specific execution checks are left to CI.
  • A representative TinyGo goroutine/JSON input passes LLVM 22 DWARF verification for roundtrip, -O1, and -O1 --asyncify; the Asyncify output runs under Wasmtime and prints {"name":"dwarf","value":42}. Stripped outputs remain byte-identical to both prerequisites. The full Netbird application has not been tested.
Mode #9196 module bytes This PR module bytes #9196 time This PR time
Roundtrip 1,893,879 1,895,081 167 ms 171 ms
-O1 1,872,431 1,937,517 212 ms 201 ms
-O1 --asyncify 2,146,432 2,460,857 423 ms 458 ms

Times are nine-run interleaved local medians after warm-up; background system activity makes small differences inconclusive. These are debug-processing costs, not runtime performance. Asyncify executable code stays exactly 671,942 bytes; the extra debug rows increase file size and peak RSS (approximately 150 → 185 MiB, three-run medians). This simplification reduces implementation complexity but does not establish a peak-memory improvement.

This is an original contribution, developed with AI assistance.

@cpunion
cpunion requested a review from a team as a code owner October 2, 2026 04:20
@cpunion
cpunion requested review from tlively and removed request for a team October 2, 2026 04:20
@tlively

tlively commented Oct 2, 2026

Copy link
Copy Markdown
Member

@kripken, do you have more context for this?

@kripken

kripken commented Oct 2, 2026

Copy link
Copy Markdown
Member

No, I have no more context here.

@cpunion it would be good to clarify what is fixed here with a small example.

Also the overview could be more specific: "Preserve instruction origins in rewritten DWARF line tables" is something we were already doing, or at least trying to.

@tlively

tlively commented Oct 2, 2026

Copy link
Copy Markdown
Member

Asyncify's inserted rewind/unwind code must not inherit a neighboring user's source line.

Why is this?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compiler: WASM DWARF misses ~40% of code bytes with opts=1

3 participants