mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 01:29:41 +01:00
Merge pull request #5585 from unknownbrackets/perf
Improve performance when running tests / fix function replacement
This commit is contained in:
commit
c7953c4934
10 files changed
+101
-63
No files matched your search
@@ -172,13 +172,11 @@ void LogManager::LoadConfig(IniFile::Section *section) {
|
||||
}
|
||||
|
||||
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *format, va_list args) {
|
||||
std::lock_guard<std::mutex> lk(log_lock_);
|
||||
|
||||
char msg[MAX_MSGLEN * 2];
|
||||
LogChannel *log = log_[type];
|
||||
if (!log || !log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
|
||||
if (level > log->GetLevel() || !log->IsEnabled() || !log->HasListeners())
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> lk(log_lock_);
|
||||
static const char level_to_char[8] = "-NEWIDV";
|
||||
char formattedTime[13];
|
||||
Common::Timer::GetTimeFormatted(formattedTime);
|
||||
@@ -196,7 +194,8 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const
|
||||
if (fileshort != file)
|
||||
file = fileshort + 1;
|
||||
}
|
||||
|
||||
|
||||
char msg[MAX_MSGLEN * 2];
|
||||
char *msgPos = msg;
|
||||
if (hleCurrentThreadName != NULL) {
|
||||
msgPos += sprintf(msgPos, "%s %-12.12s %c[%s]: %s:%d ",
|
||||
@@ -228,7 +227,7 @@ void LogManager::Shutdown() {
|
||||
}
|
||||
|
||||
LogChannel::LogChannel(const char* shortName, const char* fullName, bool enable)
|
||||
: enable_(enable) {
|
||||
: enable_(enable), m_hasListeners(false) {
|
||||
strncpy(m_fullName, fullName, 128);
|
||||
strncpy(m_shortName, shortName, 32);
|
||||
#if defined(_DEBUG)
|
||||
@@ -242,11 +241,13 @@ LogChannel::LogChannel(const char* shortName, const char* fullName, bool enable)
|
||||
void LogChannel::AddListener(LogListener *listener) {
|
||||
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
||||
m_listeners.insert(listener);
|
||||
m_hasListeners = true;
|
||||
}
|
||||
|
||||
void LogChannel::RemoveListener(LogListener *listener) {
|
||||
std::lock_guard<std::mutex> lk(m_listeners_lock);
|
||||
m_listeners.erase(listener);
|
||||
m_hasListeners = !m_listeners.empty();
|
||||
}
|
||||
|
||||
void LogChannel::Trigger(LogTypes::LOG_LEVELS level, const char *msg) {
|
||||
|
||||
+2
-1
@@ -83,7 +83,7 @@ public:
|
||||
LogTypes::LOG_LEVELS GetLevel() const { return (LogTypes::LOG_LEVELS)level_; }
|
||||
|
||||
void SetLevel(LogTypes::LOG_LEVELS level) { level_ = level; }
|
||||
bool HasListeners() const { return !m_listeners.empty(); }
|
||||
bool HasListeners() const { return m_hasListeners; }
|
||||
|
||||
// Although not elegant, easy to set with a PopupMultiChoice...
|
||||
int level_;
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
char m_shortName[32];
|
||||
std::mutex m_listeners_lock;
|
||||
std::set<LogListener*> m_listeners;
|
||||
bool m_hasListeners;
|
||||
};
|
||||
|
||||
class ConsoleListener;
|
||||
|
||||
@@ -615,15 +615,21 @@ void SymbolMap::AssignFunctionIndices() {
|
||||
void SymbolMap::UpdateActiveSymbols() {
|
||||
// return; (slow in debug mode)
|
||||
lock_guard guard(lock_);
|
||||
std::map<int, u32> activeModuleIndexes;
|
||||
for (auto it = activeModuleEnds.begin(), end = activeModuleEnds.end(); it != end; ++it) {
|
||||
activeModuleIndexes[it->second.index] = it->second.start;
|
||||
}
|
||||
|
||||
activeFunctions.clear();
|
||||
activeLabels.clear();
|
||||
activeData.clear();
|
||||
|
||||
// On startup and shutdown, we can skip the rest. Tiny optimization.
|
||||
if (activeModuleEnds.empty() || (functions.empty() && labels.empty() && data.empty())) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<int, u32> activeModuleIndexes;
|
||||
for (auto it = activeModuleEnds.begin(), end = activeModuleEnds.end(); it != end; ++it) {
|
||||
activeModuleIndexes[it->second.index] = it->second.start;
|
||||
}
|
||||
|
||||
for (auto it = functions.begin(), end = functions.end(); it != end; ++it) {
|
||||
const auto mod = activeModuleIndexes.find(it->second.module);
|
||||
if (it->second.module == 0) {
|
||||
|
||||
@@ -337,7 +337,7 @@ skip:
|
||||
|
||||
for (u32 ahead = fromAddr; ahead < fromAddr + MAX_AHEAD_SCAN; ahead += 4) {
|
||||
MIPSOpcode aheadOp = Memory::Read_Instruction(ahead);
|
||||
u32 target = GetBranchTargetNoRA(ahead);
|
||||
u32 target = GetBranchTargetNoRA(ahead, aheadOp);
|
||||
if (target == INVALIDTARGET && ((aheadOp & 0xFC000000) == 0x08000000)) {
|
||||
target = GetJumpTarget(ahead);
|
||||
}
|
||||
@@ -358,7 +358,7 @@ skip:
|
||||
if (closestJumpbackAddr != INVALIDTARGET && furthestJumpbackAddr == INVALIDTARGET) {
|
||||
for (u32 behind = closestJumpbackTarget; behind < fromAddr; behind += 4) {
|
||||
MIPSOpcode behindOp = Memory::Read_Instruction(behind);
|
||||
u32 target = GetBranchTargetNoRA(behind);
|
||||
u32 target = GetBranchTargetNoRA(behind, behindOp);
|
||||
if (target == INVALIDTARGET && ((behindOp & 0xFC000000) == 0x08000000)) {
|
||||
target = GetJumpTarget(behind);
|
||||
}
|
||||
@@ -409,7 +409,7 @@ skip:
|
||||
}
|
||||
|
||||
MIPSOpcode op = Memory::Read_Instruction(addr);
|
||||
u32 target = GetBranchTargetNoRA(addr);
|
||||
u32 target = GetBranchTargetNoRA(addr, op);
|
||||
if (target != INVALIDTARGET) {
|
||||
isStraightLeaf = false;
|
||||
if (target > furthestBranch) {
|
||||
|
||||
@@ -67,6 +67,11 @@ namespace MIPSCodeUtils
|
||||
u32 GetBranchTargetNoRA(u32 addr)
|
||||
{
|
||||
MIPSOpcode op = Memory::Read_Instruction(addr);
|
||||
return GetBranchTargetNoRA(addr, op);
|
||||
}
|
||||
|
||||
u32 GetBranchTargetNoRA(u32 addr, MIPSOpcode op)
|
||||
{
|
||||
if (op != 0)
|
||||
{
|
||||
MIPSInfo info = MIPSGetInfo(op);
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace MIPSCodeUtils
|
||||
u32 GetBranchTarget(u32 addr);
|
||||
// Ignores bltzal/etc. instructions that change RA.
|
||||
u32 GetBranchTargetNoRA(u32 addr);
|
||||
u32 GetBranchTargetNoRA(u32 addr, MIPSOpcode op);
|
||||
u32 GetJumpTarget(u32 addr);
|
||||
u32 GetSureBranchTarget(u32 addr);
|
||||
bool IsVFPUBranch(MIPSOpcode op);
|
||||
|
||||
+52
-45
@@ -60,11 +60,14 @@ enum MipsEncoding
|
||||
Emu,
|
||||
Rese,
|
||||
NumEncodings,
|
||||
|
||||
Instruc = -1,
|
||||
Inval = -2,
|
||||
};
|
||||
|
||||
struct MIPSInstruction
|
||||
{
|
||||
int altEncoding;
|
||||
MipsEncoding altEncoding;
|
||||
const char *name;
|
||||
MIPSComp::MIPSCompileFunc compile;
|
||||
#ifndef FINAL
|
||||
@@ -75,16 +78,16 @@ struct MIPSInstruction
|
||||
MIPSInfo flags;
|
||||
};
|
||||
|
||||
#define INVALID {-2}
|
||||
#define INVALID {Inval}
|
||||
#define INVALID_X_8 INVALID,INVALID,INVALID,INVALID,INVALID,INVALID,INVALID,INVALID
|
||||
#define N(a) a
|
||||
|
||||
#ifndef FINAL
|
||||
#define ENCODING(a) {a}
|
||||
#define INSTR(name, comp, dis, inter, flags) {-1, N(name), comp, dis, inter, MIPSInfo(flags)}
|
||||
#define INSTR(name, comp, dis, inter, flags) {Instruc, N(name), comp, dis, inter, MIPSInfo(flags)}
|
||||
#else
|
||||
#define ENCODING(a) {a}
|
||||
#define INSTR(name, comp, dis, inter, flags) {-1, comp, inter, flags}
|
||||
#define INSTR(name, comp, dis, inter, flags) {Instruc, comp, inter, flags}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -816,36 +819,44 @@ const MIPSInstruction tableEMU[4] = {
|
||||
INVALID,
|
||||
};
|
||||
|
||||
const int encodingBits[NumEncodings][2] =
|
||||
{
|
||||
{26, 6}, //IMME
|
||||
{0, 6}, //Special
|
||||
{0, 6}, //special2
|
||||
{0, 6}, //special3
|
||||
{16, 5}, //RegImm
|
||||
{21, 5}, //Cop0
|
||||
{0, 6}, //Cop0CO
|
||||
{21, 5}, //Cop1
|
||||
{16, 5}, //Cop1BC
|
||||
{0, 6}, //Cop1S
|
||||
{0, 6}, //Cop1W
|
||||
{21, 5}, //Cop2
|
||||
{16, 2}, //Cop2BC2
|
||||
{0, 0}, //Cop2Rese
|
||||
{23, 3}, //VFPU0
|
||||
{23, 3}, //VFPU1
|
||||
{23, 3}, //VFPU3
|
||||
{21, 5}, //VFPU4Jump
|
||||
{16, 5}, //VFPU7
|
||||
{16, 5}, //VFPU4
|
||||
{23, 3}, //VFPU5
|
||||
{21, 5}, //VFPU6
|
||||
{16, 4}, //VFPUMatrix1
|
||||
{16, 5}, //VFPU9
|
||||
{6, 5}, //ALLEGREX0
|
||||
{24, 2}, //EMUHACK
|
||||
struct EncodingBitsInfo {
|
||||
EncodingBitsInfo(u8 shift_, u8 maskBits_) : shift(shift_) {
|
||||
mask = (1 << maskBits_) - 1;
|
||||
}
|
||||
u8 shift;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
const EncodingBitsInfo encodingBits[NumEncodings] =
|
||||
{
|
||||
EncodingBitsInfo(26, 6), //IMME
|
||||
EncodingBitsInfo(0, 6), //Special
|
||||
EncodingBitsInfo(0, 6), //special2
|
||||
EncodingBitsInfo(0, 6), //special3
|
||||
EncodingBitsInfo(16, 5), //RegImm
|
||||
EncodingBitsInfo(21, 5), //Cop0
|
||||
EncodingBitsInfo(0, 6), //Cop0CO
|
||||
EncodingBitsInfo(21, 5), //Cop1
|
||||
EncodingBitsInfo(16, 5), //Cop1BC
|
||||
EncodingBitsInfo(0, 6), //Cop1S
|
||||
EncodingBitsInfo(0, 6), //Cop1W
|
||||
EncodingBitsInfo(21, 5), //Cop2
|
||||
EncodingBitsInfo(16, 2), //Cop2BC2
|
||||
EncodingBitsInfo(0, 0), //Cop2Rese
|
||||
EncodingBitsInfo(23, 3), //VFPU0
|
||||
EncodingBitsInfo(23, 3), //VFPU1
|
||||
EncodingBitsInfo(23, 3), //VFPU3
|
||||
EncodingBitsInfo(21, 5), //VFPU4Jump
|
||||
EncodingBitsInfo(16, 5), //VFPU7
|
||||
EncodingBitsInfo(16, 5), //VFPU4
|
||||
EncodingBitsInfo(23, 3), //VFPU5
|
||||
EncodingBitsInfo(21, 5), //VFPU6
|
||||
EncodingBitsInfo(16, 4), //VFPUMatrix1
|
||||
EncodingBitsInfo(16, 5), //VFPU9
|
||||
EncodingBitsInfo(6, 5), //ALLEGREX0
|
||||
EncodingBitsInfo(24, 2), //EMUHACK
|
||||
EncodingBitsInfo(0, 0), //Rese
|
||||
};
|
||||
|
||||
const MIPSInstruction *mipsTables[NumEncodings] =
|
||||
{
|
||||
@@ -874,7 +885,8 @@ const MIPSInstruction *mipsTables[NumEncodings] =
|
||||
tableVFPUMatrixSet1,
|
||||
tableVFPU9,
|
||||
tableALLEGREX0,
|
||||
tableEMU
|
||||
tableEMU,
|
||||
0,
|
||||
};
|
||||
|
||||
|
||||
@@ -896,23 +908,18 @@ const MIPSInstruction *MIPSGetInstruction(MIPSOpcode op)
|
||||
{
|
||||
MipsEncoding encoding = Imme;
|
||||
const MIPSInstruction *instr = &tableImmediate[op>>26];
|
||||
while (instr->altEncoding != -1)
|
||||
while (instr->altEncoding != Instruc)
|
||||
{
|
||||
const MIPSInstruction *table = mipsTables[encoding];
|
||||
int mask = ((1<<encodingBits[encoding][1])-1);
|
||||
int shift = encodingBits[encoding][0];
|
||||
int subop = (op >> shift) & mask;
|
||||
instr = &table[subop];
|
||||
if (encoding == Rese)
|
||||
return 0; //invalid instruction
|
||||
if (!instr)
|
||||
return 0;
|
||||
if (instr->altEncoding == -2)
|
||||
if (instr->altEncoding == Inval)
|
||||
{
|
||||
//ERROR_LOG(CPU, "Invalid instruction %08x in table %i, entry %i", op, (int)encoding, subop);
|
||||
return 0; //invalid instruction
|
||||
}
|
||||
encoding = (MipsEncoding)instr->altEncoding;
|
||||
encoding = instr->altEncoding;
|
||||
|
||||
const MIPSInstruction *table = mipsTables[encoding];
|
||||
const u32 subop = (op >> encodingBits[encoding].shift) & encodingBits[encoding].mask;
|
||||
instr = &table[subop];
|
||||
}
|
||||
//alright, we have a valid MIPS instruction!
|
||||
return instr;
|
||||
|
||||
+17
-2
@@ -176,9 +176,12 @@ void Clear()
|
||||
memset(m_pVRAM, 0, VRAM_SIZE);
|
||||
}
|
||||
|
||||
Opcode Read_Instruction(u32 address, bool resolveReplacements)
|
||||
static Opcode Read_Instruction(u32 address, bool resolveReplacements, Opcode inst)
|
||||
{
|
||||
Opcode inst = Opcode(Read_U32(address));
|
||||
if (!MIPS_IS_EMUHACK(inst.encoding)) {
|
||||
return inst;
|
||||
}
|
||||
|
||||
if (MIPS_IS_RUNBLOCK(inst.encoding) && MIPSComp::jit) {
|
||||
JitBlockCache *bc = MIPSComp::jit->GetBlockCache();
|
||||
int block_num = bc->GetBlockNumberFromEmuHackOp(inst, true);
|
||||
@@ -218,6 +221,18 @@ Opcode Read_Instruction(u32 address, bool resolveReplacements)
|
||||
}
|
||||
}
|
||||
|
||||
Opcode Read_Instruction(u32 address, bool resolveReplacements)
|
||||
{
|
||||
Opcode inst = Opcode(Read_U32(address));
|
||||
return Read_Instruction(address, resolveReplacements, inst);
|
||||
}
|
||||
|
||||
Opcode ReadUnchecked_Instruction(u32 address, bool resolveReplacements)
|
||||
{
|
||||
Opcode inst = Opcode(ReadUnchecked_U32(address));
|
||||
return Read_Instruction(address, resolveReplacements, inst);
|
||||
}
|
||||
|
||||
Opcode Read_Opcode_JIT(u32 address)
|
||||
{
|
||||
Opcode inst = Opcode(Read_U32(address));
|
||||
|
||||
@@ -140,6 +140,7 @@ void Write_Opcode_JIT(const u32 _Address, const Opcode _Value);
|
||||
|
||||
// Should be used by analyzers, disassemblers etc. Does resolve replacements.
|
||||
Opcode Read_Instruction(const u32 _Address, bool resolveReplacements = false);
|
||||
Opcode ReadUnchecked_Instruction(const u32 _Address, bool resolveReplacements = false);
|
||||
|
||||
u8 Read_U8(const u32 _Address);
|
||||
u16 Read_U16(const u32 _Address);
|
||||
|
||||
+3
-2
@@ -17,7 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Core/Host.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/Debugger/SymbolMap.h"
|
||||
|
||||
#define HEADLESSHOST_CLASS HeadlessHost
|
||||
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
virtual void BootDone() {}
|
||||
|
||||
virtual bool IsDebuggingEnabled() {return false;}
|
||||
virtual bool AttemptLoadSymbolMap() {return false;}
|
||||
virtual bool AttemptLoadSymbolMap() { symbolMap.Clear(); return false; }
|
||||
|
||||
virtual bool ShouldSkipUI() { return true; }
|
||||
|
||||
|
||||
Reference in new issue
Block a user