From 70e26eeb4561b9a394545c69968f8a3461c080bb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 27 Dec 2019 22:50:14 +0300 Subject: [PATCH] LLVM: compress PPU cache Compress PPU modules to .gz (backward compatible with uncompressed cache) --- Utilities/JIT.cpp | 83 +++++++++++++++++++++++++++++++++++- rpcs3/Emu/Cell/PPUThread.cpp | 4 +- 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/Utilities/JIT.cpp b/Utilities/JIT.cpp index 105cc0995c..466eb2e0a9 100644 --- a/Utilities/JIT.cpp +++ b/Utilities/JIT.cpp @@ -7,6 +7,7 @@ #include "sysinfo.h" #include "VirtualMemory.h" #include +#include #ifdef __linux__ #include @@ -912,12 +913,92 @@ public: { std::string name = m_path; name.append(module->getName()); - fs::file(name, fs::rewrite).write(obj.getBufferStart(), obj.getBufferSize()); + //fs::file(name, fs::rewrite).write(obj.getBufferStart(), obj.getBufferSize()); + name.append(".gz"); + + z_stream zs{}; + uLong zsz = compressBound(obj.getBufferSize()) + 256; + auto zbuf = std::make_unique(zsz); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + deflateInit2(&zs, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY); +#pragma GCC diagnostic pop + zs.avail_in = static_cast(obj.getBufferSize()); + zs.next_in = reinterpret_cast(const_cast(obj.getBufferStart())); + zs.avail_out = static_cast(zsz); + zs.next_out = zbuf.get(); + + switch (deflate(&zs, Z_FINISH)) + { + case Z_OK: + case Z_STREAM_END: + { + deflateEnd(&zs); + break; + } + default: + { + LOG_ERROR(GENERAL, "LLVM: Failed to compress module: %s", module->getName().data()); + deflateEnd(&zs); + return; + } + } + + fs::file(name, fs::rewrite).write(zbuf.get(), zsz - zs.avail_out); LOG_NOTICE(GENERAL, "LLVM: Created module: %s", module->getName().data()); } static std::unique_ptr load(const std::string& path) { + if (fs::file cached{path + ".gz", fs::read}) + { + std::vector gz = cached.to_vector(); + std::vector out; + z_stream zs{}; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" + inflateInit2(&zs, 16 + 15); +#pragma GCC diagnostic pop + zs.avail_in = static_cast(gz.size()); + zs.next_in = gz.data(); + out.resize(gz.size() * 6); + zs.avail_out = static_cast(out.size()); + zs.next_out = out.data(); + + while (zs.avail_in) + { + switch (inflate(&zs, Z_FINISH)) + { + case Z_OK: break; + case Z_STREAM_END: break; + case Z_BUF_ERROR: + { + if (zs.avail_in) + break; + [[fallthrough]]; + } + default: + inflateEnd(&zs); + return nullptr; + } + + if (zs.avail_in) + { + auto cur_size = zs.next_out - out.data(); + out.resize(out.size() + 65536); + zs.avail_out = static_cast(out.size() - cur_size); + zs.next_out = out.data() + cur_size; + } + } + + out.resize(zs.next_out - out.data()); + inflateEnd(&zs); + + auto buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(out.size()); + std::memcpy(buf->getBufferStart(), out.data(), out.size()); + return buf; + } + if (fs::file cached{path, fs::read}) { auto buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(cached.size()); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 743d796f78..0c60db11fd 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1617,7 +1617,7 @@ extern void ppu_initialize(const ppu_module& info) } // Check object file - if (fs::is_file(cache_path + obj_name)) + if (fs::is_file(cache_path + obj_name + ".gz") || fs::is_file(cache_path + obj_name)) { if (!jit) { @@ -1657,7 +1657,7 @@ extern void ppu_initialize(const ppu_module& info) g_progr_pdone++; } - if (Emu.IsStopped() || !jit || !fs::is_file(cache_path + obj_name)) + if (Emu.IsStopped() || !jit || !fs::is_file(cache_path + obj_name + ".gz")) { return; }