@@ -133,15 +133,26 @@ inline bool MethodDesc::IsILStub()
133133 return ((mcDynamic == GetClassification ()) && dac_cast<PTR_DynamicMethodDesc>(this )->IsILStub ());
134134}
135135
136- // This method is intended to identify runtime defined methods that don't have a corresponding Metadata or
137- // LCG definition so they can be filtered from diagnostic introspection (stacktraces, code viewing, stepping, etc).
138- // Partly this is a user experience consideration to preserve the abstraction users would expect based on
139- // source code and assembly contents. Partly it is also a technical limitation that many parts of
140- // diagnostics don't know how to work with methods that aren't backed by metadata and IL in a module.
141- // Currently this method only triages methods whose code was generated from IL. We rely on filtering that occurs implicitly
142- // elsewhere to avoid including other kinds of stubs like prestubs or unboxing stubs.
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. Currently this method only triages methods whose code was generated from IL.
143141inline bool MethodDesc::IsDiagnosticsHidden ()
144142{
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+
154+ // NOTE: Currently this method doesn't filter out unboxing stubs although it seems like it should. I haven't identified a concrete
155+ // scenario that produces a bad user experience but more exploration might find one.
145156 WRAPPER_NO_CONTRACT;
146157 return IsILStub () || IsAsyncThunkMethod ();
147158}
0 commit comments