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

View File

@ -67,17 +67,19 @@ public:
void ClearMemLocks(void); void ClearMemLocks(void);
size_t NumMemLocks(void); size_t NumMemLocks(void);
bool HaveAnyGPRReadBP(void); inline bool HaveRegBP(void) { return m_bHaveRegBP; }
bool HaveAnyGPRWriteBP(void); inline bool HaveAnyGPRWriteBP(void) { return m_GPRWriteBP != 0; }
bool HaveGPRWriteBP(int nReg); inline bool HaveAnyGPRReadBP(void) { return m_GPRReadBP != 0; }
bool HaveGPRReadBP(int nReg); 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 ToggleGPRWriteBP(int nReg);
void ToggleGPRReadBP(int nReg); void ToggleGPRReadBP(int nReg);
bool HaveHIWriteBP(void);
bool HaveHIReadBP(void);
bool HaveLOWriteBP(void);
bool HaveLOReadBP(void);
void ToggleHIWriteBP(void); void ToggleHIWriteBP(void);
void ToggleHIReadBP(void); void ToggleHIReadBP(void);
void ToggleLOWriteBP(void); void ToggleLOWriteBP(void);
@ -95,6 +97,7 @@ private:
memlocks_t m_MemLocks; memlocks_t m_MemLocks;
bool m_bHaveRegBP;
uint32_t m_GPRWriteBP, m_GPRReadBP; uint32_t m_GPRWriteBP, m_GPRReadBP;
bool m_HIWriteBP, m_HIReadBP, m_LOWriteBP, m_LOReadBP; 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*/) LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{ {
DlgResize_Init(); DlgResize_Init();

View File

@ -32,9 +32,27 @@ public:
void Refresh(); void Refresh();
void PushEntry(uint32_t routineAddress, uint32_t callingAddress); inline void PushEntry(uint32_t routineAddress, uint32_t callingAddress)
void PopEntry(); {
void ClearEntries(); 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: private:

View File

@ -540,19 +540,19 @@ void CDebuggerUI::HandleCartToRamDMA(void)
// Called from the interpreter core at the beginning of every CPU step // Called from the interpreter core at the beginning of every CPU step
void CDebuggerUI::CPUStepStarted() 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()) if (isStepping() && bCPULoggingEnabled())
{ {
Debug_RefreshCPULogWindow(); Debug_RefreshCPULogWindow();
} }
uint32_t pc = g_Reg->m_PROGRAM_COUNTER; if(bStoreOp && m_Breakpoints->NumMemLocks() > 0)
COpInfo opInfo(R4300iOp::m_Opcode);
if (opInfo.IsStoreCommand())
{ {
uint32_t memoryAddress = opInfo.GetLoadStoreAddress(); if (m_Breakpoints->MemLockExists(storeAddress, opInfo.NumBytesToStore()))
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
{ {
// Memory is locked, skip op // Memory is locked, skip op
g_Settings->SaveBool(Debugger_SkipOp, true); g_Settings->SaveBool(Debugger_SkipOp, true);
@ -560,6 +560,8 @@ void CDebuggerUI::CPUStepStarted()
} }
} }
if (m_ScriptSystem->HaveCallbacks())
{
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc); m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc);
if (SkipOp()) { return; } if (SkipOp()) { return; }
@ -569,27 +571,23 @@ void CDebuggerUI::CPUStepStarted()
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc); m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc);
if (SkipOp()) { return; } if (SkipOp()) { return; }
// Memory events, pi cart -> ram dma if (bStoreOp)
if (opInfo.IsLoadStoreCommand()) // Read and write instructions
{ {
uint32_t memoryAddress = opInfo.GetLoadStoreAddress(); m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(storeAddress);
if (opInfo.IsLoadCommand()) // Read instructions
{
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(memoryAddress);
if (SkipOp()) { return; } if (SkipOp()) { return; }
} }
else // Write instructions
{
m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(memoryAddress);
if (SkipOp()) { return; }
if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG if (opInfo.IsLoadCommand())
{
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(opInfo.GetLoadStoreAddress());
if (SkipOp()) { return; }
}
}
if (bStoreOp && storeAddress == 0xA460000C) // PI_WR_LEN_REG
{ {
HandleCartToRamDMA(); HandleCartToRamDMA();
} }
}
}
if (CDebugSettings::ExceptionBreakpoints() != 0) if (CDebugSettings::ExceptionBreakpoints() != 0)
{ {
@ -603,6 +601,8 @@ void CDebuggerUI::CPUStepStarted()
} }
} }
if (m_Breakpoints->HaveRegBP())
{
if (m_Breakpoints->HaveAnyGPRWriteBP()) if (m_Breakpoints->HaveAnyGPRWriteBP())
{ {
int nReg = 0; int nReg = 0;
@ -634,6 +634,7 @@ void CDebuggerUI::CPUStepStarted()
g_Settings->SaveBool(Debugger_SteppingOps, true); g_Settings->SaveBool(Debugger_SteppingOps, true);
} }
} }
}
// Called before opcode is executed (not called if SkipOp is set) // Called before opcode is executed (not called if SkipOp is set)
void CDebuggerUI::CPUStep() void CDebuggerUI::CPUStep()
@ -647,15 +648,15 @@ void CDebuggerUI::CPUStep()
// Called after opcode has been executed // Called after opcode has been executed
void CDebuggerUI::CPUStepEnded() void CDebuggerUI::CPUStepEnded()
{ {
if (m_StackTrace == NULL)
{
return;
}
OPCODE Opcode = R4300iOp::m_Opcode; OPCODE Opcode = R4300iOp::m_Opcode;
uint32_t op = Opcode.op; uint32_t op = Opcode.op;
uint32_t funct = Opcode.funct; 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 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); 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.param4 = param4;
jsCallback.bOnce = bOnce; jsCallback.bOnce = bOnce;
m_Callbacks.push_back(jsCallback); m_Callbacks.push_back(jsCallback);
m_ScriptSystem->CallbackAdded();
return jsCallback.callbackId; return jsCallback.callbackId;
} }
@ -122,6 +123,7 @@ void CScriptHook::RemoveById(int callbackId)
if (m_Callbacks[i].callbackId == callbackId) if (m_Callbacks[i].callbackId == callbackId)
{ {
m_Callbacks.erase(m_Callbacks.begin() + i); m_Callbacks.erase(m_Callbacks.begin() + i);
m_ScriptSystem->CallbackRemoved();
return; return;
} }
} }
@ -135,6 +137,7 @@ void CScriptHook::RemoveByParam(uint32_t param)
if (m_Callbacks[i].param == param) if (m_Callbacks[i].param == param)
{ {
m_Callbacks.erase(m_Callbacks.begin() + i); m_Callbacks.erase(m_Callbacks.begin() + i);
m_ScriptSystem->CallbackRemoved();
return; return;
} }
} }
@ -148,6 +151,7 @@ void CScriptHook::RemoveByInstance(CScriptInstance* scriptInstance)
if (m_Callbacks[i].scriptInstance == scriptInstance) if (m_Callbacks[i].scriptInstance == scriptInstance)
{ {
m_Callbacks.erase(m_Callbacks.begin() + i); 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); WSAStartup(MAKEWORD(2, 2), &wsaData);
m_NextCallbackId = 0; m_NextCallbackId = 0;
m_NumCallbacks = 0;
m_Debugger = debugger; m_Debugger = debugger;
@ -208,3 +209,16 @@ int CScriptSystem::GetNextCallbackId()
{ {
return m_NextCallbackId++; 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; } INSTANCE_ENTRY;
CDebuggerUI* m_Debugger; CDebuggerUI* m_Debugger;
int m_NumCallbacks;
char* m_APIScript; char* m_APIScript;
vector<HOOKENTRY> m_Hooks; vector<HOOKENTRY> m_Hooks;
@ -103,6 +103,13 @@ public:
CScriptHook* GetHook(const char* hookId); CScriptHook* GetHook(const char* hookId);
int GetNextCallbackId(); int GetNextCallbackId();
void CallbackAdded();
void CallbackRemoved();
inline int HaveCallbacks()
{
return m_NumCallbacks != 0;
}
void DeleteStoppedInstances(); void DeleteStoppedInstances();
INSTANCE_STATE GetInstanceState(char* scriptName); INSTANCE_STATE GetInstanceState(char* scriptName);