public override void EnumerateRefsOfObject(ulong objRef, Action <ulong, int> action) { if (!_containsPointers) { return; } if (_gcDesc == null) { if (!FillGCDesc() || _gcDesc == null) { return; } } var size = GetSize(objRef); var cache = _heap.MemoryReader; if (!cache.Contains(objRef)) { cache = _heap.NativeRuntime.MemoryReader; } _gcDesc.WalkObject(objRef, (ulong)size, cache, action); }
public override IEnumerable <ClrReference> EnumerateReferencesWithFields(ulong obj, ClrType type, bool carefully, bool considerDependantHandles) { if (type is null) { throw new ArgumentNullException(nameof(type)); } if (considerDependantHandles) { ImmutableArray <(ulong Source, ulong Target)> dependent = GetHeapData().GetDependentHandles(_helpers); 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; ClrObject target = new ClrObject(dependantObj, GetObjectType(dependantObj)); yield return(ClrReference.CreateFromDependentHandle(target)); } } } } 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 || obj + size > seg.End || (!seg.IsLargeObjectSegment && size > MaxGen2ObjectSize)) { yield break; } } foreach ((ulong reference, int offset) in gcdesc.WalkObject(obj, size, _helpers.DataReader)) { ClrObject target = new ClrObject(reference, GetObjectType(reference)); yield return(ClrReference.CreateFromFieldOrArray(target, type, offset)); } } } }
public override IEnumerable <ClrObject> EnumerateObjectReferences(ulong obj, ClrType type, bool carefully, bool considerDependantHandles) { if (type is null) { throw new ArgumentNullException(nameof(type)); } if (considerDependantHandles) { ImmutableArray <(ulong Source, ulong Target)> dependent = GetHeapData().GetDependentHandles(_helpers); 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 ClrObject(dependantObj, GetObjectType(dependantObj))); } } } } if (type.IsCollectible) { ulong la = _helpers.DataReader.ReadPointer(type.LoaderAllocatorHandle); if (la != 0) { yield return(new ClrObject(la, GetObjectType(la))); } } 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 || obj + size > seg.End || (!seg.IsLargeObjectSegment && size > MaxGen2ObjectSize)) { yield break; } } int intSize = (int)size; byte[] buffer = ArrayPool <byte> .Shared.Rent(intSize); try { int read = _helpers.DataReader.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 ClrObject(reference, GetObjectType(reference))); } } } finally { ArrayPool <byte> .Shared.Return(buffer); } } } }