private static object DeserializeInner(RuntimeTypeHandle[] runtimeTypeHandles, byte *buffer, long length) { byte *objectId = buffer + IntPtr.Size; while (objectId < buffer + length) { IntPtr typeHandle = IntPtr.Size == 8 ? runtimeTypeHandles[(int)*(long *)objectId].Value : runtimeTypeHandles[*(int *)objectId].Value; bool isArray = ((long)typeHandle & 0x2) == 0x2; var mt = (MethodTable *)typeHandle; if (isArray) { mt = IntPtr.Size == 8 ? (MethodTable *)*(long *)(typeHandle + 6) : (MethodTable *)*(int *)(typeHandle + 6); // TODO: Is this correct for 32-bit? } long objectSize = mt->BaseSize; var flags = mt->Flags; bool hasComponentSize = (flags & 0x80000000) == 0x80000000; if (hasComponentSize) { var numComponents = (long)*(int *)(objectId + IntPtr.Size); objectSize += numComponents * mt->ComponentSize; } bool containsPointerOrCollectible = (flags & 0x10000000) == 0x10000000 || (flags & 0x1000000) == 0x1000000; if (containsPointerOrCollectible) { var entries = *(int *)((byte *)mt - IntPtr.Size); if (entries < 0) { entries -= entries; } var slots = 1 + entries * 2; var gcdesc = new GCDesc(buffer, (byte *)mt - (slots * IntPtr.Size), slots * IntPtr.Size); if (IntPtr.Size == 8) { gcdesc.FixupObject64(objectId, objectSize); } else { gcdesc.FixupObject32(objectId, objectSize); } } if (IntPtr.Size == 8) { *(long *)objectId = (long)mt; } else { *(int *)objectId = (int)mt; } objectId += objectSize + Padding(objectSize, IntPtr.Size); } var tmp = buffer + IntPtr.Size; return(Unsafe.Read <object>(&tmp)); }