From 7a8108c68a1d870175dab2b79ebe0c89b9287d57 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tom=C3=A1=C5=A1=20Rylek?= Date: Thu, 5 Nov 2020 13:21:20 +0100 Subject: [PATCH] Add R2RDump support for lazy GC info (#44261) This change makes it such that GC info is not automatically parsed for each method, we only store a delegate performing the parsing that gets called on demand. In practice this also helps us with working around a bug in GC info previously crashing R2RDump when emitting PDB in ARM release build mode. Thanks Tomas --- .../ReadyToRunMethod.cs | 89 +++++++++++++++++----- src/coreclr/src/tools/r2rdump/TextDumper.cs | 8 +- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs b/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs index 10b4af9..4d08408 100644 --- a/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs +++ b/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs @@ -101,13 +101,27 @@ namespace ILCompiler.Reflection.ReadyToRun public int StartAddress { get; } /// + /// The relative virtual address to the end of the code block + /// + public int EndAddress { get; } + + /// /// The size of the code block in bytes /// /// /// /// The EndAddress field in the runtime functions section is conditional on machine type /// Size is -1 for images without the EndAddress field /// - public int Size { get; } + public int Size + { + get + { + EnsureInitialized(); + return _size; + } + } + + private int _size = -1; /// /// The relative virtual address to the unwind info @@ -171,41 +185,54 @@ namespace ILCompiler.Reflection.ReadyToRun int codeOffset, ReadyToRunMethod method, BaseUnwindInfo unwindInfo, - BaseGcInfo gcInfo) + Func gcInfo) { _readyToRunReader = readyToRunReader; + Id = id; StartAddress = startRva; + EndAddress = endRva; UnwindRVA = unwindRva; Method = method; UnwindInfo = unwindInfo; + CodeOffset = codeOffset; + method.GetGcInfo = gcInfo; + } + + private void EnsureInitialized() + { + if (_size < 0) + { + _size = GetSize(); + } + } - if (endRva != -1) + private int GetSize() + { + if (EndAddress != -1) { - Size = endRva - startRva; + return EndAddress - StartAddress; } - else if (unwindInfo is x86.UnwindInfo) + else if (UnwindInfo is x86.UnwindInfo) { - Size = (int)((x86.UnwindInfo)unwindInfo).FunctionLength; + return (int)((x86.UnwindInfo)UnwindInfo).FunctionLength; } - else if (unwindInfo is Arm.UnwindInfo) + else if (UnwindInfo is Arm.UnwindInfo) { - Size = (int)((Arm.UnwindInfo)unwindInfo).FunctionLength; + return (int)((Arm.UnwindInfo)UnwindInfo).FunctionLength; } - else if (unwindInfo is Arm64.UnwindInfo) + else if (UnwindInfo is Arm64.UnwindInfo) { - Size = (int)((Arm64.UnwindInfo)unwindInfo).FunctionLength; + return (int)((Arm64.UnwindInfo)UnwindInfo).FunctionLength; } - else if (gcInfo != null) + else if (Method.GcInfo != null) { - Size = gcInfo.CodeLength; + return Method.GcInfo.CodeLength; } else { - Size = -1; + return -1; } - CodeOffset = codeOffset; - method.GcInfo = gcInfo; } } @@ -273,7 +300,19 @@ namespace ILCompiler.Reflection.ReadyToRun /// public int EntryPointRuntimeFunctionId { get; set; } - public BaseGcInfo GcInfo { get; set; } + public Func GetGcInfo { get; set; } + + public BaseGcInfo GcInfo + { + get + { + EnsureInitialized(); + return _gcInfo; + } + } + + private BaseGcInfo _gcInfo; + private ReadyToRunReader _readyToRunReader; private List _fixupCells; @@ -404,6 +443,14 @@ namespace ILCompiler.Reflection.ReadyToRun SignatureString = sb.ToString(); } + private void EnsureInitialized() + { + if (_gcInfo == null && GetGcInfo != null) + { + _gcInfo = GetGcInfo(); + } + } + private void EnsureFixupCells() { if (_fixupCells != null) @@ -460,7 +507,7 @@ namespace ILCompiler.Reflection.ReadyToRun int runtimeFunctionSize = _readyToRunReader.CalculateRuntimeFunctionSize(); int runtimeFunctionOffset = _readyToRunReader.CompositeReader.GetOffset(_readyToRunReader.ReadyToRunHeader.Sections[ReadyToRunSectionType.RuntimeFunctions].RelativeVirtualAddress); int curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize; - BaseGcInfo gcInfo = null; + Func gcInfo = default(Func); int codeOffset = 0; for (int i = 0; i < RuntimeFunctionCount; i++) { @@ -485,7 +532,7 @@ namespace ILCompiler.Reflection.ReadyToRun unwindInfo = new Amd64.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { - gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); + gcInfo = new Func(() => new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion)); } } else if (_readyToRunReader.Machine == Machine.I386) @@ -493,7 +540,7 @@ namespace ILCompiler.Reflection.ReadyToRun unwindInfo = new x86.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { - gcInfo = new x86.GcInfo(_readyToRunReader.Image, unwindOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); + gcInfo = new Func(() => new x86.GcInfo(_readyToRunReader.Image, unwindOffset, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion)); } } else if (_readyToRunReader.Machine == Machine.ArmThumb2) @@ -501,7 +548,7 @@ namespace ILCompiler.Reflection.ReadyToRun unwindInfo = new Arm.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { - gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); // Arm and Arm64 use the same GcInfo format as x64 + gcInfo = new Func(() => new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion)); // Arm and Arm64 use the same GcInfo format as x6 } } else if (_readyToRunReader.Machine == Machine.Arm64) @@ -509,7 +556,7 @@ namespace ILCompiler.Reflection.ReadyToRun unwindInfo = new Arm64.UnwindInfo(_readyToRunReader.Image, unwindOffset); if (i == 0) { - gcInfo = new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion); + gcInfo = new Func(() => new Amd64.GcInfo(_readyToRunReader.Image, unwindOffset + unwindInfo.Size, _readyToRunReader.Machine, _readyToRunReader.ReadyToRunHeader.MajorVersion)); } } diff --git a/src/coreclr/src/tools/r2rdump/TextDumper.cs b/src/coreclr/src/tools/r2rdump/TextDumper.cs index dc0608b..682abd7 100644 --- a/src/coreclr/src/tools/r2rdump/TextDumper.cs +++ b/src/coreclr/src/tools/r2rdump/TextDumper.cs @@ -155,12 +155,13 @@ namespace R2RDump if (_options.GC && method.GcInfo != null) { + BaseGcInfo gcInfo = method.GcInfo; _writer.WriteLine("GC info:"); - _writer.Write(method.GcInfo); + _writer.Write(gcInfo); if (_options.Raw) { - DumpBytes(method.GcInfo.Offset, (uint)method.GcInfo.Size, "", false); + DumpBytes(gcInfo.Offset, (uint)gcInfo.Size, "", false); } } SkipLine(); @@ -226,7 +227,8 @@ namespace R2RDump _writer.WriteLine(); } - if (!_options.HideTransitions && rtf.Method.GcInfo?.Transitions != null && rtf.Method.GcInfo.Transitions.TryGetValue(codeOffset, out List transitionsForOffset)) + BaseGcInfo gcInfo = (_options.HideTransitions ? null : rtf.Method?.GcInfo); + if (gcInfo != null && gcInfo.Transitions.TryGetValue(codeOffset, out List transitionsForOffset)) { string[] formattedTransitions = new string[transitionsForOffset.Count]; for (int transitionIndex = 0; transitionIndex < formattedTransitions.Length; transitionIndex++) -- 2.7.4