summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTryTwo <taolas@gmail.com>2023-11-27 17:08:31 -0700
committerTryTwo <taolas@gmail.com>2025-02-04 00:21:13 -0700
commitbbf72e79f90714be6f1de4eea080911e7070f488 (patch)
tree3bdbe8048dc305ae01f9491798ba55747f6b4164
parent696b363f478961bb18420b79ef9f09eabd600e55 (diff)
Breakpoints: Fix lag when adding or removing multiple memory breakpoints by only calling DBATUpdated() once.
-rw-r--r--Source/Core/Core/PowerPC/BreakPoints.cpp43
-rw-r--r--Source/Core/Core/PowerPC/BreakPoints.h7
-rw-r--r--Source/Core/Core/PowerPC/GDBStub.cpp3
-rw-r--r--Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp45
4 files changed, 61 insertions, 37 deletions
diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp
index 19ceac7b3f..bb3c683fb4 100644
--- a/Source/Core/Core/PowerPC/BreakPoints.cpp
+++ b/Source/Core/Core/PowerPC/BreakPoints.cpp
@@ -255,6 +255,8 @@ MemChecks::TMemChecksStr MemChecks::GetStrings() const
void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
{
+ const Core::CPUThreadGuard guard(m_system);
+
for (const std::string& mc_string : mc_strings)
{
TMemCheck mc;
@@ -281,15 +283,16 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
mc.condition = Expression::TryParse(condition);
}
- Add(std::move(mc));
+ Add(std::move(mc), false);
}
+
+ Update();
}
-void MemChecks::Add(TMemCheck memory_check)
+void MemChecks::Add(TMemCheck memory_check, bool update)
{
- bool had_any = HasAny();
-
const Core::CPUThreadGuard guard(m_system);
+
// Check for existing breakpoint, and overwrite with new info.
// This is assuming we usually want the new breakpoint over an old one.
const u32 address = memory_check.start_address;
@@ -306,11 +309,9 @@ void MemChecks::Add(TMemCheck memory_check)
{
m_mem_checks.emplace_back(std::move(memory_check));
}
- // If this is the first one, clear the JIT cache so it can switch to
- // watchpoint-compatible code.
- if (!had_any)
- m_system.GetJitInterface().ClearCache(guard);
- m_system.GetMMU().DBATUpdated();
+
+ if (update)
+ Update();
}
bool MemChecks::ToggleEnable(u32 address)
@@ -325,7 +326,7 @@ bool MemChecks::ToggleEnable(u32 address)
return true;
}
-bool MemChecks::Remove(u32 address)
+bool MemChecks::Remove(u32 address, bool update)
{
const auto iter =
std::find_if(m_mem_checks.cbegin(), m_mem_checks.cend(),
@@ -336,9 +337,10 @@ bool MemChecks::Remove(u32 address)
const Core::CPUThreadGuard guard(m_system);
m_mem_checks.erase(iter);
- if (!HasAny())
- m_system.GetJitInterface().ClearCache(guard);
- m_system.GetMMU().DBATUpdated();
+
+ if (update)
+ Update();
+
return true;
}
@@ -346,7 +348,20 @@ void MemChecks::Clear()
{
const Core::CPUThreadGuard guard(m_system);
m_mem_checks.clear();
- m_system.GetJitInterface().ClearCache(guard);
+ Update();
+}
+
+void MemChecks::Update()
+{
+ const Core::CPUThreadGuard guard(m_system);
+
+ // Clear the JIT cache so it can switch the watchpoint-compatible mode.
+ if (m_mem_breakpoints_set != HasAny())
+ {
+ m_system.GetJitInterface().ClearCache(guard);
+ m_mem_breakpoints_set = HasAny();
+ }
+
m_system.GetMMU().DBATUpdated();
}
diff --git a/Source/Core/Core/PowerPC/BreakPoints.h b/Source/Core/Core/PowerPC/BreakPoints.h
index 9b07fb53c0..6b08c25c8d 100644
--- a/Source/Core/Core/PowerPC/BreakPoints.h
+++ b/Source/Core/Core/PowerPC/BreakPoints.h
@@ -115,19 +115,20 @@ public:
TMemChecksStr GetStrings() const;
void AddFromStrings(const TMemChecksStr& mc_strings);
- void Add(TMemCheck memory_check);
+ void Add(TMemCheck memory_check, bool update = true);
bool ToggleEnable(u32 address);
TMemCheck* GetMemCheck(u32 address, size_t size = 1);
bool OverlapsMemcheck(u32 address, u32 length) const;
- // Remove Breakpoint. Returns whether it was removed.
- bool Remove(u32 address);
+ bool Remove(u32 address, bool update = true);
+ void Update();
void Clear();
bool HasAny() const { return !m_mem_checks.empty(); }
private:
TMemChecks m_mem_checks;
Core::System& m_system;
+ bool m_mem_breakpoints_set = false;
};
diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp
index 349f35254c..c9875a99db 100644
--- a/Source/Core/Core/PowerPC/GDBStub.cpp
+++ b/Source/Core/Core/PowerPC/GDBStub.cpp
@@ -174,9 +174,10 @@ static void RemoveBreakpoint(BreakpointType type, u32 addr, u32 len)
auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks();
while (memchecks.GetMemCheck(addr, len) != nullptr)
{
- memchecks.Remove(addr);
+ memchecks.Remove(addr, false);
INFO_LOG_FMT(GDB_STUB, "gdb: removed a memcheck: {:08x} bytes at {:08x}", len, addr);
}
+ memchecks.Update();
}
Host_PPCBreakpointsChanged();
}
diff --git a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp
index fcf57c8acf..1775d180fa 100644
--- a/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp
+++ b/Source/Core/DolphinQt/Debugger/MemoryViewWidget.cpp
@@ -817,29 +817,36 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
if (row && memchecks.OverlapsMemcheck(addr, m_bytes_per_row))
overlap = true;
- for (int i = 0; i < breaks; i++)
{
- u32 address = addr + length * i;
- TMemCheck* check_ptr = memchecks.GetMemCheck(address, length);
+ const Core::CPUThreadGuard guard(m_system);
- if (check_ptr == nullptr && !overlap)
- {
- TMemCheck check;
- check.start_address = address;
- check.end_address = check.start_address + length - 1;
- check.is_ranged = length > 0;
- check.is_break_on_read = (m_bp_type == BPType::ReadOnly || m_bp_type == BPType::ReadWrite);
- check.is_break_on_write = (m_bp_type == BPType::WriteOnly || m_bp_type == BPType::ReadWrite);
- check.log_on_hit = m_do_log;
- check.break_on_hit = true;
-
- memchecks.Add(std::move(check));
- }
- else if (check_ptr != nullptr)
+ for (int i = 0; i < breaks; i++)
{
- // Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view).
- memchecks.Remove(check_ptr->start_address);
+ u32 address = addr + length * i;
+ TMemCheck* check_ptr = memchecks.GetMemCheck(address, length);
+
+ if (check_ptr == nullptr && !overlap)
+ {
+ TMemCheck check;
+ check.start_address = address;
+ check.end_address = check.start_address + length - 1;
+ check.is_ranged = length > 0;
+ check.is_break_on_read = (m_bp_type == BPType::ReadOnly || m_bp_type == BPType::ReadWrite);
+ check.is_break_on_write =
+ (m_bp_type == BPType::WriteOnly || m_bp_type == BPType::ReadWrite);
+ check.log_on_hit = m_do_log;
+ check.break_on_hit = true;
+
+ memchecks.Add(std::move(check), false);
+ }
+ else if (check_ptr != nullptr)
+ {
+ // Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view).
+ memchecks.Remove(check_ptr->start_address, false);
+ }
}
+
+ memchecks.Update();
}
emit Host::GetInstance()->PPCBreakpointsChanged();