| File: FullGraphLogStrategy.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.DependencyAnalysisFramework\ILCompiler.DependencyAnalysisFramework.csproj (ILCompiler.DependencyAnalysisFramework) |
// 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.Collections.Generic; using System.Diagnostics; namespace ILCompiler.DependencyAnalysisFramework { public struct FullGraphLogStrategy<DependencyContextType> : IDependencyAnalysisMarkStrategy<DependencyContextType> { private sealed class MarkData : IEquatable<MarkData> { public MarkData(string reason, DependencyNodeCore<DependencyContextType> reason1, DependencyNodeCore<DependencyContextType> reason2) { Reason = reason; Reason1 = reason1; Reason2 = reason2; } public string Reason { get; } public DependencyNodeCore<DependencyContextType> Reason1 { get; } public DependencyNodeCore<DependencyContextType> Reason2 { get; } private static int CombineHashCodes(int h1, int h2) { return (((h1 << 5) + h1) ^ h2); } private static int CombineHashCodes(int h1, int h2, int h3) { return CombineHashCodes(CombineHashCodes(h1, h2), h3); } public override int GetHashCode() { int reasonHashCode = Reason != null ? Reason.GetHashCode() : 0; int reason1HashCode = Reason1 != null ? Reason1.GetHashCode() : 0; int reason2HashCode = Reason2 != null ? Reason2.GetHashCode() : 0; return CombineHashCodes(reasonHashCode, reason1HashCode, reason2HashCode); } public override bool Equals(object obj) { MarkData other = obj as MarkData; if (other == null) return false; return Equals(other); } public bool Equals(MarkData other) { if (Reason1 != other.Reason1) return false; if (Reason2 != other.Reason2) return false; if (Reason == other.Reason) return true; if (Reason != null) { return Reason.Equals(other.Reason); } return false; } } private sealed class MarkDataEqualityComparer : IEqualityComparer<MarkData> { public bool Equals(MarkData x, MarkData y) { return x.Equals(y); } public int GetHashCode(MarkData obj) { return obj.GetHashCode(); } public static IEqualityComparer<MarkData> Default = new MarkDataEqualityComparer(); } private HashSet<string> _reasonStringOnlyNodes; bool IDependencyAnalysisMarkStrategy<DependencyContextType>.MarkNode( DependencyNodeCore<DependencyContextType> node, DependencyNodeCore<DependencyContextType> reasonNode, DependencyNodeCore<DependencyContextType> reasonNode2, string reason) { bool newlyMarked = !node.Marked; HashSet<MarkData> associatedNodes; if (newlyMarked) { associatedNodes = new HashSet<MarkData>(MarkDataEqualityComparer.Default); node.SetMark(associatedNodes); } else { associatedNodes = (HashSet<MarkData>)node.GetMark(); } if ((reasonNode == null) && (reasonNode2 == null)) { Debug.Assert(reason != null); _reasonStringOnlyNodes ??= new HashSet<string>(); _reasonStringOnlyNodes.Add(reason); } associatedNodes.Add(new MarkData(reason, reasonNode, reasonNode2)); return newlyMarked; } void IDependencyAnalysisMarkStrategy<DependencyContextType>.VisitLogNodes(IEnumerable<DependencyNodeCore<DependencyContextType>> nodeList, IDependencyAnalyzerLogNodeVisitor<DependencyContextType> logNodeVisitor) { var combinedNodesReported = new HashSet<Tuple<DependencyNodeCore<DependencyContextType>, DependencyNodeCore<DependencyContextType>>>(); if (_reasonStringOnlyNodes != null) { foreach (string reasonOnly in _reasonStringOnlyNodes) { logNodeVisitor.VisitRootNode(reasonOnly); } } foreach (DependencyNodeCore<DependencyContextType> node in nodeList) { if (node.Marked) { HashSet<MarkData> nodeReasons = (HashSet<MarkData>)node.GetMark(); foreach (MarkData markData in nodeReasons) { if (markData.Reason2 != null) { var combinedNode = new Tuple<DependencyNodeCore<DependencyContextType>, DependencyNodeCore<DependencyContextType>>(markData.Reason1, markData.Reason2); if (combinedNodesReported.Add(combinedNode)) { logNodeVisitor.VisitCombinedNode(combinedNode); } } } } } } void IDependencyAnalysisMarkStrategy<DependencyContextType>.VisitLogEdges(IEnumerable<DependencyNodeCore<DependencyContextType>> nodeList, IDependencyAnalyzerLogEdgeVisitor<DependencyContextType> logEdgeVisitor) { foreach (DependencyNodeCore<DependencyContextType> node in nodeList) { if (node.Marked) { HashSet<MarkData> nodeReasons = (HashSet<MarkData>)node.GetMark(); foreach (MarkData markData in nodeReasons) { if (markData.Reason2 != null) { Debug.Assert(markData.Reason1 != null); logEdgeVisitor.VisitEdge(markData.Reason1, markData.Reason2, node, markData.Reason); } else if (markData.Reason1 != null) { logEdgeVisitor.VisitEdge(markData.Reason1, node, markData.Reason); } else { Debug.Assert(markData.Reason != null); logEdgeVisitor.VisitEdge(markData.Reason, node); } } } } } void IDependencyAnalysisMarkStrategy<DependencyContextType>.AttachContext(DependencyContextType context) { // This logger does not need to use the context } } }