| File: Contracts\ExecutionManager\ExecutionManagerCore.InterpreterJitManager.cs | Web Access |
| Project: src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.Contracts\Microsoft.Diagnostics.DataContractReader.Contracts.csproj (Microsoft.Diagnostics.DataContractReader.Contracts) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Microsoft.Diagnostics.DataContractReader.ExecutionManagerHelpers; namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal partial class ExecutionManagerCore<T> : IExecutionManager { private sealed class InterpreterJitManager : JitManager { private readonly INibbleMap _nibbleMap; public InterpreterJitManager(Target target, INibbleMap nibbleMap) : base(target) { _nibbleMap = nibbleMap; } public override bool GetMethodInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, [NotNullWhen(true)] out CodeBlock? info) { info = null; if (rangeSection.IsRangeList) return false; if (rangeSection.Data is null) throw new ArgumentException(nameof(rangeSection)); TargetPointer codeStart = FindMethodCode(rangeSection, jittedCodeAddress); if (codeStart == TargetPointer.Null) return false; Debug.Assert(codeStart.Value <= jittedCodeAddress.Value); TargetNUInt relativeOffset = new TargetNUInt(jittedCodeAddress.Value - codeStart.Value); if (!GetInterpreterRealCodeHeader(codeStart, out Data.InterpreterRealCodeHeader? realCodeHeader)) return false; info = new CodeBlock(codeStart.Value, realCodeHeader.MethodDesc, relativeOffset, rangeSection.Data.JitManager); return true; } public override void GetMethodRegionInfo( RangeSection rangeSection, TargetCodePointer jittedCodeAddress, out uint hotSize, out TargetPointer coldStart, out uint coldSize) { coldStart = TargetPointer.Null; coldSize = 0; IGCInfo gcInfo = Target.Contracts.GCInfo; GetGCInfo(rangeSection, jittedCodeAddress, out TargetPointer pGcInfo, out uint gcVersion); IGCInfoHandle gcInfoHandle = gcInfo.DecodeInterpreterGCInfo(pGcInfo, gcVersion); hotSize = gcInfo.GetCodeLength(gcInfoHandle); Debug.Assert(hotSize > 0); } public override TargetPointer GetUnwindInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress) { // Interpreter code has no native unwind info return TargetPointer.Null; } public override CodeKind GetCodeKind(RangeSection rangeSection, TargetCodePointer codeAddress) { return CodeKind.Interpreter; } public override TargetPointer GetDebugInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, out bool hasFlagByte) { hasFlagByte = false; if (rangeSection.IsRangeList || rangeSection.Data is null) return TargetPointer.Null; TargetPointer codeStart = FindMethodCode(rangeSection, jittedCodeAddress); if (codeStart == TargetPointer.Null) return TargetPointer.Null; if (!GetInterpreterRealCodeHeader(codeStart, out Data.InterpreterRealCodeHeader? realCodeHeader)) return TargetPointer.Null; return realCodeHeader.DebugInfo; } public override void GetGCInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, out TargetPointer gcInfo, out uint gcVersion) { gcInfo = TargetPointer.Null; gcVersion = 0; if (rangeSection.IsRangeList || rangeSection.Data is null) return; TargetPointer codeStart = FindMethodCode(rangeSection, jittedCodeAddress); if (codeStart == TargetPointer.Null) return; if (!GetInterpreterRealCodeHeader(codeStart, out Data.InterpreterRealCodeHeader? realCodeHeader)) return; gcVersion = Target.ReadGlobal<uint>(Constants.Globals.GCInfoVersion); gcInfo = realCodeHeader.GCInfo; } public override void GetExceptionClauses(RangeSection rangeSection, CodeBlockHandle codeInfoHandle, out TargetPointer startAddr, out TargetPointer endAddr) { startAddr = TargetPointer.Null; endAddr = TargetPointer.Null; if (rangeSection.Data is null) throw new ArgumentException(nameof(rangeSection)); TargetPointer codeStart = FindMethodCode(rangeSection, new TargetCodePointer(codeInfoHandle.Address)); if (!GetInterpreterRealCodeHeader(codeStart, out Data.InterpreterRealCodeHeader? realCodeHeader)) return; if (realCodeHeader.JitEHInfo is null) return; TargetNUInt numEHInfos = Target.ReadNUInt(realCodeHeader.JitEHInfo.Address - (ulong)Target.PointerSize); startAddr = realCodeHeader.JitEHInfo.Clauses; endAddr = startAddr + numEHInfos.Value * Target.GetTypeInfo(DataType.EEExceptionClause).Size!.Value; } private TargetPointer FindMethodCode(RangeSection rangeSection, TargetCodePointer jittedCodeAddress) { Debug.Assert(rangeSection.Data is not null); if (!rangeSection.IsCodeHeap) throw new InvalidOperationException("RangeSection is not a code heap"); TargetPointer heapListAddress = rangeSection.Data.HeapList; Data.CodeHeapListNode heapListNode = Target.ProcessedData.GetOrAdd<Data.CodeHeapListNode>(heapListAddress); return _nibbleMap.FindMethodCode(heapListNode, jittedCodeAddress); } private bool GetInterpreterRealCodeHeader(TargetPointer codeStart, [NotNullWhen(true)] out Data.InterpreterRealCodeHeader? realCodeHeader) { realCodeHeader = null; if (codeStart == TargetPointer.Null) return false; // Same layout as EEJitManager: CodeHeader pointer lives at codeStart - pointerSize int codeHeaderOffset = Target.PointerSize; TargetPointer codeHeaderIndirect = new TargetPointer(codeStart - (ulong)codeHeaderOffset); if (RangeSection.IsStubCodeBlock(Target, codeHeaderIndirect)) return false; TargetPointer codeHeaderAddress = Target.ReadPointer(codeHeaderIndirect); realCodeHeader = Target.ProcessedData.GetOrAdd<Data.InterpreterRealCodeHeader>(codeHeaderAddress); return true; } } }