Beispiel #1
0
        private static unsafe void WriteObjectGraphToDisk(byte *stackAllocatedData, Stream stream, Dictionary <object, long> serializedObjectMap, Queue <object> objectQueue, RuntimeTypeHandleDictionary mtTokenMap, ref long lastReservedObjectEnd)
        {
            long nextObjectHeaderFilePointer = 0;

            while (objectQueue.Count != 0)
            {
                object       o        = objectQueue.Dequeue();
                ref TypeInfo typeInfo = ref mtTokenMap.GetOrAddValueRef(Type.GetTypeHandle(o));

                long mtToken;

                if (typeInfo != null)
                {
                    mtToken = typeInfo.MTToken;
                }
                else
                {
                    mtToken  = mtTokenMap.Count - 1;
                    typeInfo = GetObjectInfo(o, mtToken);
                }

                long hashCode = (RuntimeHelpers.GetHashCode(o) & 0x0fffffff) | (1 << 27) | (1 << 26);

                fixed(byte *data = &GetRawData(o))
                {
                    MethodTable *mt;

                    if (IntPtr.Size == 8)
                    {
                        *(long *)stackAllocatedData       = hashCode;
                        *(long *)(stackAllocatedData + 8) = mtToken;
                        stream.Write(new ReadOnlySpan <byte>(stackAllocatedData, 16));
                        mt = (MethodTable *)*(long *)(data - IntPtr.Size);
                    }
                    else
                    {
                        *(int *)stackAllocatedData       = (int)hashCode;
                        *(int *)(stackAllocatedData + 4) = (int)mtToken;
                        stream.Write(new ReadOnlySpan <byte>(stackAllocatedData, 8));
                        mt = (MethodTable *)*(int *)(data - IntPtr.Size);
                    }

                    uint flags            = mt->Flags;
                    bool hasComponentSize = (flags & 0x80000000) == 0x80000000;

                    long objectSize = mt->BaseSize;

                    if (hasComponentSize)
                    {
                        var numComponents = (long)*(int *)data;
                        objectSize += numComponents * mt->ComponentSize;
                    }

                    var remainingSize = objectSize - IntPtr.Size - IntPtr.Size; // because we have already written the object header and MT Token

                    if (remainingSize <= int.MaxValue)
                    {
                        stream.Write(new ReadOnlySpan <byte>(data, (int)remainingSize));
                    }
                    else
                    {
                        WriteLargeObject(stream, data, remainingSize);
                    }

                    bool containsPointersOrCollectible = (flags & 0x10000000) == 0x10000000 || (flags & 0x1000000) == 0x1000000;

                    if (containsPointersOrCollectible)
                    {
                        var gcdesc = new GCDesc(typeInfo.GCDescData, typeInfo.GCDescSize);
                        gcdesc.EnumerateObject(data, objectSize, serializedObjectMap, objectQueue, stream, nextObjectHeaderFilePointer, ref lastReservedObjectEnd);
                    }

                    nextObjectHeaderFilePointer += objectSize + Padding(objectSize, IntPtr.Size);
                    stream.Seek(nextObjectHeaderFilePointer, SeekOrigin.Begin);
                }
            }