private void ParseObjectHeader(StartIndices startIndices, MemorySection[] heap, ulong originalHeapAddress, out ulong typeInfoAddress, out int indexOfObject, out bool wasAlreadyCrawled, List <PackedManagedObject> outManagedObjects)
        {
            BytesAndOffset bo = heap.Find(originalHeapAddress, _virtualMachineInformation);

            UInt64         pointer1 = bo.ReadPointer();
            BytesAndOffset pointer2 = bo.NextPointer();

            if (HasMarkBit(pointer1) == 0)
            {
                TypeDescription typeDescription = GetTypeDescription(heap, pointer1);

                wasAlreadyCrawled = false;
                indexOfObject     = outManagedObjects.Count + startIndices.OfFirstManagedObject;
                typeInfoAddress   = typeDescription.typeInfoAddress;

                int size = SizeOfObjectInBytes(typeDescription, bo, heap, originalHeapAddress);

                outManagedObjects.Add(new PackedManagedObject()
                {
                    address = originalHeapAddress, size = size, typeIndex = typeDescription.typeIndex
                });

                //okay, we gathered all information, now lets set the mark bit, and store the index for this object in the 2nd pointer of the header, which is rarely used.
                bo.WritePointer(pointer1 | 1);
                pointer2.WritePointer((ulong)indexOfObject);
                return;
            }

            //give typeinfo address back without the markbit
            typeInfoAddress   = ClearMarkBit(pointer1);
            wasAlreadyCrawled = true;
            //read the index for this object that we stored in the 2ndpointer field of the header
            indexOfObject = (int)pointer2.ReadPointer();
        }
        private void CrawlPointerNonRecursive(PackedMemorySnapshot packedMemorySnapshot, StartIndices startIndices, ulong pointer, int indexOfFrom, List <Connection> out_connections, List <PackedManagedObject> out_managedObjects, Stack <ThingToProfile> out_thingsToProfile)
        {
            BytesAndOffset bo = packedMemorySnapshot.managedHeapSections.Find(pointer, _virtualMachineInformation);

            if (!bo.IsValid)
            {
                return;
            }

            UInt64 typeInfoAddress;
            int    indexOfObject;
            bool   wasAlreadyCrawled;

            try
            {
                ParseObjectHeader(startIndices, packedMemorySnapshot.managedHeapSections, pointer, out typeInfoAddress, out indexOfObject, out wasAlreadyCrawled, out_managedObjects);
            }
            catch (Exception e)
            {
                UnityEngine.Debug.LogWarningFormat("Exception parsing object header. Skipping. {0}", e);
                return;
            }

            out_connections.Add(new Connection()
            {
                from = indexOfFrom, to = indexOfObject
            });

            if (wasAlreadyCrawled)
            {
                return;
            }

            TypeDescription typeDescription = _typeInfoToTypeDescription[typeInfoAddress];

            if (!typeDescription.isArray)
            {
                out_thingsToProfile.Push(new ThingToProfile(typeDescription, bo.Add(_virtualMachineInformation.objectHeaderSize), false, indexOfObject));
                return;
            }

            int             arrayLength = ArrayTools.ReadArrayLength(packedMemorySnapshot.managedHeapSections, pointer, typeDescription, _virtualMachineInformation);
            TypeDescription elementType = packedMemorySnapshot.typeDescriptions[typeDescription.baseOrElementTypeIndex];
            BytesAndOffset  cursor      = bo.Add(_virtualMachineInformation.arrayHeaderSize);

            for (int i = 0; i != arrayLength; i++)
            {
                if (elementType.isValueType)
                {
                    out_thingsToProfile.Push(new ThingToProfile(elementType, cursor, false, indexOfObject));
                    cursor = cursor.Add(elementType.size);
                }
                else
                {
                    out_thingsToProfile.Push(new ThingToProfile(cursor.ReadPointer(), indexOfObject));
                    cursor = cursor.NextPointer();
                }
            }
        }
        private TypeDescription RestoreObjectHeader(MemorySection[] heaps, ulong address, int managedObjectIndex)
        {
            BytesAndOffset bo              = heaps.Find(address, _virtualMachineInformation);
            UInt64         mask            = this._virtualMachineInformation.pointerSize == 8 ? System.UInt64.MaxValue - 1 : System.UInt32.MaxValue - 1;
            UInt64         pointer         = bo.ReadPointer();
            UInt64         typeInfoAddress = pointer & mask;

            bo.WritePointer(typeInfoAddress);

            UInt64 restoreValue = 0;

            _pointer2Backups.TryGetValue(managedObjectIndex, out restoreValue);
            bo.NextPointer().WritePointer(restoreValue);

            return(GetTypeDescription(heaps, typeInfoAddress));
        }