Debugger: Improved performance (games run about 50% faster with debugger opened compared to before)

This commit is contained in:
Souryo 2016-11-18 21:32:07 -05:00
parent 5a24608f8f
commit cf24fdc1d0
4 changed files with 70 additions and 78 deletions

View File

@ -15,9 +15,17 @@ bool Breakpoint::Matches(uint32_t memoryAddr, uint32_t absoluteAddr)
return _addr == -1 || ((int32_t)memoryAddr == _addr && !_isAbsoluteAddr) || ((int32_t)absoluteAddr == _addr && _isAbsoluteAddr); return _addr == -1 || ((int32_t)memoryAddr == _addr && !_isAbsoluteAddr) || ((int32_t)absoluteAddr == _addr && _isAbsoluteAddr);
} }
BreakpointType Breakpoint::GetType() bool Breakpoint::HasBreakpointType(BreakpointType type)
{ {
return _type; switch(type) {
case BreakpointType::Global: return (_type == BreakpointTypeFlags::Global);
case BreakpointType::Execute: return (_type & BreakpointTypeFlags::Execute) == BreakpointTypeFlags::Execute;
case BreakpointType::ReadRam: return (_type & BreakpointTypeFlags::ReadRam) == BreakpointTypeFlags::ReadRam;
case BreakpointType::WriteRam: return (_type & BreakpointTypeFlags::WriteRam) == BreakpointTypeFlags::WriteRam;
case BreakpointType::ReadVram: return (_type & BreakpointTypeFlags::ReadVram) == BreakpointTypeFlags::ReadVram;
case BreakpointType::WriteVram: return (_type & BreakpointTypeFlags::WriteVram) == BreakpointTypeFlags::WriteVram;
}
return false;
} }
string Breakpoint::GetCondition() string Breakpoint::GetCondition()

View File

