diff --git a/rpcs3/Emu/Cell/SPUAnalyser.cpp b/rpcs3/Emu/Cell/SPUAnalyser.cpp index 7a009d1164..2ff0389809 100644 --- a/rpcs3/Emu/Cell/SPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/SPUAnalyser.cpp @@ -12,9 +12,24 @@ std::shared_ptr SPUDatabase::find(const be_t* data, u64 key const auto& func = found.first->second; // Compare binary data explicitly (TODO: optimize) - if (LIKELY(func->size <= max_size) && std::memcmp(func->data.data(), data, func->size) == 0) + //if (LIKELY(func->size <= max_size) && std::memcmp(func->data.data(), data, func->size) == 0) { - return func; + const auto dwords = (u32*)(func->data.data()); + const auto cast_data = (u32*)(data); + const auto limit = std::min(max_size, func->size) >> 2; + + bool failed = false; + for (u32 dword = 0; dword < limit; dword++) + { + if (dwords[dword] != cast_data[dword]) + { + failed = true; + break; + } + } + + if (!failed) + return func; } } @@ -43,23 +58,27 @@ std::shared_ptr SPUDatabase::analyse(const be_t* ls, u32 en // Key for multimap const u64 key = entry | u64{ ls[entry / 4] } << 32; + const be_t* base = ls + entry / 4; + const u32 block_sz = max_limit - entry; { - reader_lock lock(m_mutex); + //reader_lock lock(m_mutex); // Try to find existing function in the database - if (auto func = find(ls + entry / 4, key, max_limit - entry)) + if (auto func = find(base, key, block_sz)) { return func; } } - writer_lock lock(m_mutex); - - // Double-check - if (auto func = find(ls + entry / 4, key, max_limit - entry)) { - return func; + writer_lock lock(m_mutex); + + // Double-check + if (auto func = find(base, key, block_sz)) + { + return func; + } } // Initialize block entries with the function entry point @@ -81,11 +100,15 @@ std::shared_ptr SPUDatabase::analyse(const be_t* ls, u32 en const auto type = s_spu_itype.decode(op.opcode); - // Find existing function - if (pos != entry && find(ls + pos / 4, pos | u64{ op.opcode } << 32, limit - pos)) { - limit = pos; - break; + //reader_lock lock(m_mutex); + + // Find existing function + if (pos != entry && find(ls + pos / 4, pos | u64{ op.opcode } << 32, limit - pos)) + { + limit = pos; + break; + } } // Additional analysis at the beginning of the block @@ -311,8 +334,23 @@ std::shared_ptr SPUDatabase::analyse(const be_t* ls, u32 en // Set whether the function can reset stack func->does_reset_stack = ila_sp_pos < limit; - // Add function to the database - m_db.emplace(key, func); + // Lock here just before we write to the db + // Its is unlikely that the second check will pass anyway so we delay this step since compiling functions is very fast + { + writer_lock lock(m_mutex); + + if (0)//funcs_length != m_db.size()) + { + // Double-check if something new has been written before we got here + if (auto func = find(base, key, block_sz)) + { + return func; + } + } + + // Add function to the database + m_db.emplace(key, func); + } LOG_SUCCESS(SPU, "Function detected [0x%05x-0x%05x] (size=0x%x)", func->addr, func->addr + func->size, func->size);