mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
JIT profiler: in block performance counter.
MemoryView: raw memory display. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@522 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
bec80af7d2
commit
0ba3948c42
@ -9,6 +9,7 @@ protected:
|
||||
virtual ~DebugInterface() {}
|
||||
public:
|
||||
virtual const char *disasm(unsigned int /*address*/) {return "NODEBUGGER";}
|
||||
virtual const char *getRawMemoryString(unsigned int /*address*/){return "NODEBUGGER";}
|
||||
virtual int getInstructionSize(int /*instruction*/) {return 1;}
|
||||
|
||||
virtual bool isAlive() {return true;}
|
||||
|
@ -42,6 +42,25 @@ const char *PPCDebugInterface::disasm(unsigned int address)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const char *PPCDebugInterface::getRawMemoryString(unsigned int address)
|
||||
{
|
||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
{
|
||||
if (address < 0xE0000000)
|
||||
{
|
||||
static char str[256] ={0};
|
||||
if (sprintf(str,"%08X",readMemory(address))!=8) {
|
||||
PanicAlert("getRawMemoryString -> WTF! ( as read somewhere;) )");
|
||||
return ":(";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
return "No RAM";
|
||||
}
|
||||
static const char tmp[] = "<unknown>";
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned int PPCDebugInterface::readMemory(unsigned int address)
|
||||
{
|
||||
return Memory::ReadUnchecked_U32(address);
|
||||
|
@ -12,6 +12,7 @@ class PPCDebugInterface : public DebugInterface
|
||||
public:
|
||||
PPCDebugInterface(){}
|
||||
virtual const char *disasm(unsigned int address);
|
||||
virtual const char *getRawMemoryString(unsigned int address);
|
||||
virtual int getInstructionSize(int instruction) {return 4;}
|
||||
virtual bool isAlive();
|
||||
virtual bool isBreakpoint(unsigned int address);
|
||||
|
@ -398,6 +398,15 @@ namespace Jit64
|
||||
|
||||
if (Profiler::g_ProfileBlocks) {
|
||||
ADD(32, M(&b.runCount), Imm8(1));
|
||||
#ifdef _WIN32
|
||||
b.ticCounter.QuadPart = 0;
|
||||
b.ticStart.QuadPart = 0;
|
||||
b.ticStop.QuadPart = 0;
|
||||
#else
|
||||
//TODO
|
||||
#endif
|
||||
// get start tic
|
||||
PROFILER_QUERY_PERFORMACE_COUNTER(&b.ticStart);
|
||||
}
|
||||
|
||||
//Start up the register allocators
|
||||
@ -416,8 +425,18 @@ namespace Jit64
|
||||
js.compilerPC = ops[i].address;
|
||||
js.op = &ops[i];
|
||||
js.instructionNumber = i;
|
||||
if (i == (int)size - 1)
|
||||
if (i == (int)size - 1) {
|
||||
js.isLastInstruction = true;
|
||||
if (Profiler::g_ProfileBlocks) {
|
||||
// CAUTION!!! push on stack regs you use, do your stuff, then pop
|
||||
PROFILER_VPUSH;
|
||||
// get end tic
|
||||
PROFILER_QUERY_PERFORMACE_COUNTER(&b.ticStop);
|
||||
// tic counter += (end tic - start tic)
|
||||
PROFILER_ADD_DIFF_LARGE_INTEGER(&b.ticCounter, &b.ticStop, &b.ticStart);
|
||||
PROFILER_VPOP;
|
||||
}
|
||||
}
|
||||
|
||||
// const GekkoOpInfo *info = GetOpInfo();
|
||||
// if (js.isLastInstruction)
|
||||
|
@ -18,6 +18,9 @@
|
||||
#define _JITCACHE_H
|
||||
|
||||
#include "../Gekko.h"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> // -> LARGE_INTEGER
|
||||
#endif
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
@ -52,6 +55,13 @@ namespace Jit64
|
||||
u32 codeSize;
|
||||
u32 originalSize;
|
||||
int runCount; // for profiling.
|
||||
#ifdef _WIN32
|
||||
// we don't really need to save start and stop
|
||||
// TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;)
|
||||
LARGE_INTEGER ticStart; // for profiling - time.
|
||||
LARGE_INTEGER ticStop; // for profiling - time.
|
||||
LARGE_INTEGER ticCounter; // for profiling - time.
|
||||
#endif
|
||||
const u8 *checkedEntry;
|
||||
bool invalid;
|
||||
int flags;
|
||||
|
@ -30,9 +30,9 @@ bool g_ProfileInstructions;
|
||||
|
||||
struct BlockStat
|
||||
{
|
||||
BlockStat(int bn, int c) : blockNum(bn), cost(c) {}
|
||||
BlockStat(int bn, u64 c) : blockNum(bn), cost(c) {}
|
||||
int blockNum;
|
||||
int cost;
|
||||
u64 cost;
|
||||
|
||||
bool operator <(const BlockStat &other) const {
|
||||
return cost > other.cost;
|
||||
@ -43,14 +43,25 @@ void WriteProfileResults(const char *filename) {
|
||||
std::vector<BlockStat> stats;
|
||||
stats.reserve(Jit64::GetNumBlocks());
|
||||
u64 cost_sum = 0;
|
||||
#ifdef _WIN32
|
||||
u64 timecost_sum = 0;
|
||||
LARGE_INTEGER countsPerSec;
|
||||
QueryPerformanceFrequency(&countsPerSec);
|
||||
#endif
|
||||
for (int i = 0; i < Jit64::GetNumBlocks(); i++)
|
||||
{
|
||||
const Jit64::JitBlock *block = Jit64::GetBlock(i);
|
||||
int cost = (block->originalSize / 4) * block->runCount; // rough heuristic. mem instructions should cost more.
|
||||
u64 cost = (block->originalSize / 4) * block->runCount; // rough heuristic. mem instructions should cost more.
|
||||
#ifdef _WIN32
|
||||
u64 timecost = block->ticCounter.QuadPart; // Indeed ;)
|
||||
#endif
|
||||
if (block->runCount >= 1) { // Todo: tweak.
|
||||
stats.push_back(BlockStat(i, cost));
|
||||
}
|
||||
cost_sum += cost;
|
||||
#ifdef _WIN32
|
||||
timecost_sum += timecost;
|
||||
#endif
|
||||
}
|
||||
|
||||
sort(stats.begin(), stats.end());
|
||||
@ -59,14 +70,21 @@ void WriteProfileResults(const char *filename) {
|
||||
PanicAlert("failed to open %s", filename);
|
||||
return;
|
||||
}
|
||||
fprintf(f, "Profile\n");
|
||||
fprintf(f, "origAddr\tblkName\tcost\ttimeCost\tpercent\ttimePercent\tOvAllinBlkTime(ms)\tblkCodeSize\n");
|
||||
for (unsigned int i = 0; i < stats.size(); i++)
|
||||
{
|
||||
const Jit64::JitBlock *block = Jit64::GetBlock(stats[i].blockNum);
|
||||
if (block) {
|
||||
std::string name = g_symbolDB.GetDescription(block->originalAddress);
|
||||
double percent = 100 * (double)stats[i].cost / (double)cost_sum;
|
||||
fprintf(f, "%08x - %s - %i (%f%%)\n", block->originalAddress, name.c_str(), stats[i].cost, percent);
|
||||
double percent = 100.0 * (double)stats[i].cost / (double)cost_sum;
|
||||
#ifdef _WIN32
|
||||
double timePercent = 100.0 * (double)block->ticCounter.QuadPart / (double)timecost_sum;
|
||||
fprintf(f, "%08x\t%s\t%llu\t%llu\t%llf\t%llf\t%lf\t%i\n",
|
||||
block->originalAddress, name.c_str(), stats[i].cost, block->ticCounter.QuadPart, percent, timePercent, (double)block->ticCounter.QuadPart*1000.0/(double)countsPerSec.QuadPart, block->codeSize);
|
||||
#else
|
||||
fprintf(f, "%08x\t%s\t%llu\t???\t%llf\t???\t???\t%i\n",
|
||||
block->originalAddress, name.c_str(), stats[i].cost, /*block->ticCounter.QuadPart,*/ percent, /*timePercent, (double)block->ticCounter.QuadPart*1000.0/(double)countsPerSec.QuadPart,*/ block->codeSize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
@ -19,6 +19,34 @@
|
||||
#ifndef _PROFILER_H
|
||||
#define _PROFILER_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PROFILER_QUERY_PERFORMACE_COUNTER(pt) \
|
||||
LEA(32, EAX, M(pt)); PUSH(EAX); \
|
||||
CALL(QueryPerformanceCounter)
|
||||
// TODO: r64 way
|
||||
// asm write : (u64) dt += t1-t0
|
||||
#define PROFILER_ADD_DIFF_LARGE_INTEGER(pdt, pt1, pt0) \
|
||||
MOV(32, R(EAX), M(pt1.LowPart)); \
|
||||
SUB(32, R(EAX), M(pt0.LowPart)); \
|
||||
MOV(32, R(ECX), M(pt1.HighPart)); \
|
||||
SBB(32, R(ECX), M(pt0.HighPart)); \
|
||||
ADD(32, R(EAX), M(pdt.LowPart)); \
|
||||
MOV(32, R(EDX), M(pdt.HighPart)); \
|
||||
ADC(32, R(EDX), R(ECX)); \
|
||||
MOV(32, M(pdt.LowPart), R(EAX)); \
|
||||
MOV(32, M(pdt.HighPart), R(EDX))
|
||||
|
||||
#define PROFILER_VPUSH PUSH(EAX);PUSH(ECX);PUSH(EDX)
|
||||
#define PROFILER_VPOP POP(EDX);POP(ECX);POP(EAX)
|
||||
#else
|
||||
// TODO
|
||||
#define PROFILER_QUERY_PERFORMACE_COUNTER(pt)
|
||||
#define PROFILER_ADD_DIFF_LARGE_INTEGER(pdt, pt1, pt0)
|
||||
#define PROFILER_VPUSH
|
||||
#define PROFILER_VPOP
|
||||
#endif
|
||||
|
||||
|
||||
namespace Profiler
|
||||
{
|
||||
extern bool g_ProfileBlocks;
|
||||
|
@ -223,8 +223,9 @@ void CMemoryView::OnErase(wxEraseEvent& event)
|
||||
void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
int fontSize = 8;
|
||||
wxRect rc = GetClientRect();
|
||||
wxFont font(7, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT);
|
||||
wxFont font(fontSize, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_LIGHT);
|
||||
dc.SetFont(font);
|
||||
struct branch
|
||||
{
|
||||
@ -254,7 +255,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
dc.SetPen(nullPen);
|
||||
dc.SetBrush(bgBrush);
|
||||
dc.DrawRectangle(0, 0, 16, rc.height);
|
||||
dc.DrawRectangle(0, 0, rc.width, 5);
|
||||
dc.DrawRectangle(0, 0, rc.width, 5+8);
|
||||
// TODO - clean up this freaking mess!!!!!
|
||||
int i;
|
||||
|
||||
@ -294,6 +295,10 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
dc.SetBrush(currentBrush);
|
||||
dc.SetTextForeground(_T("#600000"));
|
||||
dc.DrawText(temp, 17, rowY1);
|
||||
char mem[256] = {0};
|
||||
strcpy(mem, debugger->getRawMemoryString(address));
|
||||
dc.SetTextForeground(_T("#000080"));
|
||||
dc.DrawText(wxString::FromAscii(mem), 17+fontSize*(8), rowY1);
|
||||
dc.SetTextForeground(_T("#000000"));
|
||||
|
||||
if (debugger->isAlive())
|
||||
@ -347,7 +352,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
dc.SetTextForeground(_T("#000000"));
|
||||
}
|
||||
|
||||
dc.DrawText(wxString::FromAscii(dis2), 126, rowY1);
|
||||
dc.DrawText(wxString::FromAscii(dis2), 17+fontSize*(8+8+8), rowY1);
|
||||
}
|
||||
|
||||
if (strcmp(dis, "blr"))
|
||||
@ -359,7 +364,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
dc.SetTextForeground(_T("#8000FF"));
|
||||
}
|
||||
|
||||
dc.DrawText(wxString::FromAscii(dis), 70, rowY1);
|
||||
dc.DrawText(wxString::FromAscii(dis), 17+fontSize*(8+8), rowY1);
|
||||
|
||||
if (desc[0] == 0)
|
||||
{
|
||||
@ -372,7 +377,7 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
//UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
|
||||
if (strlen(desc))
|
||||
{
|
||||
dc.DrawText(wxString::FromAscii(desc), 235, rowY1);
|
||||
dc.DrawText(wxString::FromAscii(desc), 17+fontSize*(8+8+8+30), rowY1);
|
||||
}
|
||||
|
||||
if (debugger->isBreakpoint(address))
|
||||
|
@ -70,14 +70,15 @@ CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id,
|
||||
{
|
||||
wxBoxSizer* sizerBig = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* sizerRight = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
|
||||
// didn't see anything usefull in the left part
|
||||
//wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
DebugInterface* di = new PPCDebugInterface();
|
||||
|
||||
sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(90, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
|
||||
//sizerLeft->Add(symbols = new wxListBox(this, IDM_SYMBOLLIST, wxDefaultPosition, wxSize(20, 100), 0, NULL, wxLB_SORT), 1, wxEXPAND);
|
||||
memview = new CMemoryView(di, this, wxID_ANY);
|
||||
sizerBig->Add(sizerLeft, 2, wxEXPAND);
|
||||
sizerBig->Add(memview, 5, wxEXPAND);
|
||||
//sizerBig->Add(sizerLeft, 1, wxEXPAND);
|
||||
sizerBig->Add(memview, 20, wxEXPAND);
|
||||
sizerBig->Add(sizerRight, 0, wxEXPAND | wxALL, 3);
|
||||
sizerRight->Add(buttonGo = new wxButton(this, IDM_DEBUG_GO, _T("&Go")));
|
||||
sizerRight->Add(addrbox = new wxTextCtrl(this, IDM_ADDRBOX, _T("")));
|
||||
@ -85,8 +86,8 @@ CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id,
|
||||
|
||||
SetSizer(sizerBig);
|
||||
|
||||
sizerLeft->SetSizeHints(this);
|
||||
sizerLeft->Fit(this);
|
||||
//sizerLeft->SetSizeHints(this);
|
||||
//sizerLeft->Fit(this);
|
||||
sizerRight->SetSizeHints(this);
|
||||
sizerRight->Fit(this);
|
||||
sizerBig->SetSizeHints(this);
|
||||
|
Loading…
x
Reference in New Issue
Block a user