@ -7,24 +7,35 @@ enum BreakpointType
Global = 0, Global = 0,
Execute = 1, Execute = 1,
ReadRam = 2, ReadRam = 2,
WriteRam = 4, WriteRam = 3,
ReadVram = 8, ReadVram = 4,
WriteVram = 16, WriteVram = 5,
}; };
class Breakpoint class Breakpoint
{ {
private:
enum BreakpointTypeFlags
{
Global = 0,
Execute = 1,
ReadRam = 2,
WriteRam = 4,
ReadVram = 8,
WriteVram = 16,
};
public: public:
Breakpoint(); Breakpoint();
~Breakpoint(); ~Breakpoint();
bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr); bool Matches(uint32_t memoryAddr, uint32_t absoluteAddr);
BreakpointType GetType(); bool HasBreakpointType(BreakpointType type);
string GetCondition(); string GetCondition();
void ClearCondition(); void ClearCondition();
private: private:
BreakpointType _type; BreakpointTypeFlags _type;
int32_t _addr; int32_t _addr;
bool _isAbsoluteAddr; bool _isAbsoluteAddr;
char _condition[1000]; char _condition[1000];

View File

@ -12,6 +12,7 @@
#include "ExpressionEvaluator.h" #include "ExpressionEvaluator.h"
Debugger* Debugger::Instance = nullptr; Debugger* Debugger::Instance = nullptr;
const int Debugger::BreakpointTypeCount;
Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper) Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<PPU> ppu, shared_ptr<MemoryManager> memoryManager, shared_ptr<BaseMapper> mapper)
{ {
@ -32,7 +33,6 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
_flags = 0; _flags = 0;
_hasBreakpoint = false;
_bpUpdateNeeded = false; _bpUpdateNeeded = false;
_executionStopped = false; _executionStopped = false;
@ -121,27 +121,37 @@ CdlRatios Debugger::GetCdlRatios()
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length) void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
{ {
_hasBreakpoint = length > 0; _bpUpdateLock.AcquireSafe();
while(_updatingBreakpoints) { }
_newBreakpoints.clear(); _newBreakpoints.clear();
_newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length); _newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length);
_bpUpdateNeeded = true; _bpUpdateNeeded = true;
if(_executionStopped) { if(_executionStopped) {
UpdateBreakpoints(); UpdateBreakpoints();
} else {
bool hasBreakpoint[Debugger::BreakpointTypeCount]{ false,false,false,false,false,false };
for(Breakpoint &bp : _newBreakpoints) {
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
hasBreakpoint[i] |= bp.HasBreakpointType((BreakpointType)i);
}
}
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
_hasBreakpoint[i] = hasBreakpoint[i];
}
} }
} }
void Debugger::UpdateBreakpoints() void Debugger::UpdateBreakpoints()
{ {
_updatingBreakpoints = true;
if(_bpUpdateNeeded) { if(_bpUpdateNeeded) {
_globalBreakpoints.clear(); _bpUpdateLock.AcquireSafe();
_execBreakpoints.clear();
_readBreakpoints.clear(); for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
_writeBreakpoints.clear(); _breakpoints[i].clear();
_readVramBreakpoints.clear(); _hasBreakpoint[i] = false;
_writeVramBreakpoints.clear(); }
ExpressionEvaluator expEval; ExpressionEvaluator expEval;
for(Breakpoint &bp : _newBreakpoints) { for(Breakpoint &bp : _newBreakpoints) {
@ -150,31 +160,16 @@ void Debugger::UpdateBreakpoints()
bp.ClearCondition(); bp.ClearCondition();
} }
BreakpointType type = bp.GetType(); for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
if(type & BreakpointType::Execute) { if(bp.HasBreakpointType((BreakpointType)i)) {
_execBreakpoints.push_back(bp); _breakpoints[i].push_back(bp);
} _hasBreakpoint[i] = true;
if(type & BreakpointType::ReadRam) { }
_readBreakpoints.push_back(bp);
}
if(type & BreakpointType::ReadVram) {
_readVramBreakpoints.push_back(bp);
}
if(type & BreakpointType::WriteRam) {
_writeBreakpoints.push_back(bp);
}
if(type & BreakpointType::WriteVram) {
_writeVramBreakpoints.push_back(bp);
}
if(type == BreakpointType::Global) {
_globalBreakpoints.push_back(bp);
} }
} }
_bpUpdateNeeded = false; _bpUpdateNeeded = false;
} }
_updatingBreakpoints = false;
} }
bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value) bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value)
@ -182,20 +177,11 @@ bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t
UpdateBreakpoints(); UpdateBreakpoints();
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr); uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
vector<Breakpoint> *breakpoints = nullptr; vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
switch(type) {
case BreakpointType::Global: breakpoints = &_globalBreakpoints; break;
case BreakpointType::Execute: breakpoints = &_execBreakpoints; break;
case BreakpointType::ReadRam: breakpoints = &_readBreakpoints; break;
case BreakpointType::WriteRam: breakpoints = &_writeBreakpoints; break;
case BreakpointType::ReadVram: breakpoints = &_readVramBreakpoints; break;
case BreakpointType::WriteVram: breakpoints = &_writeVramBreakpoints; break;
}
bool needState = true; bool needState = true;
for(size_t i = 0, len = breakpoints->size(); i < len; i++) { for(size_t i = 0, len = breakpoints.size(); i < len; i++) {
Breakpoint &breakpoint = (*breakpoints)[i]; Breakpoint &breakpoint = breakpoints[i];
if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) { if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) {
string condition = breakpoint.GetCondition(); string condition = breakpoint.GetCondition();
if(condition.empty()) { if(condition.empty()) {
@ -259,7 +245,7 @@ void Debugger::ProcessStepConditions(uint32_t addr)
void Debugger::PrivateProcessPpuCycle() void Debugger::PrivateProcessPpuCycle()
{ {
if(_hasBreakpoint && HasMatchingBreakpoint(BreakpointType::Global, 0, -1)) { if(_hasBreakpoint[BreakpointType::Global] && HasMatchingBreakpoint(BreakpointType::Global, 0, -1)) {
//Found a matching breakpoint, stop execution //Found a matching breakpoint, stop execution
Step(1); Step(1);
SleepUntilResume(); SleepUntilResume();
@ -316,32 +302,21 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
} }
} }
if(!breakDone && _hasBreakpoint) { if(!breakDone) {
BreakOnBreakpoint(type, addr, value); BreakpointType breakpointType = BreakpointType::Execute;
}
_currentReadAddr = nullptr;
}
void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value)
{
if(_hasBreakpoint) {
BreakpointType breakpointType;
switch(type) { switch(type) {
case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break; case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; break;
case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break; case MemoryOperationType::Write: breakpointType = BreakpointType::WriteRam; break;
default:
case MemoryOperationType::ExecOpCode:
case MemoryOperationType::ExecOperand: breakpointType = BreakpointType::Execute; break;
} }
if(HasMatchingBreakpoint(breakpointType, addr, (type == MemoryOperationType::ExecOperand) ? -1 : value)) { if(_hasBreakpoint[breakpointType] && HasMatchingBreakpoint(breakpointType, addr, (type == MemoryOperationType::ExecOperand) ? -1 : value)) {
//Found a matching breakpoint, stop execution //Found a matching breakpoint, stop execution
Step(1); Step(1);
SleepUntilResume(); SleepUntilResume();
} }
} }
_currentReadAddr = nullptr;
} }
bool Debugger::SleepUntilResume() bool Debugger::SleepUntilResume()
@ -379,7 +354,8 @@ void Debugger::PrivateProcessVramOperation(MemoryOperationType type, uint16_t ad
_codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn); _codeDataLogger->SetFlag(absoluteAddr, type == MemoryOperationType::Read ? CdlChrFlags::Read : CdlChrFlags::Drawn);
} }
if(_hasBreakpoint && HasMatchingBreakpoint(type == MemoryOperationType::Write ? BreakpointType::WriteVram : BreakpointType::ReadVram, addr, value)) { BreakpointType bpType = type == MemoryOperationType::Write ? BreakpointType::WriteVram : BreakpointType::ReadVram;
if(_hasBreakpoint[bpType] && HasMatchingBreakpoint(bpType, addr, value)) {
//Found a matching breakpoint, stop execution //Found a matching breakpoint, stop execution
Step(1); Step(1);
SleepUntilResume(); SleepUntilResume();

View File

@ -50,6 +50,8 @@ class Debugger
private: private:
static Debugger* Instance; static Debugger* Instance;
const static int BreakpointTypeCount = 6;
unique_ptr<Disassembler> _disassembler; unique_ptr<Disassembler> _disassembler;
unique_ptr<CodeDataLogger> _codeDataLogger; unique_ptr<CodeDataLogger> _codeDataLogger;
shared_ptr<Console> _console; shared_ptr<Console> _console;
@ -58,19 +60,15 @@ private:
shared_ptr<MemoryManager> _memoryManager; shared_ptr<MemoryManager> _memoryManager;
shared_ptr<BaseMapper> _mapper; shared_ptr<BaseMapper> _mapper;
atomic<bool> _bpUpdateNeeded; bool _bpUpdateNeeded;
atomic<bool> _updatingBreakpoints; SimpleLock _bpUpdateLock;
atomic<bool> _stopFlag; atomic<bool> _stopFlag;
atomic<bool> _executionStopped; atomic<bool> _executionStopped;
atomic<int32_t> _suspendCount; atomic<int32_t> _suspendCount;
vector<Breakpoint> _newBreakpoints; vector<Breakpoint> _newBreakpoints;
vector<Breakpoint> _readBreakpoints; vector<Breakpoint> _breakpoints[BreakpointTypeCount];
vector<Breakpoint> _writeBreakpoints; bool _hasBreakpoint[BreakpointTypeCount];
vector<Breakpoint> _execBreakpoints;
vector<Breakpoint> _globalBreakpoints;
vector<Breakpoint> _readVramBreakpoints;
vector<Breakpoint> _writeVramBreakpoints;
atomic<bool> _hasBreakpoint;
deque<uint32_t> _callstackAbsolute; deque<uint32_t> _callstackAbsolute;
deque<uint32_t> _callstackRelative; deque<uint32_t> _callstackRelative;
@ -105,7 +103,6 @@ private:
bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value); bool HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value);
void UpdateCallstack(uint32_t addr); void UpdateCallstack(uint32_t addr);
void ProcessStepConditions(uint32_t addr); void ProcessStepConditions(uint32_t addr);
void BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value);
bool SleepUntilResume(); bool SleepUntilResume();
public: public: