Example #1
0
        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);
        }
Example #2
0
        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));
                }
            }
        }
Example #3
0
        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));
                }
            }
        }
Example #4
0
        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);
                }
            }
        }
Example #5
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);
        }
Example #6
0
 /// <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));