internal IEnumerable EnumerateObjectReferences()

in src/Microsoft.Diagnostics.Runtime/ClrHeap.cs [888:950]


        internal IEnumerable<ClrObject> EnumerateObjectReferences(ulong obj, ClrType type, bool carefully, bool considerDependantHandles)
        {
            if (type is null)
                throw new ArgumentNullException(nameof(type));

            if (considerDependantHandles)
            {
                (ulong Source, ulong Target)[] dependent = GetDependentHandles();

                if (dependent.Length > 0)
                {
                    int index = dependent.Search(obj, (x, y) => x.Source.CompareTo(y));
                    if (index != -1)
                    {
                        while (index >= 1 && dependent[index - 1].Source == obj)
                            index--;

                        while (index < dependent.Length && dependent[index].Source == obj)
                        {
                            ulong dependantObj = dependent[index++].Target;
                            yield return new(dependantObj, GetObjectType(dependantObj) ?? ErrorType);
                        }
                    }
                }
            }

            if (type.IsCollectible)
            {
                ulong la = _memoryReader.ReadPointer(type.LoaderAllocatorHandle);
                if (la != 0)
                    yield return new(la, GetObjectType(la) ?? ErrorType);
            }

            if (type.ContainsPointers)
            {
                GCDesc gcdesc = type.GCDesc;
                if (!gcdesc.IsEmpty)
                {
                    ulong size = GetObjectSize(obj, type);
                    if (carefully)
                    {
                        ClrSegment? seg = GetSegmentByAddress(obj);
                        if (seg is null)
                            yield break;

                        bool large = seg.Kind is GCSegmentKind.Large or GCSegmentKind.Pinned;
                        if (obj + size > seg.End || (!large && size > MaxGen2ObjectSize))
                            yield break;
                    }

                    int intSize = (int)size;
                    byte[] buffer = ArrayPool<byte>.Shared.Rent(intSize);
                    int read = _memoryReader.Read(obj, new Span<byte>(buffer, 0, intSize));
                    if (read > IntPtr.Size)
                    {
                        foreach ((ulong reference, int offset) in gcdesc.WalkObject(buffer, read))
                            yield return new(reference, GetObjectType(reference) ?? ErrorType);
                    }

                    ArrayPool<byte>.Shared.Return(buffer);
                }
            }
        }