Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 8746b88

Browse files
author
Mike McLaughlin
authored
Add better portable PDB caching to System.Diagnostics.StackTrace. (#17804) (#17842)
Add portable PDB caching to StackTrace. This is the mscorlib side of the change.
1 parent 24e03e6 commit 8746b88

File tree

4 files changed

+71
-83
lines changed

4 files changed

+71
-83
lines changed

src/mscorlib/src/System/Diagnostics/Stackframe.cs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -260,25 +260,24 @@ public override String ToString()
260260

261261
private void BuildStackFrame(int skipFrames, bool fNeedFileInfo)
262262
{
263-
using (StackFrameHelper StackF = new StackFrameHelper(null))
264-
{
265-
StackF.InitializeSourceInfo(0, fNeedFileInfo, null);
263+
StackFrameHelper StackF = new StackFrameHelper(null);
264+
265+
StackF.InitializeSourceInfo(0, fNeedFileInfo, null);
266266

267-
int iNumOfFrames = StackF.GetNumberOfFrames();
267+
int iNumOfFrames = StackF.GetNumberOfFrames();
268268

269-
skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
269+
skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
270270

271-
if ((iNumOfFrames - skipFrames) > 0)
271+
if ((iNumOfFrames - skipFrames) > 0)
272+
{
273+
method = StackF.GetMethodBase(skipFrames);
274+
offset = StackF.GetOffset(skipFrames);
275+
ILOffset = StackF.GetILOffset(skipFrames);
276+
if (fNeedFileInfo)
272277
{
273-
method = StackF.GetMethodBase(skipFrames);
274-
offset = StackF.GetOffset(skipFrames);
275-
ILOffset = StackF.GetILOffset(skipFrames);
276-
if (fNeedFileInfo)
277-
{
278-
strFileName = StackF.GetFilename(skipFrames);
279-
iLineNumber = StackF.GetLineNumber(skipFrames);
280-
iColumnNumber = StackF.GetColumnNumber(skipFrames);
281-
}
278+
strFileName = StackF.GetFilename(skipFrames);
279+
iLineNumber = StackF.GetLineNumber(skipFrames);
280+
iColumnNumber = StackF.GetColumnNumber(skipFrames);
282281
}
283282
}
284283
}

src/mscorlib/src/System/Diagnostics/Stacktrace.cs

Lines changed: 57 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace System.Diagnostics
2121
// Modifying the order or fields of this object may require other changes
2222
// to the unmanaged definition of the StackFrameHelper class, in
2323
// VM\DebugDebugger.h. The binder will catch some of these layout problems.
24-
internal class StackFrameHelper : IDisposable
24+
internal class StackFrameHelper
2525
{
2626
private Thread targetThread;
2727
private int[] rgiOffset;
@@ -44,16 +44,14 @@ internal class StackFrameHelper : IDisposable
4444
private int[] rgiLineNumber;
4545
private int[] rgiColumnNumber;
4646
private bool[] rgiLastFrameFromForeignExceptionStackTrace;
47-
private GetSourceLineInfoDelegate getSourceLineInfo;
4847
private int iFrameCount;
4948
#pragma warning restore 414
5049

5150
private delegate void GetSourceLineInfoDelegate(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize,
5251
IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset,
5352
out string sourceFile, out int sourceLine, out int sourceColumn);
5453

55-
private static Type s_symbolsType = null;
56-
private static MethodInfo s_symbolsMethodInfo = null;
54+
private static GetSourceLineInfoDelegate s_getSourceLineInfo = null;
5755

5856
[ThreadStatic]
5957
private static int t_reentrancy = 0;
@@ -74,7 +72,6 @@ public StackFrameHelper(Thread target)
7472
rgFilename = null;
7573
rgiLineNumber = null;
7674
rgiColumnNumber = null;
77-
getSourceLineInfo = null;
7875

7976
rgiLastFrameFromForeignExceptionStackTrace = null;
8077

@@ -107,27 +104,32 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce
107104
t_reentrancy++;
108105
try
109106
{
110-
if (s_symbolsMethodInfo == null)
107+
if (s_getSourceLineInfo == null)
111108
{
112-
s_symbolsType = Type.GetType(
109+
Type symbolsType = Type.GetType(
113110
"System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
114111
throwOnError: false);
115112

116-
if (s_symbolsType == null)
113+
if (symbolsType == null)
114+
{
117115
return;
116+
}
118117

119-
s_symbolsMethodInfo = s_symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
120-
if (s_symbolsMethodInfo == null)
118+
MethodInfo symbolsMethodInfo = symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
119+
if (symbolsMethodInfo == null)
120+
{
121121
return;
122-
}
122+
}
123123

124-
if (getSourceLineInfo == null)
125-
{
126124
// Create an instance of System.Diagnostics.Stacktrace.Symbols
127-
object target = Activator.CreateInstance(s_symbolsType);
125+
object target = Activator.CreateInstance(symbolsType);
128126

129127
// Create an instance delegate for the GetSourceLineInfo method
130-
getSourceLineInfo = (GetSourceLineInfoDelegate)s_symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target);
128+
GetSourceLineInfoDelegate getSourceLineInfo = (GetSourceLineInfoDelegate)symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target);
129+
130+
// We could race with another thread. It doesn't matter if we win or lose, the losing instance will be GC'ed and all threads including this one will
131+
// use the winning instance
132+
Interlocked.CompareExchange(ref s_getSourceLineInfo, getSourceLineInfo, null);
131133
}
132134

133135
for (int index = 0; index < iFrameCount; index++)
@@ -136,7 +138,7 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce
136138
// ENC or the source/line info was already retrieved, the method token is 0.
137139
if (rgiMethodToken[index] != 0)
138140
{
139-
getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index],
141+
s_getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index],
140142
rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index],
141143
rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]);
142144
}
@@ -151,18 +153,6 @@ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exce
151153
}
152154
}
153155

