Merge pull request #1678 from shygoo/debugger-opt

[Debugger] Optimize interpreter breakpoint and callback checks
This commit is contained in:
zilmar 2019-12-03 06:13:26 +10:30 committed by GitHub
commit b78a8d182d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 130 additions and 109 deletions

View File

@ -18,6 +18,7 @@
#include <Project64-core/N64System/N64Class.h>
CBreakpoints::CBreakpoints() :
m_bHaveRegBP(false),
m_GPRWriteBP(0),
m_GPRReadBP(0),
m_HIWriteBP(false),
@ -359,22 +360,17 @@ size_t CBreakpoints::NumMemLocks()
return m_MemLocks.size();
}
bool CBreakpoints::HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; }
bool CBreakpoints::HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; }
bool CBreakpoints::HaveGPRWriteBP(int nReg) { return (m_GPRWriteBP & (1 << nReg)) != 0; }
bool CBreakpoints::HaveGPRReadBP(int nReg) { return (m_GPRReadBP & (1 << nReg)) != 0; }
void CBreakpoints::ToggleGPRWriteBP(int nReg) { m_GPRWriteBP ^= (1 << nReg); }
void CBreakpoints::ToggleGPRReadBP(int nReg) { m_GPRReadBP ^= (1 << nReg); }
void CBreakpoints::UpdateHaveRegBP(void)
{
m_bHaveRegBP = HaveAnyGPRWriteBP() || HaveAnyGPRReadBP() || HaveHIWriteBP() || HaveHIReadBP() || HaveLOWriteBP() || HaveLOReadBP();
}
bool CBreakpoints::HaveHIWriteBP(void) { return m_HIWriteBP; }
bool CBreakpoints::HaveHIReadBP(void) { return m_HIReadBP; }
bool CBreakpoints::HaveLOWriteBP(void) { return m_LOWriteBP; }
bool CBreakpoints::HaveLOReadBP(void) { return m_LOReadBP; }
void CBreakpoints::ToggleHIWriteBP(void) { m_HIWriteBP = !m_HIWriteBP; }
void CBreakpoints::ToggleHIReadBP(void) { m_HIReadBP = !m_HIReadBP; }
void CBreakpoints::ToggleLOWriteBP(void) { m_LOWriteBP = !m_LOWriteBP; }
void CBreakpoints::ToggleLOReadBP(void) { m_LOReadBP = !m_LOReadBP; }
void CBreakpoints::ToggleGPRWriteBP(int nReg) { m_GPRWriteBP ^= (1 << nReg); UpdateHaveRegBP(); }
void CBreakpoints::ToggleGPRReadBP(int nReg) { m_GPRReadBP ^= (1 << nReg); UpdateHaveRegBP(); }
void CBreakpoints::ToggleHIWriteBP(void) { m_HIWriteBP = !m_HIWriteBP; UpdateHaveRegBP(); }
void CBreakpoints::ToggleHIReadBP(void) { m_HIReadBP = !m_HIReadBP; UpdateHaveRegBP(); }
void CBreakpoints::ToggleLOWriteBP(void) { m_LOWriteBP = !m_LOWriteBP; UpdateHaveRegBP(); }
void CBreakpoints::ToggleLOReadBP(void) { m_LOReadBP = !m_LOReadBP; UpdateHaveRegBP(); }
void CBreakpoints::PreUpdateBP()
{

View File

@ -67,17 +67,19 @@ public:
void ClearMemLocks(void);
size_t NumMemLocks(void);
bool HaveAnyGPRReadBP(void);
bool HaveAnyGPRWriteBP(void);
bool HaveGPRWriteBP(int nReg);
bool HaveGPRReadBP(int nReg);
inline bool HaveRegBP(void) { return m_bHaveRegBP; }
inline bool HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; }
inline bool HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; }
inline bool HaveGPRWriteBP(int nReg) { return (m_GPRWriteBP & (1 << nReg)) != 0; }
inline bool HaveGPRReadBP(int nReg) { return (m_GPRReadBP & (1 << nReg)) != 0; }
inline bool HaveHIWriteBP(void) { return m_HIWriteBP; }
inline bool HaveHIReadBP(void) { return m_HIReadBP; }
inline bool HaveLOWriteBP(void) { return m_LOWriteBP; }
inline bool HaveLOReadBP(void) { return m_LOReadBP; }
void UpdateHaveRegBP(void);
void ToggleGPRWriteBP(int nReg);
void ToggleGPRReadBP(int nReg);
bool HaveHIWriteBP(void);
bool HaveHIReadBP(void);
bool HaveLOWriteBP(void);
bool HaveLOReadBP(void);
void ToggleHIWriteBP(void);
void ToggleHIReadBP(void);
void ToggleLOWriteBP(void);
@ -95,6 +97,7 @@ private:
memlocks_t m_MemLocks;
bool m_bHaveRegBP;
uint32_t m_GPRWriteBP, m_GPRReadBP;
bool m_HIWriteBP, m_HIReadBP, m_LOWriteBP, m_LOReadBP;
};

