diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 7f8369c2f7..6950b9c51c 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -4,13 +4,13 @@
https://github.com/dotnet/symstore
e09f81a0b38786cb20f66b589a8b88b6997a62da
-
+
https://github.com/microsoft/clrmd
- e61e6bdb23739ad2c59616b6c8d6659f4558c88d
+ 3368bf4451a9441076595022fdff0f2bbea57b1b
-
+
https://github.com/microsoft/clrmd
- e61e6bdb23739ad2c59616b6c8d6659f4558c88d
+ 3368bf4451a9441076595022fdff0f2bbea57b1b
diff --git a/eng/Versions.props b/eng/Versions.props
index 143aad16b7..6f24f21666 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -45,7 +45,7 @@
5.0.0
1.1.0
- 3.0.0-beta.23177.1
+ 3.0.0-beta.23205.1
16.9.0-beta1.21055.5
3.0.7
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/ExtensionMethodHelpers.cs b/src/Microsoft.Diagnostics.ExtensionCommands/ExtensionMethodHelpers.cs
index 15f81d59ff..5f35b39381 100644
--- a/src/Microsoft.Diagnostics.ExtensionCommands/ExtensionMethodHelpers.cs
+++ b/src/Microsoft.Diagnostics.ExtensionCommands/ExtensionMethodHelpers.cs
@@ -37,39 +37,5 @@ internal static ulong FindMostCommonPointer(this IEnumerable enumerable)
group ptr by ptr into g
orderby g.Count() descending
select g.First()).First();
-
- internal static Generation GetGeneration(this ClrObject obj, ClrSegment knownSegment)
- {
- if (knownSegment is null)
- {
- knownSegment = obj.Type.Heap.GetSegmentByAddress(obj);
- if (knownSegment is null)
- {
- return Generation.Error;
- }
- }
-
- if (knownSegment.Kind == GCSegmentKind.Ephemeral)
- {
- return knownSegment.GetGeneration(obj) switch
- {
- 0 => Generation.Gen0,
- 1 => Generation.Gen1,
- 2 => Generation.Gen2,
- _ => Generation.Error
- };
- }
-
- return knownSegment.Kind switch
- {
- GCSegmentKind.Generation0 => Generation.Gen0,
- GCSegmentKind.Generation1 => Generation.Gen1,
- GCSegmentKind.Generation2 => Generation.Gen2,
- GCSegmentKind.Large => Generation.Large,
- GCSegmentKind.Pinned => Generation.Pinned,
- GCSegmentKind.Frozen => Generation.Frozen,
- _ => Generation.Error
- };
- }
}
}
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/FindEphemeralReferencesToLOHCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/FindEphemeralReferencesToLOHCommand.cs
index d28166badb..c7fa399b83 100644
--- a/src/Microsoft.Diagnostics.ExtensionCommands/FindEphemeralReferencesToLOHCommand.cs
+++ b/src/Microsoft.Diagnostics.ExtensionCommands/FindEphemeralReferencesToLOHCommand.cs
@@ -130,8 +130,8 @@ public override void Invoke()
Console.CancellationToken.ThrowIfCancellationRequested();
// This handles both regions and segments
- Generation gen = obj.GetGeneration(seg);
- if (gen is not Generation.Gen0 or Generation.Gen1)
+ Generation gen = seg.GetGeneration(obj);
+ if (gen is not Generation.Generation0 or Generation.Generation1)
{
continue;
}
@@ -145,8 +145,7 @@ public override void Invoke()
continue;
}
- Generation refGen = objRef.GetGeneration(null);
- if (refGen == Generation.Large)
+ if (GetGenerationWithoutSegment(objRef) == Generation.Large)
{
yield return (obj, objRef);
}
@@ -174,8 +173,7 @@ public override void Invoke()
continue;
}
- Generation refGen = objRef.GetGeneration(null);
- if (refGen is Generation.Gen0 or Generation.Gen1)
+ if (GetGenerationWithoutSegment(objRef) is Generation.Generation0 or Generation.Generation1)
{
yield return (obj, objRef);
}
@@ -183,5 +181,16 @@ public override void Invoke()
}
}
}
+
+ private Generation GetGenerationWithoutSegment(ClrObject obj)
+ {
+ ClrSegment seg = Runtime.Heap.GetSegmentByAddress(obj);
+ if (seg is not null)
+ {
+ return seg.GetGeneration(obj);
+ }
+
+ return Generation.Unknown;
+ }
}
}
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/FindReferencesToEphemeralCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/FindReferencesToEphemeralCommand.cs
index e77660dbd1..8c5f3c0eac 100644
--- a/src/Microsoft.Diagnostics.ExtensionCommands/FindReferencesToEphemeralCommand.cs
+++ b/src/Microsoft.Diagnostics.ExtensionCommands/FindReferencesToEphemeralCommand.cs
@@ -88,8 +88,8 @@ private IEnumerable FindObjectsWithEphemeralReferences()
Console.CancellationToken.ThrowIfCancellationRequested();
// Skip this object if it's gen0 or we hit an error
- Generation objGen = obj.GetGeneration(seg);
- if (objGen is Generation.Gen0 or Generation.Error)
+ Generation objGen = seg.GetGeneration(obj);
+ if (objGen is Generation.Generation0 or Generation.Unknown)
{
continue;
}
@@ -108,10 +108,11 @@ private IEnumerable FindObjectsWithEphemeralReferences()
ulong refObjSize = objRef.Size;
- Generation refGen = objRef.GetGeneration(null);
+ ClrSegment refSeg = Runtime.Heap.GetSegmentByAddress(objRef);
+ Generation refGen = refSeg?.GetGeneration(objRef) ?? Generation.Unknown;
switch (refGen)
{
- case Generation.Gen0:
+ case Generation.Generation0:
gen0 ??= new EphemeralRefCount()
{
Object = obj,
@@ -128,8 +129,8 @@ private IEnumerable FindObjectsWithEphemeralReferences()
break;
- case Generation.Gen1:
- if (objGen > Generation.Gen1)
+ case Generation.Generation1:
+ if (objGen > Generation.Generation1)
{
gen1 ??= new EphemeralRefCount()
{
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/GCHeapStatCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/GCHeapStatCommand.cs
index 062eb694b9..a7c24db50a 100644
--- a/src/Microsoft.Diagnostics.ExtensionCommands/GCHeapStatCommand.cs
+++ b/src/Microsoft.Diagnostics.ExtensionCommands/GCHeapStatCommand.cs
@@ -217,25 +217,22 @@ private HeapInfo GetHeapInfo(ClrSubHeap heap)
continue;
}
- GenerationInfo gen = seg.GetGeneration(obj) switch
+ GenerationInfo genInfo = result.GetInfoByGeneration(seg.GetGeneration(obj));
+ if (genInfo is not null)
{
- 0 => result.Gen0,
- 1 => result.Gen1,
- _ => result.Gen2,
- };
-
- if (obj.IsFree)
- {
- result.Ephemeral.Free += obj.Size;
- gen.Free += obj.Size;
- }
- else
- {
- gen.Allocated += obj.Size;
-
- if (IncludeUnreachable && !LiveObjects.IsLive(obj))
+ if (obj.IsFree)
+ {
+ result.Ephemeral.Free += obj.Size;
+ genInfo.Free += obj.Size;
+ }
+ else
{
- gen.Unrooted += obj.Size;
+ genInfo.Allocated += obj.Size;
+
+ if (IncludeUnreachable && !LiveObjects.IsLive(obj))
+ {
+ genInfo.Unrooted += obj.Size;
+ }
}
}
}
@@ -307,6 +304,20 @@ private sealed class HeapInfo
Frozen = left.Frozen + right.Frozen,
};
}
+
+ public GenerationInfo GetInfoByGeneration(Generation gen)
+ {
+ return gen switch
+ {
+ Generation.Generation0 => Gen0,
+ Generation.Generation1 => Gen1,
+ Generation.Generation2 => Gen2,
+ Generation.Large => LoH,
+ Generation.Pinned => PoH,
+ Generation.Frozen => Frozen,
+ _ => null
+ };
+ }
}
private sealed class GenerationInfo
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/GCWhereCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/GCWhereCommand.cs
index 3967c4bb32..fad8d35df1 100644
--- a/src/Microsoft.Diagnostics.ExtensionCommands/GCWhereCommand.cs
+++ b/src/Microsoft.Diagnostics.ExtensionCommands/GCWhereCommand.cs
@@ -54,22 +54,18 @@ public override void Invoke()
{
generation = "reserve";
}
- else if (segment.Kind == GCSegmentKind.Frozen)
- {
- generation = "frozen";
- }
- else if (segment.Kind == GCSegmentKind.Pinned)
- {
- generation = "pinned";
- }
- else if (segment.Kind == GCSegmentKind.Large)
- {
- generation = "large";
- }
else
{
- int gen = segment.GetGeneration(address);
- generation = gen != -1 ? gen.ToString() : "???";
+ generation = segment.GetGeneration(address) switch
+ {
+ Generation.Generation0 => "0",
+ Generation.Generation1 => "1",
+ Generation.Generation2 => "2",
+ Generation.Frozen => "frozen",
+ Generation.Pinned => "pinned",
+ Generation.Large => "large",
+ _ => "???",
+ };
}
object addressColumn = segment.ObjectRange.Contains(address) ? new DmlListNearObj(address) : address;
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/Generation.cs b/src/Microsoft.Diagnostics.ExtensionCommands/Generation.cs
deleted file mode 100644
index 990ef71a2d..0000000000
--- a/src/Microsoft.Diagnostics.ExtensionCommands/Generation.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.Diagnostics.ExtensionCommands
-{
- internal enum Generation
- {
- Gen0,
- Gen1,
- Gen2,
- Large,
- Pinned,
- Frozen,
- Error,
- }
-}
diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/SizeStatsCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/SizeStatsCommand.cs
index 61e88f7a37..5208edaa48 100644
--- a/src/Microsoft.Diagnostics.ExtensionCommands/SizeStatsCommand.cs
+++ b/src/Microsoft.Diagnostics.ExtensionCommands/SizeStatsCommand.cs
@@ -16,9 +16,9 @@ public sealed class SizeStatsCommand : CommandBase
public override void Invoke()
{
- SizeStats(Generation.Gen0, isFree: false);
- SizeStats(Generation.Gen1, isFree: false);
- SizeStats(Generation.Gen2, isFree: false);
+ SizeStats(Generation.Generation0, isFree: false);
+ SizeStats(Generation.Generation1, isFree: false);
+ SizeStats(Generation.Generation2, isFree: false);
SizeStats(Generation.Large, isFree: false);
bool hasPinned = Runtime.Heap.Segments.Any(seg => seg.Kind == GCSegmentKind.Pinned);
@@ -32,9 +32,9 @@ public override void Invoke()
SizeStats(Generation.Frozen, isFree: false);
}
- SizeStats(Generation.Gen0, isFree: true);
- SizeStats(Generation.Gen1, isFree: true);
- SizeStats(Generation.Gen2, isFree: true);
+ SizeStats(Generation.Generation0, isFree: true);
+ SizeStats(Generation.Generation1, isFree: true);
+ SizeStats(Generation.Generation2, isFree: true);
SizeStats(Generation.Large, isFree: true);
if (hasPinned)
@@ -62,7 +62,7 @@ private void SizeStats(Generation requestedGen, bool isFree)
// If Kind == Ephemeral, we have to further filter by object generation
if (seg.Kind == GCSegmentKind.Ephemeral)
{
- if (obj.GetGeneration(seg) != requestedGen)
+ if (seg.GetGeneration(obj) != requestedGen)
{
continue;
}
@@ -104,10 +104,10 @@ private static bool FilterByGeneration(ClrSegment seg, Generation gen)
{
return seg.Kind switch
{
- GCSegmentKind.Ephemeral => gen <= Generation.Gen2,
- GCSegmentKind.Generation0 => gen == Generation.Gen0,
- GCSegmentKind.Generation1 => gen == Generation.Gen1,
- GCSegmentKind.Generation2 => gen == Generation.Gen2,
+ GCSegmentKind.Ephemeral => gen <= Generation.Generation2,
+ GCSegmentKind.Generation0 => gen == Generation.Generation0,
+ GCSegmentKind.Generation1 => gen == Generation.Generation1,
+ GCSegmentKind.Generation2 => gen == Generation.Generation2,
GCSegmentKind.Frozen => gen == Generation.Frozen,
GCSegmentKind.Pinned => gen == Generation.Pinned,
GCSegmentKind.Large => gen == Generation.Large,