private Task <Tuple <LinkedList <ClrObject>, ClrRoot> > PathToParallel(ObjectSet seen, Dictionary <ulong, LinkedListNode <ClrObject> > knownEndPoints, ClrHandle handle, ulong target, bool unique, CancellationToken cancelToken) { Debug.Assert(IsFullyCached); Task <Tuple <LinkedList <ClrObject>, ClrRoot> > t = new Task <Tuple <LinkedList <ClrObject>, ClrRoot> >(() => { LinkedList <ClrObject> path = PathTo(seen, knownEndPoints, ClrObject.Create(handle.Object, handle.Type), target, unique, true, cancelToken).FirstOrDefault(); return(new Tuple <LinkedList <ClrObject>, ClrRoot>(path, path != null ? GetHandleRoot(handle) : null)); }); t.Start(); return(t); }
public override IEnumerable <ClrObject> EnumerateObjects() { RevisionValidator.Validate(Revision, GetRuntimeRevision()); for (int i = 0; i < _segments.Length; ++i) { ClrSegment seg = _segments[i]; for (ulong obj = seg.GetFirstObject(out ClrType type); obj != 0; obj = seg.NextObject(obj, out type)) { _lastSegmentIdx = i; yield return(ClrObject.Create(obj, type)); } } }
public override IEnumerable <ClrObject> EnumerateObjects() { if (Revision != GetRuntimeRevision()) { ClrDiagnosticsException.ThrowRevisionError(Revision, GetRuntimeRevision()); } for (int i = 0; i < _segments.Length; ++i) { ClrSegment seg = _segments[i]; for (ulong obj = seg.GetFirstObject(out ClrType type); obj != 0; obj = seg.NextObject(obj, out type)) { _lastSegmentIdx = i; yield return(ClrObject.Create(obj, type)); } } }
private IEnumerable <LinkedList <ClrObject> > PathTo(ObjectSet seen, Dictionary <ulong, LinkedListNode <ClrObject> > knownEndPoints, ClrObject source, ulong target, bool unique, bool parallel, CancellationToken cancelToken) { seen.Add(source.Address); bool foundTarget; LinkedListNode <ClrObject> foundEnding; if (source.Type == null) { yield break; } LinkedList <PathEntry> path = new LinkedList <PathEntry>(); if (source.Address == target) { path.AddLast(new PathEntry() { Object = source }); yield return(GetResult(knownEndPoints, path, null, target)); yield break; } path.AddLast(new PathEntry() { Object = source, Todo = GetRefs(seen, knownEndPoints, source, target, unique, parallel, cancelToken, out foundTarget, out foundEnding) }); // Did the 'start' object point directly to 'end'? If so, early out. if (foundTarget) { path.AddLast(new PathEntry() { Object = ClrObject.Create(target, _heap.GetObjectType(target)) }); yield return(GetResult(knownEndPoints, path, null, target)); } else if (foundEnding != null) { yield return(GetResult(knownEndPoints, path, foundEnding, target)); } while (path.Count > 0) { cancelToken.ThrowIfCancellationRequested(); TraceFullPath(null, path); var last = path.Last.Value; if (last.Todo.Count == 0) { // We've exhausted all children and didn't find the target. Remove this node // and continue. path.RemoveLast(); } else { // We loop here in case we encounter an object we've already processed (or if // we can't get an object's type...inconsistent heap happens sometimes). do { cancelToken.ThrowIfCancellationRequested(); ClrObject next = last.Todo.Pop(); // Now that we are in the process of adding 'next' to the path, don't ever consider // this object in the future. if (!seen.Add(next.Address)) { continue; } // We should never reach the 'end' here, as we always check if we found the target // value when adding refs below. Debug.Assert(next.Address != target); PathEntry nextPathEntry = new PathEntry() { Object = next, Todo = GetRefs(seen, knownEndPoints, next, target, unique, parallel, cancelToken, out foundTarget, out foundEnding) }; path.AddLast(nextPathEntry); // If we found the target object while enumerating refs of the current object, we are done. if (foundTarget) { path.AddLast(new PathEntry() { Object = ClrObject.Create(target, _heap.GetObjectType(target)) }); TraceFullPath("FoundTarget", path); yield return(GetResult(knownEndPoints, path, null, target)); path.RemoveLast(); path.RemoveLast(); } else if (foundEnding != null) { TraceFullPath(path, foundEnding); yield return(GetResult(knownEndPoints, path, foundEnding, target)); path.RemoveLast(); } // Now that we've added a new entry to 'path', break out of the do/while that's looping through Todo. break; }while (last.Todo.Count > 0); } } }
private Task <Tuple <LinkedList <ClrObject>, ClrRoot> > PathToParallel(ObjectSet seen, Dictionary <ulong, LinkedListNode <ClrObject> > knownEndPoints, ClrRoot root, ulong target, bool unique, CancellationToken cancelToken) { Debug.Assert(IsFullyCached); Task <Tuple <LinkedList <ClrObject>, ClrRoot> > t = new Task <Tuple <LinkedList <ClrObject>, ClrRoot> >(() => new Tuple <LinkedList <ClrObject>, ClrRoot>(PathTo(seen, knownEndPoints, ClrObject.Create(root.Object, root.Type), target, unique, true, cancelToken).FirstOrDefault(), root)); t.Start(); return(t); }
/// <summary> /// Gets a <see cref="ClrObject"/> for the given address on this heap. /// </summary> /// <remarks> /// The returned object will have a <c>null</c> <see cref="ClrObject.Type"/> if objRef does not point to /// a valid managed object. /// </remarks> /// <param name="objRef"></param> /// <returns></returns> public ClrObject GetObject(ulong objRef) => ClrObject.Create(objRef, GetObjectType(objRef));