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);
}
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()

View File

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

View File

@ -12,6 +12,7 @@
#include "ExpressionEvaluator.h"
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)
{
@ -32,7 +33,6 @@ Debugger::Debugger(shared_ptr<Console> console, shared_ptr<CPU> cpu, shared_ptr<
_flags = 0;
_hasBreakpoint = false;
_bpUpdateNeeded = false;
_executionStopped = false;
@ -121,27 +121,37 @@ CdlRatios Debugger::GetCdlRatios()
void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
{
_hasBreakpoint = length > 0;
while(_updatingBreakpoints) { }
_bpUpdateLock.AcquireSafe();
_newBreakpoints.clear();
_newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length);
_bpUpdateNeeded = true;
if(_executionStopped) {
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()
{
_updatingBreakpoints = true;
if(_bpUpdateNeeded) {
_globalBreakpoints.clear();
_execBreakpoints.clear();
_readBreakpoints.clear();
_writeBreakpoints.clear();
_readVramBreakpoints.clear();
_writeVramBreakpoints.clear();
_bpUpdateLock.AcquireSafe();
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
_breakpoints[i].clear();
_hasBreakpoint[i] = false;
}
ExpressionEvaluator expEval;
for(Breakpoint &bp : _newBreakpoints) {
@ -150,31 +160,16 @@ void Debugger::UpdateBreakpoints()
bp.ClearCondition();
}
BreakpointType type = bp.GetType();
if(type & BreakpointType::Execute) {
_execBreakpoints.push_back(bp);
}
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);
for(int i = 0; i < Debugger::BreakpointTypeCount; i++) {
if(bp.HasBreakpointType((BreakpointType)i)) {
_breakpoints[i].push_back(bp);
_hasBreakpoint[i] = true;
}
}
}
_bpUpdateNeeded = false;
}
_updatingBreakpoints = false;
}
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();
uint32_t absoluteAddr = _mapper->ToAbsoluteAddress(addr);
vector<Breakpoint> *breakpoints = nullptr;
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;
}
vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
bool needState = true;
for(size_t i = 0, len = breakpoints->size(); i < len; i++) {
Breakpoint &breakpoint = (*breakpoints)[i];
for(size_t i = 0, len = breakpoints.size(); i < len; i++) {
Breakpoint &breakpoint = breakpoints[i];
if(type == BreakpointType::Global || breakpoint.Matches(addr, absoluteAddr)) {
string condition = breakpoint.GetCondition();
if(condition.empty()) {
@ -259,7 +245,7 @@ void Debugger::ProcessStepConditions(uint32_t addr)
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
Step(1);
SleepUntilResume();
@ -316,32 +302,21 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
}
}
if(!breakDone && _hasBreakpoint) {
BreakOnBreakpoint(type, addr, value);
}
_currentReadAddr = nullptr;
}
void Debugger::BreakOnBreakpoint(MemoryOperationType type, uint32_t addr, uint8_t value)
{
if(_hasBreakpoint) {
BreakpointType breakpointType;
if(!breakDone) {
BreakpointType breakpointType = BreakpointType::Execute;
switch(type) {
case MemoryOperationType::Read: breakpointType = BreakpointType::ReadRam; 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
Step(1);
SleepUntilResume();
}
}
_currentReadAddr = nullptr;
}
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);
}
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
Step(1);
SleepUntilResume();

View File

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