Merge pull request #13302 from TryTwo/Breakpoints_Fix_Lag
Breakpoints: Fix lag when loading multiple memory breakpoints
This commit is contained in:
commit
6ee08fb9db
|
@ -255,6 +255,8 @@ MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||||
|
|
||||||
void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
|
void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
|
||||||
{
|
{
|
||||||
|
const Core::CPUThreadGuard guard(m_system);
|
||||||
|
|
||||||
for (const std::string& mc_string : mc_strings)
|
for (const std::string& mc_string : mc_strings)
|
||||||
{
|
{
|
||||||
TMemCheck mc;
|
TMemCheck mc;
|
||||||
|
@ -281,15 +283,16 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
|
||||||
mc.condition = Expression::TryParse(condition);
|
mc.condition = Expression::TryParse(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
Add(std::move(mc));
|
Add(std::move(mc), false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemChecks::Add(TMemCheck memory_check)
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemChecks::Add(TMemCheck memory_check, bool update)
|
||||||
{
|
{
|
||||||
bool had_any = HasAny();
|
|
||||||
|
|
||||||
const Core::CPUThreadGuard guard(m_system);
|
const Core::CPUThreadGuard guard(m_system);
|
||||||
|
|
||||||
// Check for existing breakpoint, and overwrite with new info.
|
// Check for existing breakpoint, and overwrite with new info.
|
||||||
// This is assuming we usually want the new breakpoint over an old one.
|
// This is assuming we usually want the new breakpoint over an old one.
|
||||||
const u32 address = memory_check.start_address;
|
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));
|
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 (update)
|
||||||
if (!had_any)
|
Update();
|
||||||
m_system.GetJitInterface().ClearCache(guard);
|
|
||||||
m_system.GetMMU().DBATUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemChecks::ToggleEnable(u32 address)
|
bool MemChecks::ToggleEnable(u32 address)
|
||||||
|
@ -325,7 +326,7 @@ bool MemChecks::ToggleEnable(u32 address)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemChecks::Remove(u32 address)
|
bool MemChecks::Remove(u32 address, bool update)
|
||||||
{
|
{
|
||||||
const auto iter =
|
const auto iter =
|
||||||
std::find_if(m_mem_checks.cbegin(), m_mem_checks.cend(),
|
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);
|
const Core::CPUThreadGuard guard(m_system);
|
||||||
m_mem_checks.erase(iter);
|
m_mem_checks.erase(iter);
|
||||||
if (!HasAny())
|
|
||||||
m_system.GetJitInterface().ClearCache(guard);
|
if (update)
|
||||||
m_system.GetMMU().DBATUpdated();
|
Update();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +348,20 @@ void MemChecks::Clear()
|
||||||
{
|
{
|
||||||
const Core::CPUThreadGuard guard(m_system);
|
const Core::CPUThreadGuard guard(m_system);
|
||||||
m_mem_checks.clear();
|
m_mem_checks.clear();
|
||||||
|
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_system.GetJitInterface().ClearCache(guard);
|
||||||
|
m_mem_breakpoints_set = HasAny();
|
||||||
|
}
|
||||||
|
|
||||||
m_system.GetMMU().DBATUpdated();
|
m_system.GetMMU().DBATUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,19 +115,20 @@ public:
|
||||||
TMemChecksStr GetStrings() const;
|
TMemChecksStr GetStrings() const;
|
||||||
void AddFromStrings(const TMemChecksStr& mc_strings);
|
void AddFromStrings(const TMemChecksStr& mc_strings);
|
||||||
|
|
||||||
void Add(TMemCheck memory_check);
|
void Add(TMemCheck memory_check, bool update = true);
|
||||||
|
|
||||||
bool ToggleEnable(u32 address);
|
bool ToggleEnable(u32 address);
|
||||||
|
|
||||||
TMemCheck* GetMemCheck(u32 address, size_t size = 1);
|
TMemCheck* GetMemCheck(u32 address, size_t size = 1);
|
||||||
bool OverlapsMemcheck(u32 address, u32 length) const;
|
bool OverlapsMemcheck(u32 address, u32 length) const;
|
||||||
// Remove Breakpoint. Returns whether it was removed.
|
bool Remove(u32 address, bool update = true);
|
||||||
bool Remove(u32 address);
|
|
||||||
|
|
||||||
|
void Update();
|
||||||
void Clear();
|
void Clear();
|
||||||
bool HasAny() const { return !m_mem_checks.empty(); }
|
bool HasAny() const { return !m_mem_checks.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TMemChecks m_mem_checks;
|
TMemChecks m_mem_checks;
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
|
bool m_mem_breakpoints_set = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -174,9 +174,10 @@ static void RemoveBreakpoint(BreakpointType type, u32 addr, u32 len)
|
||||||
auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks();
|
auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks();
|
||||||
while (memchecks.GetMemCheck(addr, len) != nullptr)
|
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);
|
INFO_LOG_FMT(GDB_STUB, "gdb: removed a memcheck: {:08x} bytes at {:08x}", len, addr);
|
||||||
}
|
}
|
||||||
|
memchecks.Update();
|
||||||
}
|
}
|
||||||
Host_PPCBreakpointsChanged();
|
Host_PPCBreakpointsChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -994,6 +994,9 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
|
||||||
if (row && memchecks.OverlapsMemcheck(addr, m_bytes_per_row))
|
if (row && memchecks.OverlapsMemcheck(addr, m_bytes_per_row))
|
||||||
overlap = true;
|
overlap = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
const Core::CPUThreadGuard guard(m_system);
|
||||||
|
|
||||||
for (int i = 0; i < breaks; i++)
|
for (int i = 0; i < breaks; i++)
|
||||||
{
|
{
|
||||||
u32 address = addr + length * i;
|
u32 address = addr + length * i;
|
||||||
|
@ -1006,19 +1009,23 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
|
||||||
check.end_address = check.start_address + length - 1;
|
check.end_address = check.start_address + length - 1;
|
||||||
check.is_ranged = length > 0;
|
check.is_ranged = length > 0;
|
||||||
check.is_break_on_read = (m_bp_type == BPType::ReadOnly || m_bp_type == BPType::ReadWrite);
|
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.is_break_on_write =
|
||||||
|
(m_bp_type == BPType::WriteOnly || m_bp_type == BPType::ReadWrite);
|
||||||
check.log_on_hit = m_do_log;
|
check.log_on_hit = m_do_log;
|
||||||
check.break_on_hit = true;
|
check.break_on_hit = true;
|
||||||
|
|
||||||
memchecks.Add(std::move(check));
|
memchecks.Add(std::move(check), false);
|
||||||
}
|
}
|
||||||
else if (check_ptr != nullptr)
|
else if (check_ptr != nullptr)
|
||||||
{
|
{
|
||||||
// Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view).
|
// Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view).
|
||||||
memchecks.Remove(check_ptr->start_address);
|
memchecks.Remove(check_ptr->start_address, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memchecks.Update();
|
||||||
|
}
|
||||||
|
|
||||||
emit Host::GetInstance()->PPCBreakpointsChanged();
|
emit Host::GetInstance()->PPCBreakpointsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue