Conversation
|
Azure Pipelines: Successfully started running 7 pipeline(s). 9 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Contributor
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
lewing
force-pushed
the
lewing-r2r-cdac-for-wasm
branch
2 times, most recently
from
September 14, 2026 18:53
d5f26e6 to
69ad34f
Compare
Expose WebAssembly ReadyToRun virtual IP ranges through the runtime data descriptor and resolve them before the RangeSectionMap. Mask funclet flags and keep virtual code identity separate from loaded-image RVA reads. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This was referenced Sep 14, 2026
Handle feature-gated hot/cold metadata, isolate candidate module validation during registration, and remove the unsupported virtual-IP list length limit. Match WASM descriptor layouts and cover long lists, partial registration, and root/funclet image metadata. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Allow up to 65,536 nodes while retaining full-list ambiguity and cycle checks. Reject an over-budget chain before reading its next node, even after a match. Document the budget as reader policy and cover exact-budget success, budget+1 rejection, and the read boundary with a compact fixture. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover the shared native and cDAC invariant that a filter clause offset equals the flagged funclet start relative to its controlling method. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Map the executable filter entry to its containing runtime function before comparing funclet starts, matching native WASM behavior while preserving non-WASM offset comparisons. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve variable debug information produced by RyuJIT for ReadyToRun WebAssembly code, including scope ranges across relooper block ordering and packed wasm local register locations. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The end-to-end variable-debug-info validation exposed the hidden wasm portable-entry-pointer argument as a source local. The argument is appended after user arguments, but unlike the wasm stack-pointer argument it was not recorded or excluded by compMap2ILvarNum. AddDoubles therefore reported the hidden i32 argument as source local 0, alongside the real f64 parameters. Record the argument's local number when it is created, map it to UNKNOWN_ILNUM, and account for it when mapping later internal locals back to IL variable numbers. Replace the count-only wasm R2R checks with complete exact records for the AddDoubles parameters and SumWithFinally local: variable identity, native range, location kind, packed wasm local, and frame-pointer-relative offset. Mutate the local-index bits of one packed register and prove the exact oracle rejects the corrupted record. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Define the packed WASM debug-register bit layout in ICorDebugInfo and have the JIT derive its register masks from that shared encoding contract. Assert that the JIT register representation and WasmValueType count remain compatible with the debug-info format. Document that the static ReadyToRun reader's compiled-in shift must move with a versioned R2R debug-info format change, since it has no live target descriptor from which to discover a different layout. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Publish the shared WASM register type shift and value-type count through the target data descriptor so version-skewed readers can reject incompatible variable debug information. Document the producer-owned encoding and extend the static ReadyToRun reader coverage for reserved and unsupported value-type codes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add a no-opt object local that remains live across a GC call in a finally funclet. Assert its IL class type, complete ReadyToRun variable tuples, frame-relative GC slot, and safepoint coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add exact optimized tracked-variable coverage, frame-base ABI variations including localloc and funclets, and same-type GC slot identity with a legitimate null reference. Pin the current stack VarLoc base encoding and document that absolute frame reconstruction is independent of unstable wasm local indices. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the WASM stack-walk context's SP, virtual IP, and logical frame pointer coherent with the native RtlVirtualUnwind and Frame::UpdateRegDisplay paths. - Derive IP and logical FP for the R2R InlinedCallFrame marker. - Use TransitionBlock's saved R2R SP, including lazy return-address recovery, and avoid treating the generic fallback argument area as a shadow frame. - Copy the full serialized WASM context for software exception frames. - Detect reverse P/Invoke from GC info so native caller bytes are never probed as a possible R2R shadow frame; retain caller SP with IP/FP cleared. - Expose a documented StackWalk function identity containing the raw shared table index, owning module, image runtime-function index, and nullable funclet classification. Reject native/interpreter handles before reading shadow-frame memory while preserving a known raw index when range lookup itself fails. Add native-layout transition fixtures, real adjacent root/funclet range coverage, parent/nested/terminator/localloc unwind coverage, and false-frame reverse-P/Invoke tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Decode the WASM register representation produced by ReadyToRun debug info as symbolic WasmLocal/WasmLocalPair locations with an encoding-specific value type. Engine-owned locals remain symbolic; stack locations resolve from the logical frame pointer already maintained by the StackWalk context. Advertise the register type shift and supported value count as WASM cDAC data descriptor globals. Require and validate those values before reading a non-empty variable stream so a reader/target format mismatch fails explicitly instead of plausibly decoding the wrong local or type. Reject malformed packed registers and impossible shift/count combinations. Keep current stack encoding exact: base register 2 means context FP. Remove speculative decoded stack-base locals whose values the reader could not honor. Preserve the original packed VarLoc through DacDbi for consumers that need the ICorDebugInfo representation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep engine-private WASM locals unavailable rather than fabricating a zero value, and distinguish an unreadable VLT_STK_BYREF pointer from a legitimate stack-homed null reference. The native DAC retains one logical location when indirect pointer reads fail, but its subsequent address-zero memory read fails on native platforms. WASM linear address zero is readable, so carrying that fallback forward can return successful irrelevant bytes. Preserve the logical location count while making all address/value/object access report CORDBG_E_READVIRTUAL_FAILURE when the indirection is unreadable or resolves to null. Non-WASM dereference behavior remains unchanged. Exact controls cover an unreadable byref, a null byref pointer, a readable null reference, and a symbolic engine local with no physical location. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
lewing
force-pushed
the
lewing-r2r-cdac-for-wasm
branch
from
September 16, 2026 01:48
69ad34f to
7e72c0e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Decode ReadyToRun WebAssembly variable locations through cDAC while keeping wasm unwind state and function identity in the shared StackWalk contract.
WasmLocal(Index, WasmDebugValueType)/WasmLocalPairvalues.VLT_STKfrom the logical frame pointer already stored in the frame context.IStackWalk.ICorDebugInfo::VarLocdata through DacDbi.Temporary stack
Important
This draft depends on both #133917 and #133086. Their head branches live in the
lewing/runtimefork, so this upstream PR cannot target either branch directly and temporarily contains both lower layers. After those PRs merge, their commits will disappear when this branch is rebased ontomain.Lower-layer heads:
443fb559f4771c3fbf31a1e85d07ef9aebfd10cc2ea1ed1481d412fa5f461f1b355ce8e51a985ddeThe temporary history is exactly:
443fb559f47.a7a349ecf4d.4aac9657b3c—[cdac][wasm] Maintain frame context and expose function identity657f254f921—[cdac][wasm] Decode ReadyToRun variable locations7e72c0e0d16—[cdac][wasm] Handle unavailable variable valuesProducer constants, encoding globals, optimized-record tests, GC specimens, and stack-base invariants remain owned by #133086. Virtual-IP descriptor/traversal and filter-funclet classification remain owned by #133917.
Corrected virtual-IP dependency
#133917 fixes the live runtime model that #130988's mock test did not represent: WASM ReadyToRun virtual IPs are registered in
ExecutionManager::s_pVirtualIPRangeList, notRangeSectionMap.This PR consumes that shared correction rather than adding a parallel lookup. The integrated reader:
RangeSectionMaplookup;FilterOffsetto its containing runtime function before comparing the masked funclet start.The last point reflects corrected #133917 head
443fb559f47. A filter entry may be inside the filter runtime function rather than exactly at its start; rawFilterOffset == funcletStartequality is intentionally not used.StackWalk context and function identity
Native WASM
RtlVirtualUnwindupdatesInterpreterSP,InterpreterIP, and the funclet-resolvedInterpreterFPtogether. cDAC now maintains the same invariant:InlinedCallFramemarkerINLINED_PINVOKE_FROM_R2Rderives IP/FP fromCallSiteSPrather than treating marker1as an IP.TransitionFrameuses its saved R2R SP, lazily derives a zero return address, and derives FP only when the saved SP/IP are valid. The generic argument-area fallback is never parsed as a shadow frame.IStackWalk.GetWasmFunctionIdentityis valid only for ReadyToRun frameless frames and returns:Runtime table indices are globally relocated by each module's
tableBase, but V8func_indexvalues are module-local. Consumers therefore need the owning module plus image-relative runtime-function index to select the correct script and translate through its element section.Logical frame pointer and stack locations
Current producer stack records encode base register
2;REG_FPBASE,REG_SPBASE, andREGNUM_AMBIENT_SPcollapse to that value on WASM. The record identifies a logical frame-relative home, not a particular V8 local.The absolute frame pointer is reconstructed from shadow-stack memory by the shared unwinder:
localloc: logical FP aliases SP;localloc: logical FP remains the fixed pre-adjustment frame base;Measured engine-local indices (
$0,$1,$3) are current codegen observations, not cDAC format or API. No FP-local metadata is required. Variable resolution consumesWasmContext.FramePointer.Variable locations
RyuJIT packs a local index and JIT debug value type into the 32-bit
RegNumpayload. cDAC receives the encoding from target globals:WasmDebugRegisterTypeShiftWasmDebugValueTypeCountA non-empty WASM Vars stream with missing, mismatched, impossible, or unknown encoding metadata fails explicitly. Invalid packed registers do not fall back to native register locations.
The contract reports:
VLT_REG/VLT_REG_BYREFasWasmLocal;VLT_REG_REGasWasmLocalPair;WasmDebugValueTypeis JIT debug-encoding vocabulary, not the full stable WebAssembly specification type set. Managed references currently use the JIT's machineI32/I64representation.Unavailable and null values
Three cases remain intentionally distinct:
GetBytes/GetAddressfail withE_NOINTERFACE.VLT_STK_BYREFindirection: one logical location remains, matching native location count, while address/value/object access fails withCORDBG_E_READVIRTUAL_FAILURE.The native DAC converts a failed byref read to address zero and subsequently fails because native address zero is unmapped. WASM linear address zero is readable, so carrying that fallback forward would fabricate a successful unrelated value. Non-WASM behavior is unchanged.
Producer validation from #133086
The producer now has exact MinOpts and FullOpts coverage. This is not a minopts-only feature, and optimized-away locals are explicitly absent rather than required to appear.
Representative exact records include:
The reference slots are producer-verified
GC_FRAMEREG_REL, pinned/untracked roots across an actual GC. Their common method-wide range is a documented current producer limitation; this PR does not claim per-local range-end fidelity.Existing live validation
The previous live non-filter validations remain applicable to the equivalent consumer behavior:
A no-opt
SumWithFinallyfinally-funclet pause also demonstrated parent-FP stack resolution and a known value read fromFP + offset.These runs did not exercise filter-funclet classification. The corrected
443fb559f47filter behavior is current through focused cDAC tests, including the non-equal filter-entry case. No claim is made that the old full-stack live artifact validates that corrected filter path.Live two-marker/null C2 validation remains a follow-up on the coherent combined reader/runtime artifact; the producer descriptor and root-slot oracle are now fixed by #133086.
Tests after corrected restack
tools.cdactests:StackWalk.mdusage section was refreshed and verified current.Existing mutation evidence includes packed-register mismatch, unavailable-value regression, frame-kind identity gating, stale funclet FP, C3
DereferenceOrZerofallback, and #133917's filter-entry raw-equality mutation.Limitations and readiness
_legacyImplcomparison.v128register encodings have synthetic decode coverage but their live V8 representations remain unproven.IDebugInfo.GetMethodVarInfo, so the final descriptor-to-CDP join remains a consumer follow-up.The corrected lower-layer integration is complete, but this PR remains draft pending lower-PR readiness and Larry's decision. It is not being marked ready by this update.
Note
This pull request description was generated with GitHub Copilot.