154-
void IDisposable.Dispose()
155-
{
156-
if (getSourceLineInfo != null)
157-
{
158-
IDisposable disposable = getSourceLineInfo.Target as IDisposable;
159-
if (disposable != null)
160-
{
161-
disposable.Dispose();
162-
}
163-
}
164-
}
165-
166156
public virtual MethodBase GetMethodBase(int i)
167157
{
168158
// There may be a better way to do this.
@@ -362,56 +352,57 @@ private void CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThrea
362352
{
363353
m_iMethodsToSkip += iSkip;
364354

365-
using (StackFrameHelper StackF = new StackFrameHelper(targetThread))
366-
{
367-
StackF.InitializeSourceInfo(0, fNeedFileInfo, e);
368-
369-
m_iNumOfFrames = StackF.GetNumberOfFrames();
355+
StackFrameHelper StackF = new StackFrameHelper(targetThread);
356+
357+
StackF.InitializeSourceInfo(0, fNeedFileInfo, e);
370358

371-
if (m_iMethodsToSkip > m_iNumOfFrames)
372-
m_iMethodsToSkip = m_iNumOfFrames;
359+
m_iNumOfFrames = StackF.GetNumberOfFrames();
373360

374-
if (m_iNumOfFrames != 0)
375-
{
376-
frames = new StackFrame[m_iNumOfFrames];
361+
if (m_iMethodsToSkip > m_iNumOfFrames)
362+
m_iMethodsToSkip = m_iNumOfFrames;
377363

378-
for (int i = 0; i < m_iNumOfFrames; i++)
379-
{
380-
bool fDummy1 = true;
381-
bool fDummy2 = true;
382-
StackFrame sfTemp = new StackFrame(fDummy1, fDummy2);
364+
if (m_iNumOfFrames != 0)
365+
{
366+
frames = new StackFrame[m_iNumOfFrames];
383367

384-
sfTemp.SetMethodBase(StackF.GetMethodBase(i));
385-
sfTemp.SetOffset(StackF.GetOffset(i));
386-
sfTemp.SetILOffset(StackF.GetILOffset(i));
368+
for (int i = 0; i < m_iNumOfFrames; i++)
369+
{
370+
bool fDummy1 = true;
371+
bool fDummy2 = true;
372+
StackFrame sfTemp = new StackFrame(fDummy1, fDummy2);
387373

388-
sfTemp.SetIsLastFrameFromForeignExceptionStackTrace(StackF.IsLastFrameFromForeignExceptionStackTrace(i));
374+
sfTemp.SetMethodBase(StackF.GetMethodBase(i));
375+
sfTemp.SetOffset(StackF.GetOffset(i));
376+
sfTemp.SetILOffset(StackF.GetILOffset(i));
389377

390-
if (fNeedFileInfo)
391-
{
392-
sfTemp.SetFileName(StackF.GetFilename(i));
393-
sfTemp.SetLineNumber(StackF.GetLineNumber(i));
394-
sfTemp.SetColumnNumber(StackF.GetColumnNumber(i));
395-
}
378+
sfTemp.SetIsLastFrameFromForeignExceptionStackTrace(StackF.IsLastFrameFromForeignExceptionStackTrace(i));
396379

397-
frames[i] = sfTemp;
380+
if (fNeedFileInfo)
381+
{
382+
sfTemp.SetFileName(StackF.GetFilename(i));
383+
sfTemp.SetLineNumber(StackF.GetLineNumber(i));
384+
sfTemp.SetColumnNumber(StackF.GetColumnNumber(i));
398385
}
399386

400-
// CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
401-
// but this is not desired if building a stack trace from an exception.
402-
if (e == null)
403-
m_iMethodsToSkip += CalculateFramesToSkip(StackF, m_iNumOfFrames);
387+
frames[i] = sfTemp;
388+
}
404389

405-
m_iNumOfFrames -= m_iMethodsToSkip;
406-
if (m_iNumOfFrames < 0)
407-
{
408-
m_iNumOfFrames = 0;
409-
}
390+
// CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
391+
// but this is not desired if building a stack trace from an exception.
392+
if (e == null)
393+
m_iMethodsToSkip += CalculateFramesToSkip(StackF, m_iNumOfFrames);
394+
395+
m_iNumOfFrames -= m_iMethodsToSkip;
396+
if (m_iNumOfFrames < 0)
397+
{
398+
m_iNumOfFrames = 0;
410399
}
400+
}
411401

412-
// In case this is the same object being re-used, set frames to null
413-
else
414-
frames = null;
402+
// In case this is the same object being re-used, set frames to null
403+
else
404+
{
405+
frames = null;
415406
}
416407
}
417408

src/vm/debugdebugger.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class StackFrameHelper : public Object
6060

6161
BOOLARRAYREF rgiLastFrameFromForeignExceptionStackTrace;
6262

63-
OBJECTREF getSourceLineInfo;
6463
int iFrameCount;
6564

6665
protected:

src/vm/mscorlib.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,6 @@ DEFINE_FIELD_U(rgFilename, StackFrameHelper, rgFilename)
847847
DEFINE_FIELD_U(rgiLineNumber, StackFrameHelper, rgiLineNumber)
848848
DEFINE_FIELD_U(rgiColumnNumber, StackFrameHelper, rgiColumnNumber)
849849
DEFINE_FIELD_U(rgiLastFrameFromForeignExceptionStackTrace, StackFrameHelper, rgiLastFrameFromForeignExceptionStackTrace)
850-
DEFINE_FIELD_U(getSourceLineInfo, StackFrameHelper, getSourceLineInfo)
851850
DEFINE_FIELD_U(iFrameCount, StackFrameHelper, iFrameCount)
852851

853852
DEFINE_CLASS(STREAM, IO, Stream)

0 commit comments

Comments
 (0)