View File

@ -24,28 +24,6 @@ CDebugStackTrace::~CDebugStackTrace()
{
}
void CDebugStackTrace::PushEntry(uint32_t routineAddress, uint32_t callingAddress)
{
if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES)
{
m_Entries[m_EntriesIndex] = { routineAddress, callingAddress };
m_EntriesIndex++;
}
}
void CDebugStackTrace::PopEntry()
{
if (m_EntriesIndex > 0)
{
m_EntriesIndex--;
}
}
void CDebugStackTrace::ClearEntries()
{
m_EntriesIndex = 0;
}
LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
DlgResize_Init();

View File

@ -32,9 +32,27 @@ public:
void Refresh();
void PushEntry(uint32_t routineAddress, uint32_t callingAddress);
void PopEntry();
void ClearEntries();
inline void PushEntry(uint32_t routineAddress, uint32_t callingAddress)
{
if (m_EntriesIndex < STACKTRACE_MAX_ENTRIES)
{
m_Entries[m_EntriesIndex] = { routineAddress, callingAddress };
m_EntriesIndex++;
}
}
inline void PopEntry()
{
if (m_EntriesIndex > 0)
{
m_EntriesIndex--;
}
}
inline void ClearEntries()
{
m_EntriesIndex = 0;
}
private:

View File

