Skip to content

Commit c01656e

Browse files
noahfalkCopilotjkotas
authored
Adjust IsDiagnosticsHidden + MethodDesc comments
- Include additional stubs in IsDiagnosticsHidden (conceptually makes sense but no concrete bug was verified fixed by this) - Added clarifying comments on some MethodDesc APIs related to TransientIL and diagnostics. Co-authored-by: Copilot <[email protected]> Co-authored-by: Jan Kotas <[email protected]>
1 parent a927415 commit c01656e

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/coreclr/vm/method.inl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ inline PTR_DynamicMethodDesc MethodDesc::AsDynamicMethodDesc()
109109
return dac_cast<PTR_DynamicMethodDesc>(this);
110110
}
111111

112+
// NOTE: Not all methods that create IL at runtime are considered dynamic methods. This only returns TRUE
113+
// for methods represented by DynamicMethodDesc. Transient IL (see TryGenerateTransientILImplementation) also
114+
// generates IL at runtime but returns FALSE here.
112115
inline bool MethodDesc::IsDynamicMethod()
113116
{
114117
LIMITED_METHOD_CONTRACT;
@@ -121,16 +124,35 @@ inline bool MethodDesc::IsLCGMethod()
121124
return ((mcDynamic == GetClassification()) && dac_cast<PTR_DynamicMethodDesc>(this)->IsLCGMethod());
122125
}
123126

127+
// NOTE: This method only detects the subset of ILStubs that are internally represented using DynamicMethodDesc.
128+
// There are other methods compiled from IL generated at runtime via ILStubLinker that still return FALSE here.
129+
// See TryGenerateTransientILImplementation.
124130
inline bool MethodDesc::IsILStub()
125131
{
126132
WRAPPER_NO_CONTRACT;
127133
return ((mcDynamic == GetClassification()) && dac_cast<PTR_DynamicMethodDesc>(this)->IsILStub());
128134
}
129135

136+
// This method is intended to identify methods that aren't shown in diagnostic introspection (stacktraces,
137+
// code viewing, stepping, etc). Partly this is a user experience consideration to preserve the
138+
// abstraction users would expect based on source code and assembly contents. Partly it is also a technical
139+
// limitation that many parts of diagnostics don't know how to work with methods that aren't backed by
140+
// metadata and IL in a module.
130141
inline bool MethodDesc::IsDiagnosticsHidden()
131142
{
143+
// Although good user experience can be subjective these are guidelines:
144+
// - We don't want stacktraces to show extra frames when the IL only shows a single call was made. If our runtime stackwalker
145+
// is going to include multiple frames pointing at different MethodDescs then all but one of them should be hidden.
146+
// - In most cases when multiple MethodDescs occur for the same IL call, one of them is a MethodDesc that
147+
// compiled original IL defined in the module (for its default code version at least). That is the one we want to show
148+
// and the rest should be hidden.
149+
// - In other cases the user defines methods in their source code but provides no implementation (for
150+
// example interop calls, Array methods, Delegate.Invoke, or UnsafeAccessor). Ideally a filtered stacktrace would include exactly
151+
// one frame for these calls as well but we haven't always done this consistently. For calls that redirect to another managed method users
152+
// tolerate if the runtime-implemented frame is missing because they can still see the managed target method.
153+
132154
WRAPPER_NO_CONTRACT;
133-
return IsILStub() || IsAsyncThunkMethod();
155+
return IsILStub() || IsAsyncThunkMethod() || IsWrapperStub();
134156
}
135157

136158
inline BOOL MethodDesc::IsQCall()

src/coreclr/vm/prestub.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,9 @@ bool MethodDesc::TryGenerateTransientILImplementation(DynamicResolver** resolver
10571057
{
10581058
STANDARD_VM_CONTRACT;
10591059

1060+
// When adding new methods implemented by Transient IL, consider if MethodDesc::IsDiagnosticsHidden() needs to be
1061+
// updated as well.
1062+
10601063
if (TryGenerateAsyncThunk(resolver, methodILDecoder))
10611064
{
10621065
return true;

0 commit comments

Comments
 (0)