private ReferrerTreeNode CreateGCRootNode(RootGraphNode node) { return(new ReferrerTreeNode(this, new[] { node }, null, node.ClrRoot.Name, null, null, -1, null, false, true, GetNodeType())); ReferrerTreeNodeType GetNodeType() { switch (node.ClrRoot.Kind) { case GCRootKind.StaticVar: return(ReferrerTreeNodeType.StaticVar); // "static var StringTheory.SampleApp.Program.E" case GCRootKind.ThreadStaticVar: return(ReferrerTreeNodeType.ThreadStaticVar); case GCRootKind.Pinning: return(ReferrerTreeNodeType.Pinning); // "Pinned handle" case GCRootKind.AsyncPinning: return(ReferrerTreeNodeType.AsyncPinning); case GCRootKind.LocalVar: return(ReferrerTreeNodeType.LocalVar); case GCRootKind.Strong: return(ReferrerTreeNodeType.StrongHandle); // "Strong handle" case GCRootKind.Weak: return(ReferrerTreeNodeType.WeakHandle); case GCRootKind.Finalizer: return(ReferrerTreeNodeType.Finalizer); default: throw new ArgumentOutOfRangeException(); } } }
/// <summary> /// Traverse the canvas and evaluate it /// </summary> public override void TraverseAll() { RootGraphNode rootNode = Canvas.rootNode; rootNode.Calculate(); //Debug.Log ("RootNode is " + rootNode); }
public static ReferenceGraph Build(ClrHeap heap, HashSet <ulong> targetAddresses, CancellationToken token = default) { var graph = new ReferenceGraph(); var seen = new ObjectSet(heap); var stack = new HeapWalkStack(); var nodeByAddress = new Dictionary <ulong, ReferenceGraphNode>(); var chainCache = new Dictionary <(uint metadataToken, int fieldOffset), List <FieldReference> >(); // For each root foreach (var root in heap.EnumerateRoots(enumerateStatics: true)) { stack.Clear(); if (root.Type == null) { // This happens, though not sure why continue; } stack.Push(new ClrObjectReference(-1, root.Object, root.Type)); while (!stack.IsEmpty) { token.ThrowIfCancellationRequested(); ref var top = ref stack.Peek(); if (top.Enumerator.MoveNext()) { var o = top.Enumerator.Current; if (targetAddresses.Contains(o.Address)) { // Found a match stack.Push(o); // Ensure our stack's root is registered with the graph ref var rootLevel = ref stack[0]; if (rootLevel.GraphNode == null) { var rootNode = new RootGraphNode(root); nodeByAddress[root.Object] = rootNode; rootLevel.GraphNode = rootNode; graph.Roots.Add(rootNode); } // Build path through graph for the current stack // Skip the first node as it's always non-null for (var i = 1; i < stack.Count; i++) { ref var level = ref stack[i]; // Ensure all levels have a graph node object if (level.GraphNode == null) { if (!nodeByAddress.TryGetValue(level.Reference.Address, out var node)) { node = new ReferenceGraphNode(level.Reference.Object); nodeByAddress[level.Reference.Address] = node; if (i == stack.Count - 1) { graph.TargetSet.Add(node); } } level.GraphNode = node; ref var levelBefore = ref stack[i - 1]; var referenceChain = GetChain(levelBefore.GraphNode.Object.Type, level.Reference); level.GraphNode.Referrers.Add((node: levelBefore.GraphNode, referenceChain, fieldOffset: level.Reference.FieldOffset)); // levelBefore.GraphNode.References.Add((node: level.GraphNode, referenceChain)); } } stack.Pop(); }