Browse Source

Add more enumerator debugging.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
769990ef04
  1. 43
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  2. 66
      ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs

43
ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

@ -199,36 +199,37 @@ namespace ICSharpCode.Decompiler.IL @@ -199,36 +199,37 @@ namespace ICSharpCode.Decompiler.IL
#if DEBUG
int activeEnumerators;
#endif
[Conditional("DEBUG")]
internal void AssertNoEnumerators()
{
#if DEBUG
Debug.Assert(activeEnumerators == 0);
#endif
}
[Conditional("DEBUG")]
internal void StartEnumerator()
{
#if DEBUG
activeEnumerators++;
#endif
}
[Conditional("DEBUG")]
internal void StopEnumerator()
{
#if DEBUG
Debug.Assert(activeEnumerators > 0);
activeEnumerators--;
}
#endif
[Conditional("DEBUG")]
internal void AssertNoEnumerators()
{
#if DEBUG
Debug.Assert(activeEnumerators == 0);
#endif
}
/// <summary>
/// Enumerator over the children of an ILInstruction.
/// Warning: even though this is a struct, it is invalid to copy:
/// the number of constructor calls must match the number of dispose calls.
/// </summary>
public struct ChildrenEnumerator : IEnumerator<ILInstruction>
{
readonly ILInstruction inst;
ILInstruction inst;
readonly int end;
int pos;
@ -238,7 +239,9 @@ namespace ICSharpCode.Decompiler.IL @@ -238,7 +239,9 @@ namespace ICSharpCode.Decompiler.IL
this.inst = inst;
this.pos = -1;
this.end = inst.GetChildCount();
#if DEBUG
inst.StartEnumerator();
#endif
}
public ILInstruction Current {
@ -254,7 +257,12 @@ namespace ICSharpCode.Decompiler.IL @@ -254,7 +257,12 @@ namespace ICSharpCode.Decompiler.IL
public void Dispose()
{
inst.StopEnumerator();
#if DEBUG
if (inst != null) {
inst.StopEnumerator();
inst = null;
}
#endif
}
object System.Collections.IEnumerator.Current {
@ -263,7 +271,7 @@ namespace ICSharpCode.Decompiler.IL @@ -263,7 +271,7 @@ namespace ICSharpCode.Decompiler.IL
void System.Collections.IEnumerator.Reset()
{
throw new NotSupportedException();
pos = -1;
}
}
#endregion
@ -303,15 +311,14 @@ namespace ICSharpCode.Decompiler.IL @@ -303,15 +311,14 @@ namespace ICSharpCode.Decompiler.IL
}
enumerator.Dispose();
if (stack.Count > 0) {
yield return stack.Peek().Current;
// Pop enumerator only after yielding, so that it gets
// disposed if the enumeration is aborted.
enumerator = stack.Pop();
yield return enumerator.Current;
} else {
break;
}
}
} finally {
enumerator.Dispose();
while (stack.Count > 0) {
stack.Pop().Dispose();
}

66
ICSharpCode.Decompiler/IL/Instructions/InstructionCollection.cs

@ -56,20 +56,78 @@ namespace ICSharpCode.Decompiler.IL @@ -56,20 +56,78 @@ namespace ICSharpCode.Decompiler.IL
}
}
public List<T>.Enumerator GetEnumerator()
#region GetEnumerator
public Enumerator GetEnumerator()
{
return list.GetEnumerator();
return new Enumerator(this);
}
/// <summary>
/// Custom enumerator for InstructionCollection.
/// Unlike List{T}.Enumerator, this enumerator allows replacing an item during the enumeration.
/// Adding/removing items from the collection still is invalid (however, such
/// invalid actions are only detected in debug builds).
///
/// Warning: even though this is a struct, it is invalid to copy:
/// the number of constructor calls must match the number of dispose calls.
/// </summary>
public struct Enumerator : IEnumerator<T>
{
#if DEBUG
ILInstruction parentInstruction;
#endif
readonly List<T> list;
int pos;
public Enumerator(InstructionCollection<T> col)
{
this.list = col.list;
this.pos = -1;
#if DEBUG
this.parentInstruction = col.parentInstruction;
col.parentInstruction.StartEnumerator();
#endif
}
public bool MoveNext()
{
return ++pos < list.Count;
}
public T Current {
get { return list[pos]; }
}
public void Dispose()
{
#if DEBUG
if (parentInstruction != null) {
parentInstruction.StopEnumerator();
parentInstruction = null;
}
#endif
}
void System.Collections.IEnumerator.Reset()
{
pos = -1;
}
object System.Collections.IEnumerator.Current {
get { return this.Current; }
}
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return list.GetEnumerator();
return GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
return GetEnumerator();
}
#endregion
/// <summary>
/// Gets the index of the instruction in this collection.

Loading…
Cancel
Save