# UNDF: UNDF-2026-000001042 # UNDF: UNDF-2026-XXXXXXXXX --- a/Source/Core/Core/PowerPC/BreakPoints.h +++ b/Source/Core/Core/PowerPC/BreakPoints.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "Common/BitSet.h" @@ -60,11 +61,18 @@ public: bool Remove(u32 address); void Clear(); void ClearTemporary(); + + // Rebuild the O(1) address index. Called after any mutation. + void RebuildIndex(); private: TBreakPoints m_breakpoints; std::optional m_temp_breakpoint; Core::System& m_system; bool m_breaking_enabled = true; + + // Address -> index into m_breakpoints for O(1) lookup. + // Invalidated and rebuilt on every Add/Remove/Clear. + std::unordered_map m_bp_index; }; --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -52,10 +52,17 @@ const TBreakPoint* BreakPoints::GetBreakpoint(u32 address) const return GetRegularBreakpoint(address); } +void BreakPoints::RebuildIndex() +{ + m_bp_index.clear(); + m_bp_index.reserve(m_breakpoints.size()); + for (std::size_t i = 0; i < m_breakpoints.size(); ++i) + m_bp_index[m_breakpoints[i].address] = i; +} + const TBreakPoint* BreakPoints::GetRegularBreakpoint(u32 address) const { - auto bp = std::ranges::find(m_breakpoints, address, &TBreakPoint::address); - - if (bp == m_breakpoints.end()) + // O(1) hash lookup instead of O(N) linear scan over m_breakpoints. + auto it = m_bp_index.find(address); + if (it == m_bp_index.end()) return nullptr; - return &*bp; + return &m_breakpoints[it->second]; } @@ -115,7 +122,9 @@ void BreakPoints::Add(TBreakPoint bp) if (IsAddressBreakPoint(bp.address)) return; m_system.GetJitInterface().InvalidateICache(bp.address, 4, true); - m_breakpoints.emplace_back(std::move(bp)); + RebuildIndex(); } @@ -133,6 +142,7 @@ void BreakPoints::Add(u32 address, bool break_on_hit, bool log_on_hit, { bp.is_enabled = iter->is_enabled; *iter = std::move(bp); + RebuildIndex(); } else { m_breakpoints.emplace_back(std::move(bp)); + RebuildIndex(); } @@ -181,7 +192,9 @@ bool BreakPoints::Remove(u32 address) if (iter == m_breakpoints.cend()) return false; m_breakpoints.erase(iter); + RebuildIndex(); m_system.GetJitInterface().InvalidateICache(address, 4, true); return true; } @@ -192,6 +205,7 @@ void BreakPoints::Clear() m_system.GetJitInterface().InvalidateICache(bp.address, 4, true); } m_breakpoints.clear(); + m_bp_index.clear(); ClearTemporary(); }