From e9b24eba850a90b93790f6d781322c6cd0d2f345 Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:11:37 +0200 Subject: [PATCH] SPU Analyzer: Fix programs code caching --- rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 29 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index c60e76ecd6..45b0bfe0df 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -37,12 +37,27 @@ constexpr u32 s_reg_max = spu_recompiler_base::s_reg_max; template struct span_less { - bool operator()(const std::span& this_, const std::span& that) const + static int compare(const std::span& this_, const std::span& that) noexcept { - return std::memcmp(this_.data(), that.data(), std::min(this_.size_bytes(), that.size_bytes())) < 0; + int res = std::memcmp(this_.data(), that.data(), std::min(this_.size_bytes(), that.size_bytes())); + + if (res == 0 && this_.size() != that.size()) + { + res = this_.size() < that.size() ? -1 : 1; + } + + return res; + } + + bool operator()(const std::span& this_, const std::span& that) const noexcept + { + return compare(this_, that) < 0; } }; +template +inline constexpr span_less s_span_less{}; + // Move 4 args for calling native function from a GHC calling convention function #if defined(ARCH_X64) static u8* move_args_ghc_to_native(u8* raw) @@ -1264,7 +1279,8 @@ bool spu_program::operator<(const spu_program& rhs) const noexcept // Select range for comparison std::span lhs_data(data.data() + lhs_offs, data.size() - lhs_offs); std::span rhs_data(rhs.data.data() + rhs_offs, rhs.data.size() - rhs_offs); - const auto cmp0 = std::memcmp(lhs_data.data(), rhs_data.data(), std::min(lhs_data.size_bytes(), rhs_data.size_bytes())); + + const int cmp0 = span_less::compare(lhs_data, rhs_data); if (cmp0 < 0) return true; @@ -1274,7 +1290,8 @@ bool spu_program::operator<(const spu_program& rhs) const noexcept // Compare from address 0 to the point before the entry point (TODO: undesirable) lhs_data = {data.data(), lhs_offs}; rhs_data = {rhs.data.data(), rhs_offs}; - const auto cmp1 = std::memcmp(lhs_data.data(), rhs_data.data(), std::min(lhs_data.size_bytes(), rhs_data.size_bytes())); + + const int cmp1 = span_less::compare(lhs_data, rhs_data); if (cmp1 < 0) return true; @@ -1369,7 +1386,7 @@ spu_function_t spu_runtime::rebuild_ubertrampoline(u32 id_inst) } } - std::sort(m_flat_list.begin(), m_flat_list.end(), FN(std::memcmp(x.first.data(), y.first.data(), std::min(x.first.size_bytes(), y.first.size_bytes())) < 0)); + std::sort(m_flat_list.begin(), m_flat_list.end(), FN(s_span_less(x.first, y.first))); struct work { @@ -1567,7 +1584,7 @@ spu_function_t spu_runtime::rebuild_ubertrampoline(u32 id_inst) lhs = lhs.subspan(w.level); rhs = rhs.subspan(w.level); - return std::memcmp(lhs.data(), rhs.data(), std::min(lhs.size_bytes(), rhs.size_bytes())) < 0; + return s_span_less(lhs, rhs); }); continue;