private static unsafe void Save(string fileName) { int translatedFuncsCount; int headerSize = Unsafe.SizeOf <Header>(); Header header = new Header() { Magic = _headerMagic, CacheFileVersion = InternalVersion, Endianness = GetEndianness(), FeatureInfo = GetFeatureInfo(), OSPlatform = GetOSPlatform(), InfosLength = (int)_infosStream.Length, CodesLength = _codesList.Length(), RelocsLength = (int)_relocsStream.Length, UnwindInfosLength = (int)_unwindInfosStream.Length, PtcJumpTableLength = PtcJumpTable.GetSerializeSize(PtcJumpTable) }; long size = (long)headerSize + header.InfosLength + header.CodesLength + header.RelocsLength + header.UnwindInfosLength + header.PtcJumpTableLength; Span <byte> sizeBytes = new byte[sizeof(long)]; BinaryPrimitives.WriteInt64LittleEndian(sizeBytes, size); Hash128 sizeHash = XXHash128.ComputeHash(sizeBytes); Span <byte> sizeHashBytes = new byte[Unsafe.SizeOf <Hash128>()]; MemoryMarshal.Write <Hash128>(sizeHashBytes, ref sizeHash); IntPtr intPtr = IntPtr.Zero; try { intPtr = Marshal.AllocHGlobal(new IntPtr(size)); using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite)) { stream.Seek((long)headerSize, SeekOrigin.Begin); ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, header.InfosLength); _infosStream.WriteTo(stream); ReadOnlySpan <byte> codesBytes = (int)header.CodesLength > 0 ? new(stream.PositionPointer, (int)header.CodesLength) : ReadOnlySpan <byte> .Empty; _codesList.WriteTo(stream); ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, header.RelocsLength); _relocsStream.WriteTo(stream); ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, header.UnwindInfosLength); _unwindInfosStream.WriteTo(stream); ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, header.PtcJumpTableLength); PtcJumpTable.Serialize(stream, PtcJumpTable); header.InfosHash = XXHash128.ComputeHash(infosBytes); header.CodesHash = XXHash128.ComputeHash(codesBytes); header.RelocsHash = XXHash128.ComputeHash(relocsBytes); header.UnwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes); header.PtcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes); Debug.Assert(stream.Position == stream.Length); stream.Seek(0L, SeekOrigin.Begin); SerializeStructure(stream, header); translatedFuncsCount = GetEntriesCount(); ResetCarriersIfNeeded(); PtcJumpTable.ClearIfNeeded(); using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate)) using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true)) { try { compressedStream.Write(sizeHashBytes); compressedStream.Write(sizeBytes); stream.Seek(0L, SeekOrigin.Begin); stream.CopyTo(deflateStream); } catch { compressedStream.Position = 0L; } if (compressedStream.Position < compressedStream.Length) { compressedStream.SetLength(compressedStream.Position); } } } } finally { if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } long fileSize = new FileInfo(fileName).Length; if (fileSize != 0L) { Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); } }
/// <summary> /// Compute a guest hash from shader entries. /// </summary> /// <param name="cachedShaderEntries">The guest shader entries to use</param> /// <param name="tfd">The optional transform feedback descriptors</param> /// <returns>A guest hash from shader entries</returns> public static Hash128 ComputeGuestHashFromCache(ReadOnlySpan <GuestShaderCacheEntry> cachedShaderEntries, TransformFeedbackDescriptor[] tfd = null) { return(XXHash128.ComputeHash(ComputeGuestProgramCode(cachedShaderEntries, tfd, true))); }
public void SetHeaderHash() { Span <OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf <OuterHeader>() - Unsafe.SizeOf <Hash128>())); }
private static unsafe bool Load(string fileName, bool isBackup) { using (FileStream compressedStream = new(fileName, FileMode.Open)) using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true)) { Hash128 currentSizeHash = DeserializeStructure <Hash128>(compressedStream); Span <byte> sizeBytes = new byte[sizeof(long)]; compressedStream.Read(sizeBytes); Hash128 expectedSizeHash = XXHash128.ComputeHash(sizeBytes); if (currentSizeHash != expectedSizeHash) { InvalidateCompressedStream(compressedStream); return(false); } long size = BinaryPrimitives.ReadInt64LittleEndian(sizeBytes); IntPtr intPtr = IntPtr.Zero; try { intPtr = Marshal.AllocHGlobal(new IntPtr(size)); using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite)) { try { deflateStream.CopyTo(stream); } catch { InvalidateCompressedStream(compressedStream); return(false); } Debug.Assert(stream.Position == stream.Length); stream.Seek(0L, SeekOrigin.Begin); Header header = DeserializeStructure <Header>(stream); if (header.Magic != _headerMagic) { InvalidateCompressedStream(compressedStream); return(false); } if (header.CacheFileVersion != InternalVersion) { InvalidateCompressedStream(compressedStream); return(false); } if (header.Endianness != GetEndianness()) { InvalidateCompressedStream(compressedStream); return(false); } if (header.FeatureInfo != GetFeatureInfo()) { InvalidateCompressedStream(compressedStream); return(false); } if (header.OSPlatform != GetOSPlatform()) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, header.InfosLength); stream.Seek(header.InfosLength, SeekOrigin.Current); Hash128 infosHash = XXHash128.ComputeHash(infosBytes); if (header.InfosHash != infosHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> codesBytes = (int)header.CodesLength > 0 ? new(stream.PositionPointer, (int)header.CodesLength) : ReadOnlySpan <byte> .Empty; stream.Seek(header.CodesLength, SeekOrigin.Current); Hash128 codesHash = XXHash128.ComputeHash(codesBytes); if (header.CodesHash != codesHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, header.RelocsLength); stream.Seek(header.RelocsLength, SeekOrigin.Current); Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes); if (header.RelocsHash != relocsHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, header.UnwindInfosLength); stream.Seek(header.UnwindInfosLength, SeekOrigin.Current); Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes); if (header.UnwindInfosHash != unwindInfosHash) { InvalidateCompressedStream(compressedStream); return(false); } ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, header.PtcJumpTableLength); stream.Seek(header.PtcJumpTableLength, SeekOrigin.Current); Hash128 ptcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes); if (header.PtcJumpTableHash != ptcJumpTableHash) { InvalidateCompressedStream(compressedStream); return(false); } Debug.Assert(stream.Position == stream.Length); stream.Seek((long)Unsafe.SizeOf <Header>(), SeekOrigin.Begin); _infosStream.Write(infosBytes); stream.Seek(header.InfosLength, SeekOrigin.Current); _codesList.ReadFrom(stream); _relocsStream.Write(relocsBytes); stream.Seek(header.RelocsLength, SeekOrigin.Current); _unwindInfosStream.Write(unwindInfosBytes); stream.Seek(header.UnwindInfosLength, SeekOrigin.Current); PtcJumpTable = PtcJumpTable.Deserialize(stream); Debug.Assert(stream.Position == stream.Length); } } finally { if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } } long fileSize = new FileInfo(fileName).Length; Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()})."); return(true); }
/// <summary> /// Computes the hash of some data using the current cache hashing algorithm. /// </summary> /// <param name="data">Some data to generate a hash for.</param> /// <returns>The hash of some data using the current hashing algorithm of the cache</returns> public Hash128 ComputeHash(ReadOnlySpan <byte> data) { return(XXHash128.ComputeHash(data)); }
public bool IsHeaderValid() { Span <InnerHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1); return(XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf <InnerHeader>() - Unsafe.SizeOf <Hash128>())) == HeaderHash); }
private static unsafe void Save(string fileName) { int translatedFuncsCount; int hashSize = Unsafe.SizeOf <Hash128>(); int size = hashSize + Header.Size + GetMemoryStreamsLength() + PtcJumpTable.GetSerializeSize(PtcJumpTable); Span <byte> sizeBytes = new byte[sizeof(int)]; BinaryPrimitives.WriteInt32LittleEndian(sizeBytes, size); Hash128 sizeHash = XXHash128.ComputeHash(sizeBytes); Span <byte> sizeHashBytes = new byte[hashSize]; MemoryMarshal.Write <Hash128>(sizeHashBytes, ref sizeHash); IntPtr intPtr = IntPtr.Zero; try { intPtr = Marshal.AllocHGlobal(size); using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite)) { stream.Seek((long)hashSize, SeekOrigin.Begin); WriteHeader(stream); _infosStream.WriteTo(stream); _codesStream.WriteTo(stream); _relocsStream.WriteTo(stream); _unwindInfosStream.WriteTo(stream); PtcJumpTable.Serialize(stream, PtcJumpTable); stream.Seek((long)hashSize, SeekOrigin.Begin); ReadOnlySpan <byte> streamBytes = new(stream.PositionPointer, (int)(stream.Length - stream.Position)); Hash128 hash = XXHash128.ComputeHash(streamBytes); stream.Seek(0L, SeekOrigin.Begin); SerializeStructure(stream, hash); translatedFuncsCount = GetInfosEntriesCount(); ResetMemoryStreamsIfNeeded(); PtcJumpTable.ClearIfNeeded(); using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate)) using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true)) { try { compressedStream.Write(sizeHashBytes); compressedStream.Write(sizeBytes); stream.Seek(0L, SeekOrigin.Begin); stream.CopyTo(deflateStream); } catch { compressedStream.Position = 0L; } if (compressedStream.Position < compressedStream.Length) { compressedStream.SetLength(compressedStream.Position); } } } } finally { if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } long fileSize = new FileInfo(fileName).Length; if (fileSize != 0L) { Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); } }
private static void Save(string fileName) { int profiledFuncsCount; OuterHeader outerHeader = new OuterHeader(); outerHeader.Magic = _outerHeaderMagic; outerHeader.InfoFileVersion = InternalVersion; outerHeader.Endianness = Ptc.GetEndianness(); outerHeader.SetHeaderHash(); using (MemoryStream stream = new MemoryStream()) { Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); stream.Seek((long)Unsafe.SizeOf <Hash128>(), SeekOrigin.Begin); lock (_lock) { Serialize(stream, ProfiledFuncs); profiledFuncsCount = ProfiledFuncs.Count; } Debug.Assert(stream.Position == stream.Length); stream.Seek((long)Unsafe.SizeOf <Hash128>(), SeekOrigin.Begin); Hash128 hash = XXHash128.ComputeHash(GetReadOnlySpan(stream)); stream.Seek(0L, SeekOrigin.Begin); SerializeStructure(stream, hash); if (hash == _lastHash) { return; } using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate)) using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true)) { try { SerializeStructure(compressedStream, outerHeader); stream.WriteTo(deflateStream); _lastHash = hash; } catch { compressedStream.Position = 0L; _lastHash = default; } if (compressedStream.Position < compressedStream.Length) { compressedStream.SetLength(compressedStream.Position); } } } long fileSize = new FileInfo(fileName).Length; if (fileSize != 0L) { Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); } }
private static bool Load(string fileName, bool isBackup) { using (FileStream compressedStream = new(fileName, FileMode.Open)) using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true)) { OuterHeader outerHeader = DeserializeStructure <OuterHeader>(compressedStream); if (!outerHeader.IsHeaderValid()) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.Magic != _outerHeaderMagic) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.InfoFileVersion != InternalVersion) { InvalidateCompressedStream(compressedStream); return(false); } if (outerHeader.Endianness != Ptc.GetEndianness()) { InvalidateCompressedStream(compressedStream); return(false); } using (MemoryStream stream = new MemoryStream()) { Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L); try { deflateStream.CopyTo(stream); } catch { InvalidateCompressedStream(compressedStream); return(false); } Debug.Assert(stream.Position == stream.Length); stream.Seek(0L, SeekOrigin.Begin); Hash128 expectedHash = DeserializeStructure <Hash128>(stream); Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream)); if (actualHash != expectedHash) { InvalidateCompressedStream(compressedStream); return(false); } ProfiledFuncs = Deserialize(stream); Debug.Assert(stream.Position == stream.Length); _lastHash = actualHash; } } long fileSize = new FileInfo(fileName).Length; Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count})."); return(true); }
internal static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize) { return(XXHash128.ComputeHash(memory.GetSpan(address, checked ((int)(guestSize))))); }
private static unsafe void Save(string fileName) { int translatedFuncsCount; InnerHeader innerHeader = new InnerHeader(); innerHeader.Magic = _innerHeaderMagic; innerHeader.InfosLength = (int)_infosStream.Length; innerHeader.CodesLength = _codesList.Length(); innerHeader.RelocsLength = (int)_relocsStream.Length; innerHeader.UnwindInfosLength = (int)_unwindInfosStream.Length; innerHeader.PtcJumpTableLength = PtcJumpTable.GetSerializeSize(PtcJumpTable); OuterHeader outerHeader = new OuterHeader(); outerHeader.Magic = _outerHeaderMagic; outerHeader.CacheFileVersion = InternalVersion; outerHeader.Endianness = GetEndianness(); outerHeader.FeatureInfo = GetFeatureInfo(); outerHeader.MemoryManagerMode = GetMemoryManagerMode(); outerHeader.OSPlatform = GetOSPlatform(); outerHeader.UncompressedStreamSize = (long)Unsafe.SizeOf <InnerHeader>() + innerHeader.InfosLength + innerHeader.CodesLength + innerHeader.RelocsLength + innerHeader.UnwindInfosLength + innerHeader.PtcJumpTableLength; outerHeader.SetHeaderHash(); IntPtr intPtr = IntPtr.Zero; try { intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize)); using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite)) { stream.Seek((long)Unsafe.SizeOf <InnerHeader>(), SeekOrigin.Begin); ReadOnlySpan <byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength); _infosStream.WriteTo(stream); ReadOnlySpan <byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan <byte> .Empty; _codesList.WriteTo(stream); ReadOnlySpan <byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength); _relocsStream.WriteTo(stream); ReadOnlySpan <byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength); _unwindInfosStream.WriteTo(stream); ReadOnlySpan <byte> ptcJumpTableBytes = new(stream.PositionPointer, innerHeader.PtcJumpTableLength); PtcJumpTable.Serialize(stream, PtcJumpTable); Debug.Assert(stream.Position == stream.Length); innerHeader.InfosHash = XXHash128.ComputeHash(infosBytes); innerHeader.CodesHash = XXHash128.ComputeHash(codesBytes); innerHeader.RelocsHash = XXHash128.ComputeHash(relocsBytes); innerHeader.UnwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes); innerHeader.PtcJumpTableHash = XXHash128.ComputeHash(ptcJumpTableBytes); innerHeader.SetHeaderHash(); stream.Seek(0L, SeekOrigin.Begin); SerializeStructure(stream, innerHeader); translatedFuncsCount = GetEntriesCount(); ResetCarriersIfNeeded(); PtcJumpTable.ClearIfNeeded(); using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate)) using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true)) { try { SerializeStructure(compressedStream, outerHeader); stream.Seek(0L, SeekOrigin.Begin); stream.CopyTo(deflateStream); } catch { compressedStream.Position = 0L; } if (compressedStream.Position < compressedStream.Length) { compressedStream.SetLength(compressedStream.Position); } } } } finally { if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } long fileSize = new FileInfo(fileName).Length; if (fileSize != 0L) { Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); } }