From f14f2efa793468a1d06675fcd1a61ddc61737d5a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Mar 2018 13:33:48 -0700 Subject: [PATCH] Module: Hash functions only once during loading. This fixes the loading speed regression from #10501. --- Core/HLE/sceKernelModule.cpp | 17 +++++++++++------ Core/MIPS/MIPSAnalyst.cpp | 9 +++++++-- Core/MIPS/MIPSAnalyst.h | 3 ++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index ff9826ebe9..63c2d12927 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1268,7 +1268,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd scan = g_Config.bFuncReplacements; #endif - bool gotSymbols = scan && reader.LoadSymbols(); + bool insertSymbols = scan && !reader.LoadSymbols(); std::vector codeSections = reader.GetCodeSections(); for (SectionID id : codeSections) { u32 start = reader.GetSectionAddr(id); @@ -1280,8 +1280,9 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd if (end > module->textEnd) module->textEnd = end; - if (scan) - MIPSAnalyst::ScanForFunctions(start, end, !gotSymbols); + if (scan) { + MIPSAnalyst::ScanForFunctions(start, end, insertSymbols); + } } // Some games don't have any sections at all. @@ -1290,14 +1291,18 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd u32 scanEnd = module->textEnd; // Skip the exports and imports sections, they're not code. if (scanEnd >= std::min(modinfo->libent, modinfo->libstub)) { - MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, !gotSymbols); + MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, insertSymbols); scanStart = std::min(modinfo->libentend, modinfo->libstubend); } if (scanEnd >= std::max(modinfo->libent, modinfo->libstub)) { - MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, !gotSymbols); + MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, insertSymbols); scanStart = std::max(modinfo->libentend, modinfo->libstubend); } - MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, !gotSymbols); + MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, insertSymbols); + } + + if (scan) { + MIPSAnalyst::FinalizeScan(insertSymbols); } } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 98d07490ab..b72120ca06 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -878,13 +878,16 @@ namespace MIPSAnalyst { for (auto iter = functions.begin(), end = functions.end(); iter != end; iter++) { AnalyzedFunction &f = *iter; + if (Memory::IsValidRange(f.start, f.end - f.start + 4)) { + continue; + } // This is unfortunate. In case of emuhacks or relocs, we have to make a copy. buffer.resize((f.end - f.start + 4) / 4); size_t pos = 0; for (u32 addr = f.start; addr <= f.end; addr += 4) { u32 validbits = 0xFFFFFFFF; - MIPSOpcode instr = Memory::Read_Instruction(addr, true); + MIPSOpcode instr = Memory::ReadUnchecked_Instruction(addr, true); if (MIPS_IS_EMUHACK(instr)) { f.hasHash = false; goto skip; @@ -1015,7 +1018,7 @@ skip: return furthestJumpbackAddr; } - void ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols) { + void ScanForFunctions(u32 startAddr, u32 endAddr, bool &insertSymbols) { std::lock_guard guard(functions_lock); AnalyzedFunction currentFunction = {startAddr}; @@ -1163,7 +1166,9 @@ skip: g_symbolMap->AddFunction(DefaultFunctionName(temp, iter->start), iter->start, iter->end - iter->start + 4); } } + } + void FinalizeScan(bool insertSymbols) { HashFunctions(); std::string hashMapFilename = GetSysDirectory(DIRECTORY_SYSTEM) + "knownfuncs.ini"; diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index 9d6683c48a..030ff0e95c 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -105,7 +105,8 @@ namespace MIPSAnalyst // If we have loaded symbols from the elf, we'll register functions as they are touched // so that we don't just dump them all in the cache. void RegisterFunction(u32 startAddr, u32 size, const char *name); - void ScanForFunctions(u32 startAddr, u32 endAddr, bool insertSymbols); + void ScanForFunctions(u32 startAddr, u32 endAddr, bool &insertSymbols); + void FinalizeScan(bool insertSymbols); void ForgetFunctions(u32 startAddr, u32 endAddr); void PrecompileFunctions(); void PrecompileFunction(u32 startAddr, u32 length);