@ -540,19 +540,19 @@ void CDebuggerUI::HandleCartToRamDMA(void)
// Called from the interpreter core at the beginning of every CPU step
void CDebuggerUI::CPUStepStarted()
{
uint32_t pc = g_Reg->m_PROGRAM_COUNTER;
COpInfo opInfo(R4300iOp::m_Opcode);
bool bStoreOp = opInfo.IsStoreCommand();
uint32_t storeAddress = bStoreOp ? opInfo.GetLoadStoreAddress() : 0;
if (isStepping() && bCPULoggingEnabled())
{
Debug_RefreshCPULogWindow();
}
uint32_t pc = g_Reg->m_PROGRAM_COUNTER;
COpInfo opInfo(R4300iOp::m_Opcode);
if (opInfo.IsStoreCommand())
if(bStoreOp && m_Breakpoints->NumMemLocks() > 0)
{
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
if (m_Breakpoints->MemLockExists(storeAddress, opInfo.NumBytesToStore()))
{
// Memory is locked, skip op
g_Settings->SaveBool(Debugger_SkipOp, true);
@ -560,37 +560,35 @@ void CDebuggerUI::CPUStepStarted()
}
}
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc);
if (SkipOp()) { return; }
m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex);
if (SkipOp()) { return; }
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc);
if (SkipOp()) { return; }
// Memory events, pi cart -> ram dma
if (opInfo.IsLoadStoreCommand()) // Read and write instructions
if (m_ScriptSystem->HaveCallbacks())
{
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc);
if (SkipOp()) { return; }
if (opInfo.IsLoadCommand()) // Read instructions
m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex);
if (SkipOp()) { return; }
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc);
if (SkipOp()) { return; }
if (bStoreOp)
{
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(memoryAddress);
m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(storeAddress);
if (SkipOp()) { return; }
}
else // Write instructions
{
m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(memoryAddress);
if (SkipOp()) { return; }
if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG
{
HandleCartToRamDMA();
}
if (opInfo.IsLoadCommand())
{
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(opInfo.GetLoadStoreAddress());
if (SkipOp()) { return; }
}
}
if (bStoreOp && storeAddress == 0xA460000C) // PI_WR_LEN_REG
{
HandleCartToRamDMA();
}
if (CDebugSettings::ExceptionBreakpoints() != 0)
{
if (pc == 0x80000000 || pc == 0x80000080 ||
@ -603,36 +601,39 @@ void CDebuggerUI::CPUStepStarted()
}
}
if (m_Breakpoints->HaveAnyGPRWriteBP())
if (m_Breakpoints->HaveRegBP())
{
int nReg = 0;
opInfo.WritesGPR(&nReg);
if (m_Breakpoints->HaveAnyGPRWriteBP())
{
int nReg = 0;
opInfo.WritesGPR(&nReg);
if (nReg != 0 && m_Breakpoints->HaveGPRWriteBP(nReg))
if (nReg != 0 && m_Breakpoints->HaveGPRWriteBP(nReg))
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
}
}
if (m_Breakpoints->HaveAnyGPRReadBP())
{
int nReg1 = 0, nReg2 = 0;
opInfo.ReadsGPR(&nReg1, &nReg2);
if ((nReg1 != 0 && m_Breakpoints->HaveGPRReadBP(nReg1)) ||
(nReg2 != 0 && m_Breakpoints->HaveGPRReadBP(nReg2)))
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
}
}
if (m_Breakpoints->HaveHIWriteBP() && opInfo.WritesHI() ||
m_Breakpoints->HaveLOWriteBP() && opInfo.WritesLO() ||
m_Breakpoints->HaveHIReadBP() && opInfo.ReadsHI() ||
m_Breakpoints->HaveLOReadBP() && opInfo.ReadsLO())
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
}
}
if (m_Breakpoints->HaveAnyGPRReadBP())
{
int nReg1 = 0, nReg2 = 0;
opInfo.ReadsGPR(&nReg1, &nReg2);
if ((nReg1 != 0 && m_Breakpoints->HaveGPRReadBP(nReg1)) ||
(nReg2 != 0 && m_Breakpoints->HaveGPRReadBP(nReg2)))
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
}
}
if (m_Breakpoints->HaveHIWriteBP() && opInfo.WritesHI() ||
m_Breakpoints->HaveLOWriteBP() && opInfo.WritesLO() ||
m_Breakpoints->HaveHIReadBP() && opInfo.ReadsHI() ||
m_Breakpoints->HaveLOReadBP() && opInfo.ReadsLO())
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
}
}
// Called before opcode is executed (not called if SkipOp is set)
@ -647,15 +648,15 @@ void CDebuggerUI::CPUStep()
// Called after opcode has been executed
void CDebuggerUI::CPUStepEnded()
{
if (m_StackTrace == NULL)
{
return;
}
OPCODE Opcode = R4300iOp::m_Opcode;
uint32_t op = Opcode.op;
uint32_t funct = Opcode.funct;
if (m_StackTrace == NULL)
{
m_StackTrace = new CDebugStackTrace(this);
}
if (op == R4300i_JAL || ((op == R4300i_SPECIAL) && (funct == R4300i_SPECIAL_JALR) && (Opcode.rd == 31))) // JAL or JALR RA, x
{
m_StackTrace->PushEntry(R4300iOp::m_JumpToLocation, g_Reg->m_PROGRAM_COUNTER);

View File

@ -17,6 +17,7 @@ int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t pa
jsCallback.param4 = param4;
jsCallback.bOnce = bOnce;
m_Callbacks.push_back(jsCallback);
m_ScriptSystem->CallbackAdded();
return jsCallback.callbackId;
}
@ -122,6 +123,7 @@ void CScriptHook::RemoveById(int callbackId)
if (m_Callbacks[i].callbackId == callbackId)
{
m_Callbacks.erase(m_Callbacks.begin() + i);
m_ScriptSystem->CallbackRemoved();
return;
}
}
@ -135,6 +137,7 @@ void CScriptHook::RemoveByParam(uint32_t param)
if (m_Callbacks[i].param == param)
{
m_Callbacks.erase(m_Callbacks.begin() + i);
m_ScriptSystem->CallbackRemoved();
return;
}
}
@ -148,6 +151,7 @@ void CScriptHook::RemoveByInstance(CScriptInstance* scriptInstance)
if (m_Callbacks[i].scriptInstance == scriptInstance)
{
m_Callbacks.erase(m_Callbacks.begin() + i);
m_ScriptSystem->CallbackRemoved();
}
}
}

View File

@ -21,6 +21,7 @@ CScriptSystem::CScriptSystem(CDebuggerUI* debugger)
WSAStartup(MAKEWORD(2, 2), &wsaData);
m_NextCallbackId = 0;
m_NumCallbacks = 0;
m_Debugger = debugger;
@ -207,4 +208,17 @@ CScriptHook* CScriptSystem::GetHook(const char* hookId)
int CScriptSystem::GetNextCallbackId()
{
return m_NextCallbackId++;
}
}
void CScriptSystem::CallbackAdded()
{
m_NumCallbacks++;
}
void CScriptSystem::CallbackRemoved()
{
if (m_NumCallbacks > 0)
{
m_NumCallbacks--;
}
}

View File

@ -43,7 +43,7 @@ private:
} INSTANCE_ENTRY;
CDebuggerUI* m_Debugger;
int m_NumCallbacks;
char* m_APIScript;
vector<HOOKENTRY> m_Hooks;
@ -103,6 +103,13 @@ public:
CScriptHook* GetHook(const char* hookId);
int GetNextCallbackId();
void CallbackAdded();
void CallbackRemoved();
inline int HaveCallbacks()
{
return m_NumCallbacks != 0;
}
void DeleteStoppedInstances();
INSTANCE_STATE GetInstanceState(char* scriptName);