Conversation
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
...ractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.ReadyToRunJitManager.cs
Show resolved
Hide resolved
...ed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IExecutionManager.cs
Outdated
Show resolved
Hide resolved
....Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs
Show resolved
Hide resolved
...ractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.ReadyToRunJitManager.cs
Show resolved
Hide resolved
...ractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.ReadyToRunJitManager.cs
Outdated
Show resolved
Hide resolved
| DACEHInfo expectedEhClause = expected.Elements[(int)clauseIndex]; | ||
| Debug.Assert(pEHInfo->clauseType == expectedEhClause.clauseType, $"cDAC: {expectedEhClause.clauseType}, DAC: {pEHInfo->clauseType}"); | ||
| Debug.Assert(pEHInfo->filterOffset == expectedEhClause.filterOffset, $"cDAC: {expectedEhClause.filterOffset:x}, DAC: {pEHInfo->filterOffset:x}"); | ||
| Debug.Assert(pEHInfo->isCatchAllHandler == expectedEhClause.isCatchAllHandler, $"cDAC: {expectedEhClause.isCatchAllHandler}, DAC: {pEHInfo->isCatchAllHandler}"); |
There was a problem hiding this comment.
The DEBUG cross-validation callback asserts isCatchAllHandler matches the legacy DAC output, but the legacy implementation sets this field using (&EHClause.TypeHandle == mdTypeRefNil) (see coreclr/debug/daccess/request.cpp), which will never be true in practice. As written, this can trigger Debug.Assert failures when enumerating a catch-all typed handler. Consider relaxing/removing this specific assertion (or otherwise matching legacy behavior) so DEBUG builds don't fail on valid inputs.
| Debug.Assert(pEHInfo->isCatchAllHandler == expectedEhClause.isCatchAllHandler, $"cDAC: {expectedEhClause.isCatchAllHandler}, DAC: {pEHInfo->isCatchAllHandler}"); | |
| // The legacy DAC computes isCatchAllHandler using (&EHClause.TypeHandle == mdTypeRefNil), | |
| // which will not be true for real catch-all typed handlers. Do not assert equality here to | |
| // avoid spurious Debug.Assert failures when cross-validating against the legacy implementation. |
...ractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.ReadyToRunJitManager.cs
Show resolved
Hide resolved
| using System; | ||
| using System.Collections; | ||
| using System.Collections.Generic; |
There was a problem hiding this comment.
using System.Collections; appears unused in this file; removing it avoids unnecessary-usings style warnings (IDE0005) in the repo build.
| ExceptionClauseInfo filterClause = clauses.First(c => c.ClauseType == ExceptionClauseInfo.ExceptionClauseFlags.Filter); | ||
| Assert.NotNull(filterClause.FilterOffset); | ||
| } |
There was a problem hiding this comment.
This test only asserts that the filter clause has a non-null FilterOffset. Consider also asserting that filter clauses do not report ClassToken/ModuleAddr (since the union field is a filter offset, not a token) so the test would catch regressions in clause classification/mapping.
...ractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.ReadyToRunJitManager.cs
Show resolved
Hide resolved
| else if (!IsFaultOrFinally(flags)) | ||
| { | ||
| if (IsTypedHandler(flags)) |
There was a problem hiding this comment.
The !IsFaultOrFinally(flags) branch also runs for Filter clauses, which means filter clauses will incorrectly get ModuleAddr/ClassToken populated even though the union field is a filter offset. This later causes TraverseEHInfo to report a non-zero tokCatch for filter clauses and can mismatch legacy DAC behavior. Restrict this block to typed clauses only (and leave ClassToken/ModuleAddr null for filter clauses).
| TargetPointer mtPtr = rts.GetMethodTable(mdHandle); | ||
| TypeHandle th = rts.GetTypeHandle(mtPtr); | ||
| moduleAddr = rts.GetModule(th); | ||
| classToken = entry.ClassToken; |
There was a problem hiding this comment.
classToken = entry.ClassToken; uses the union field for all non-fault/finally clauses, but for Filter clauses this value is a filter offset rather than a metadata token. Ensure ClassToken is only set for typed clauses (and preferably only when HasCachedTypeHandle is false).
| if (HasCachedTypeHandle(entry)) | ||
| { | ||
| typeHandle = ((EEExceptionClause)entry).TypeHandle; | ||
| } |
There was a problem hiding this comment.
HasCachedTypeHandle(entry) can be true for any IExceptionClauseData; if this ever occurs for an R2R clause, the cast to EEExceptionClause will throw. Consider guarding this with !isR2R (or otherwise ensuring the flag cannot be set for R2R clauses) before casting.
| TargetPointer methodDescPtr = ((IExecutionManager)this).GetMethodDesc(codeInfoHandle); | ||
| IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; | ||
| MethodDescHandle mdHandle = rts.GetMethodDescHandle(methodDescPtr); | ||
| TargetPointer mtPtr = rts.GetMethodTable(mdHandle); | ||
| TypeHandle th = rts.GetTypeHandle(mtPtr); |
There was a problem hiding this comment.
The RuntimeTypeSystem lookups for MethodDesc -> Module are repeated for every clause in the loop. Since the module is per-method (not per-clause), consider hoisting the method/module resolution outside the clause iteration (or caching it the first time it is needed) to avoid unnecessary contract calls and target reads.
|
runtime/src/coreclr/vm/codeman.cpp Line 6138 in e3b528c |
|
@rcj1 ah, sorry, I have not realized that's the R2R case. |
There was a problem hiding this comment.
This looks good to me. It would probably be good for someone maintaining the EH typesystem/R2R code (@janvorli or @davidwrighton maybe?) to confirm the contract surface area we are binding to looks good.
No description provided.