From 3bd1eff057442ba320963ae78d8ed048de9461d6 Mon Sep 17 00:00:00 2001 From: Lee Culver Date: Thu, 6 Apr 2023 17:21:23 -0700 Subject: [PATCH] Update ClrMD version (#3804) I moved the the "Generation" enum to ClrMD itself. It's far more useful (and accurate) to talk about an object's generation as a member of an enum which describes it rather than a simple integer. This change flowed through the SOS commands which used ClrSegment.GetGeneration. I manually tested all commands affected. --- eng/Version.Details.xml | 8 ++-- eng/Versions.props | 2 +- .../ExtensionMethodHelpers.cs | 34 -------------- .../FindEphemeralReferencesToLOHCommand.cs | 21 ++++++--- .../FindReferencesToEphemeralCommand.cs | 13 +++--- .../GCHeapStatCommand.cs | 45 ++++++++++++------- .../GCWhereCommand.cs | 24 +++++----- .../Generation.cs | 16 ------- .../SizeStatsCommand.cs | 22 ++++----- 9 files changed, 76 insertions(+), 109 deletions(-) delete mode 100644 src/Microsoft.Diagnostics.ExtensionCommands/Generation.cs diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index c3a99f987..74f2539ed 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 a9e72015c..9fad78388 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 15f81d59f..5f35b3938 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/ExtensionMethodHelpers.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/ExtensionMethodHelpers.cs @@ -37,39 +37,5 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 d28166bad..c7fa399b8 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/FindEphemeralReferencesToLOHCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/FindEphemeralReferencesToLOHCommand.cs @@ -130,8 +130,8 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands continue; } - Generation refGen = objRef.GetGeneration(null); - if (refGen == Generation.Large) + if (GetGenerationWithoutSegment(objRef) == Generation.Large) { yield return (obj, objRef); } @@ -174,8 +173,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands } } } + + 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 e77660dbd..8c5f3c0ea 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/FindReferencesToEphemeralCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/FindReferencesToEphemeralCommand.cs @@ -88,8 +88,8 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 062eb694b..a7c24db50 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/GCHeapStatCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/GCHeapStatCommand.cs @@ -217,25 +217,22 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 3967c4bb3..fad8d35df 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/GCWhereCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/GCWhereCommand.cs @@ -54,22 +54,18 @@ namespace Microsoft.Diagnostics.ExtensionCommands { 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 990ef71a2..000000000 --- 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 61e88f7a3..5208edaa4 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/SizeStatsCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/SizeStatsCommand.cs @@ -16,9 +16,9 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands // 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 @@ namespace Microsoft.Diagnostics.ExtensionCommands { 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, -- 2.34.1