diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs
index 5e3040cfa6..1752558873 100644
--- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewNode.cs
@@ -88,6 +88,7 @@ namespace Debugger.AddIn.TreeModel
if (loadChildsWhenExpanding) {
loadChildsWhenExpanding = false;
SetContentRecursive(this.Tree, this.Children, this.Content.ChildNodes);
+ this.IsExpandedOnce = true;
}
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
index 9c85b0b9bc..fb18b90013 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
@@ -202,7 +202,6 @@
-
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
index 9e9a322baf..a9d87998b0 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
@@ -58,11 +58,6 @@ namespace Debugger
pauseProcessInsteadOfContinue = false;
}
- // Remove expired threads and functions
- foreach(Thread thread in process.Threads) {
- thread.CheckExpiration();
- }
-
process.NotifyPaused(new PauseSession(pausedReason));
} else {
throw new DebuggerException("Invalid state at the start of callback");
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/FrameID.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/FrameID.cs
deleted file mode 100644
index b42701002c..0000000000
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/FrameID.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-//
-//
-//
-// $Revision$
-//
-
-using System;
-
-namespace Debugger
-{
- ///
- /// Identifies frame on thread callstack
- ///
- struct FrameID {
- uint chainIndex;
- uint frameIndex;
-
- public uint ChainIndex {
- get {
- return chainIndex;
- }
- }
-
- public uint FrameIndex {
- get {
- return frameIndex;
- }
- }
-
- public FrameID(uint chainIndex, uint frameIndex)
- {
- this.chainIndex = chainIndex;
- this.frameIndex = frameIndex;
- }
-
- public override int GetHashCode()
- {
- return chainIndex.GetHashCode() ^ frameIndex.GetHashCode();
- }
-
- public override bool Equals(object obj)
- {
- if (!(obj is FrameID)) return false;
- FrameID myFrameID = (FrameID)obj;
- return this.chainIndex == myFrameID.chainIndex && this.frameIndex == myFrameID.frameIndex;
- }
-
- public override string ToString()
- {
- return string.Format("{0},{1}", this.chainIndex, this.frameIndex);
- }
- }
-}
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs
index 26330814c1..32d745d746 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs
@@ -141,12 +141,6 @@ namespace Debugger
corProcess.Stop(5000); // TODO: Hardcoded value
pauseSession = new PauseSession(PausedReason.ForcedBreak);
-
- // TODO: Code duplication from enter callback
- // Remove expired threads and functions
- foreach(Thread thread in this.Threads) {
- thread.CheckExpiration();
- }
Pause(true);
}
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/StackFrame.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/StackFrame.cs
index b1a2714ffd..0b067bb41b 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/StackFrame.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/StackFrame.cs
@@ -19,21 +19,16 @@ namespace Debugger
/// A stack frame which is being executed on some thread.
/// Use to obtain arguments or local variables.
///
- public class StackFrame: DebuggerObject, IExpirable
+ public class StackFrame: DebuggerObject
{
Process process;
+ Thread thread;
- MethodInfo methodInfo;
-
- ICorDebugFunction corFunction;
ICorDebugILFrame corILFrame;
object corILFramePauseSession;
+ ICorDebugFunction corFunction;
- Stepper stepOutStepper;
-
- bool steppedOut = false;
- Thread thread;
- FrameID frameID;
+ MethodInfo methodInfo;
/// The process in which this stack frame is executed
[Debugger.Tests.Ignore]
@@ -67,32 +62,17 @@ namespace Debugger
/// True if stack frame stepped out and is not longer valid.
public bool HasExpired {
get {
- return steppedOut || this.MethodInfo.Module.Unloaded;
+ return this.corILFramePauseSession != process.PauseSession;
}
}
- /// Occurs when stack frame expires and is no longer usable
- public event EventHandler Expired;
-
- /// Is called when stack frame expires and is no longer usable
- internal protected virtual void OnExpired(EventArgs e)
- {
- if (!steppedOut) {
- steppedOut = true;
- process.TraceMessage("StackFrame " + this.ToString() + " expired");
- if (Expired != null) {
- Expired(this, e);
- }
- }
- }
-
- internal StackFrame(Thread thread, FrameID frameID, ICorDebugILFrame corILFrame)
+ internal StackFrame(Thread thread, ICorDebugILFrame corILFrame)
{
this.process = thread.Process;
this.thread = thread;
- this.frameID = frameID;
- this.CorILFrame = corILFrame;
- corFunction = corILFrame.Function;
+ this.corILFrame = corILFrame;
+ this.corILFramePauseSession = process.PauseSession;
+ this.corFunction = corILFrame.Function;
DebugType debugType = DebugType.Create(
this.Process,
@@ -101,34 +81,19 @@ namespace Debugger
);
MethodProps methodProps = process.GetModule(corFunction.Module).MetaData.GetMethodProps(corFunction.Token);
this.methodInfo = new MethodInfo(debugType, methodProps);
-
- // Force some callback when stack frame steps out so that we can expire it
- stepOutStepper = new Stepper(this, "StackFrame Tracker");
- stepOutStepper.StepOut();
- stepOutStepper.PauseWhenComplete = false;
-
- process.TraceMessage("StackFrame " + this.ToString() + " created");
}
/// Returns diagnostic description of the frame
public override string ToString()
{
- return this.MethodInfo.Name + "(" + frameID.ToString() + ")";
+ return this.MethodInfo.FullName;
}
internal ICorDebugILFrame CorILFrame {
get {
if (HasExpired) throw new DebuggerException("StackFrame has expired");
- if (corILFramePauseSession != process.PauseSession) {
- CorILFrame = thread.GetFrameAt(frameID).As();
- }
return corILFrame;
}
- set {
- if (value == null) throw new DebuggerException("Can not set frame to null");
- corILFrame = value;
- corILFramePauseSession = process.PauseSession;
- }
}
internal uint CorInstructionPtr {
diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs
index 6234e3b4b2..8066240eab 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs
@@ -14,7 +14,7 @@ using Debugger.Wrappers.CorDebug;
namespace Debugger
{
- public partial class Thread: DebuggerObject, IExpirable
+ public partial class Thread: DebuggerObject
{
Process process;
@@ -251,7 +251,7 @@ namespace Debugger
if (corFrame.Is()) {
StackFrame stackFrame;
try {
- stackFrame = GetStackFrameFromCache(new FrameID(corChain.Index, corFrame.Index), corFrame.As());
+ stackFrame = new StackFrame(this, corFrame.CastTo());
} catch (COMException) { // TODO
continue;
};
@@ -262,95 +262,6 @@ namespace Debugger
}
}
- Dictionary functionCache = new Dictionary();
-
- StackFrame GetStackFrameFromCache(FrameID frameID, ICorDebugILFrame corFrame)
- {
- StackFrame stackFrame;
- if (functionCache.TryGetValue(frameID, out stackFrame) && !stackFrame.HasExpired) {
- stackFrame.CorILFrame = corFrame;
- return stackFrame;
- } else {
- stackFrame = new StackFrame(this, frameID, corFrame);
- functionCache[frameID] = stackFrame;
- return stackFrame;
- }
- }
-
- internal ICorDebugFrame GetFrameAt(FrameID frameID)
- {
- process.AssertPaused();
-
- ICorDebugChainEnum corChainEnum = CorThread.EnumerateChains();
- if (frameID.ChainIndex >= corChainEnum.Count) throw new ArgumentException("Chain index too big", "chainIndex");
- corChainEnum.Skip(corChainEnum.Count - frameID.ChainIndex - 1);
-
- ICorDebugChain corChain = corChainEnum.Next();
-
- if (corChain.IsManaged == 0) throw new ArgumentException("Chain is not managed", "chainIndex");
-
- ICorDebugFrameEnum corFrameEnum = corChain.EnumerateFrames();
- if (frameID.FrameIndex >= corFrameEnum.Count) throw new ArgumentException("Frame index too big", "frameIndex");
- corFrameEnum.Skip(corFrameEnum.Count - frameID.FrameIndex - 1);
-
- return corFrameEnum.Next();
- }
-
- // See docs\Stepping.txt
- internal void CheckExpiration()
- {
- try {
- ICorDebugChainEnum chainEnum = CorThread.EnumerateChains();
- } catch (COMException e) {
- // 0x8013132D: The state of the thread is invalid.
- // 0x8013134F: Object is in a zombie state
- // 0x80131301: Process was terminated.
- if ((uint)e.ErrorCode == 0x8013132D ||
- (uint)e.ErrorCode == 0x8013134F ||
- (uint)e.ErrorCode == 0x80131301) {
-
- this.Expire();
- return;
- } else throw;
- }
-
- if (process.Evaluating) return;
-
- ICorDebugChainEnum corChainEnum = CorThread.EnumerateChains();
- int maxChainIndex = (int)corChainEnum.Count - 1;
-
- ICorDebugFrameEnum corFrameEnum = corChainEnum.Next().EnumerateFrames();
- // corFrameEnum.Count can return 0 in ExitThread callback
- int maxFrameIndex = (int)corFrameEnum.Count - 1;
-
- ICorDebugFrame lastFrame = corFrameEnum.Next();
-
- // Check the token of the current stack frame - stack frame can change if there are multiple handlers for an event
- StackFrame stackFrame;
- if (lastFrame != null &&
- functionCache.TryGetValue(new FrameID((uint)maxChainIndex, (uint)maxFrameIndex), out stackFrame) &&
- stackFrame.MethodInfo.MetadataToken != lastFrame.FunctionToken) {
-
- functionCache.Remove(new FrameID((uint)maxChainIndex, (uint)maxFrameIndex));
- stackFrame.OnExpired(EventArgs.Empty);
- }
-
- // Expire all functions behind the current maximum
- // Multiple functions can expire at once (test case: Step out of Button1Click in simple winforms application)
- List> toBeRemoved = new List>();
- foreach(KeyValuePair kvp in functionCache) {
- if ((kvp.Key.ChainIndex > maxChainIndex) ||
- (kvp.Key.ChainIndex == maxChainIndex && kvp.Key.FrameIndex > maxFrameIndex)) {
-
- toBeRemoved.Add(kvp);
- }
- }
- foreach(KeyValuePair kvp in toBeRemoved){
- functionCache.Remove(kvp.Key);
- kvp.Value.OnExpired(EventArgs.Empty);
- }
- }
-
[Debugger.Tests.ToStringOnly]
public StackFrame SelectedStackFrame {
get {
diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/DebuggerTests.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/DebuggerTests.cs
index 576228770c..b3255c1602 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/DebuggerTests.cs
+++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/DebuggerTests.cs
@@ -187,27 +187,26 @@ namespace Debugger.Tests
[Test]
public void FunctionLifetime()
{
- StackFrame stackFrame;
-
StartTest("FunctionLifetime");
WaitForPause();
- stackFrame = process.SelectedStackFrame;
- ObjectDump("StackFrame", stackFrame);
+ StackFrame stackFrame = process.SelectedStackFrame;
+ ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
process.Continue(); // Go to the SubFunction
WaitForPause();
- ObjectDump("StackFrame", stackFrame);
- ObjectDump("SubStackFrame", process.SelectedStackFrame);
+ ObjectDump("Old StackFrame", stackFrame);
+ ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
process.Continue(); // Go back to Function
WaitForPause();
- Assert.AreEqual(stackFrame, process.SelectedStackFrame);
- ObjectDump("StackFrame", stackFrame);
+ ObjectDump("Old StackFrame", stackFrame);
+ ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
process.Continue(); // Setp out of function
WaitForPause();
ObjectDump("Main", process.SelectedStackFrame);
- ObjectDump("StackFrame", stackFrame);
+ ObjectDump("Old StackFrame", stackFrame);
+ ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
process.Continue();
process.WaitForExit();
diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/FunctionLifetime.xml b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/FunctionLifetime.xml
index 1a7976a878..0c642ee73c 100644
--- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/FunctionLifetime.xml
+++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/FunctionLifetime.xml
@@ -5,7 +5,7 @@
mscorlib.dll
FunctionLifetime.exe
Break
-
+
@@ -61,7 +61,7 @@
Break
-
+
@@ -76,8 +76,8 @@
True
- False
- Start=23,4 End=23,18
+ True
+
@@ -85,29 +85,8 @@
- 1
-
-
- 1
-
-
- False
-
-
-
- False
- True
- True
- 1
- i
- False
- 1
- False
- System.Int32
-
-
-
-
+
+
0
@@ -116,7 +95,7 @@
-
+
@@ -156,7 +135,41 @@
Break
-
+
+
+
+
+ Function
+ Debugger.Tests.TestPrograms.FunctionLifetime.Function
+ True
+ False
+ False
+ True
+ FunctionLifetime.exe
+ Debugger.Tests.TestPrograms.FunctionLifetime
+
+
+ True
+ True
+
+
+
+
+ 0
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
@@ -251,7 +264,7 @@
-
+
@@ -285,6 +298,45 @@
+
+
+
+
+ Main
+ Debugger.Tests.TestPrograms.FunctionLifetime.Main
+ False
+ True
+ False
+ True
+ FunctionLifetime.exe
+ Debugger.Tests.TestPrograms.FunctionLifetime
+
+
+ True
+ False
+ Start=17,4 End=17,40
+
+
+
+ 0
+
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+ 0
+
+
+
+
+
\ No newline at end of file