diff --git a/Core/Config.cpp b/Core/Config.cpp index 1c32021949..d010fe6466 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -391,7 +391,6 @@ static const ConfigSetting cpuSettings[] = { ConfigSetting("FunctionReplacements", &g_Config.bFuncReplacements, true, CfgFlag::PER_GAME | CfgFlag::REPORT), ConfigSetting("HideSlowWarnings", &g_Config.bHideSlowWarnings, false, CfgFlag::DEFAULT), ConfigSetting("HideStateWarnings", &g_Config.bHideStateWarnings, false, CfgFlag::DEFAULT), - ConfigSetting("PreloadFunctions", &g_Config.bPreloadFunctions, false, CfgFlag::PER_GAME), ConfigSetting("JitDisableFlags", &g_Config.uJitDisableFlags, (uint32_t)0, CfgFlag::PER_GAME), ConfigSetting("CPUSpeed", &g_Config.iLockedCPUSpeed, 0, CfgFlag::PER_GAME | CfgFlag::REPORT), }; diff --git a/Core/Config.h b/Core/Config.h index 40e6efe121..8a9f5cf097 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -115,7 +115,6 @@ public: bool bFuncReplacements; bool bHideSlowWarnings; bool bHideStateWarnings; - bool bPreloadFunctions; uint32_t uJitDisableFlags; bool bDisableHTTPS; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 84a17565f1..577e0bb913 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -661,9 +661,6 @@ void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting, const char // TODO: There's some double lookup going on here (we already did the lookup in GetHLEFunc above). WriteHLESyscall(func.moduleName, func.nid, func.stubAddr); currentMIPS->InvalidateICache(func.stubAddr, 8); - if (g_Config.bPreloadFunctions) { - MIPSAnalyst::PrecompileFunction(func.stubAddr, 8); - } return; } @@ -682,9 +679,6 @@ void ImportFuncSymbol(const FuncSymbolImport &func, bool reimporting, const char } WriteFuncStub(func.stubAddr, it->symAddr); currentMIPS->InvalidateICache(func.stubAddr, 8); - if (g_Config.bPreloadFunctions) { - MIPSAnalyst::PrecompileFunction(func.stubAddr, 8); - } return; } } @@ -725,9 +719,6 @@ void ExportFuncSymbol(const FuncSymbolExport &func) { INFO_LOG(Log::Loader, "Resolving function %s/%08x", func.moduleName, func.nid); WriteFuncStub(it->stubAddr, func.symAddr); currentMIPS->InvalidateICache(it->stubAddr, 8); - if (g_Config.bPreloadFunctions) { - MIPSAnalyst::PrecompileFunction(it->stubAddr, 8); - } } } } @@ -1543,8 +1534,6 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load // use module_start_func instead of entry_addr if entry_addr is 0 if (module->nm.entry_addr == 0) module->nm.entry_addr = module->nm.module_start_func; - - MIPSAnalyst::PrecompileFunctions(); } else { module->nm.entry_addr = -1; } diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 35f2eb67c0..b2eb4d1011 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -747,7 +747,6 @@ static void __KernelWriteFakeSysCall(u32 nid, u32 *ptr, u32 &pos) *ptr = pos; pos += 8; WriteHLESyscall("FakeSysCalls", nid, *ptr); - MIPSAnalyst::PrecompileFunction(*ptr, 8); } u32 HLEMipsCallReturnAddress() { diff --git a/Core/MIPS/ARM64/Arm64IRJit.cpp b/Core/MIPS/ARM64/Arm64IRJit.cpp index 4e4b6c24cb..f9b206fffc 100644 --- a/Core/MIPS/ARM64/Arm64IRJit.cpp +++ b/Core/MIPS/ARM64/Arm64IRJit.cpp @@ -65,7 +65,7 @@ static void NoBlockExits() { _assert_msg_(false, "Never exited block, invalid IR?"); } -bool Arm64JitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) { +bool Arm64JitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num) { if (GetSpaceLeft() < 0x800) return false; diff --git a/Core/MIPS/ARM64/Arm64IRJit.h b/Core/MIPS/ARM64/Arm64IRJit.h index c2992f3520..66053f42ae 100644 --- a/Core/MIPS/ARM64/Arm64IRJit.h +++ b/Core/MIPS/ARM64/Arm64IRJit.h @@ -40,7 +40,7 @@ public: bool DescribeCodePtr(const u8 *ptr, std::string &name) const override; void GenerateFixedCode(MIPSState *mipsState) override; - bool CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) override; + bool CompileBlock(IRBlockCache *irBlockCache, int block_num) override; void ClearAllBlocks() override; void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override; diff --git a/Core/MIPS/IR/IRCompBranch.cpp b/Core/MIPS/IR/IRCompBranch.cpp index e9c6afca82..3b7ff163a5 100644 --- a/Core/MIPS/IR/IRCompBranch.cpp +++ b/Core/MIPS/IR/IRCompBranch.cpp @@ -334,11 +334,7 @@ void IRFrontend::Comp_Jump(MIPSOpcode op) { // Might be a stubbed address or something? if (!Memory::IsValidAddress(targetAddr)) { // If preloading, flush - this block will likely be fixed later. - if (js.preloading) { - js.cancel = true; - } else { - ERROR_LOG(Log::JIT, "Jump to invalid address: %08x", targetAddr); - } + ERROR_LOG(Log::JIT, "Jump to invalid address: %08x", targetAddr); // TODO: Mark this block dirty or something? May be indication it will be changed by imports. // Continue so the block gets completed and crashes properly. } diff --git a/Core/MIPS/IR/IRFrontend.cpp b/Core/MIPS/IR/IRFrontend.cpp index 4300036f75..69072fe5e3 100644 --- a/Core/MIPS/IR/IRFrontend.cpp +++ b/Core/MIPS/IR/IRFrontend.cpp @@ -239,9 +239,8 @@ MIPSOpcode IRFrontend::GetOffsetInstruction(int offset) { return Memory::Read_Instruction(GetCompilerPC() + 4 * offset); } -void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &mipsBytes, bool preload) { +void IRFrontend::DoJit(u32 em_address, std::vector &instructions, u32 &mipsBytes) { js.cancel = false; - js.preloading = preload; js.blockStart = em_address; js.compilerPC = em_address; js.lastContinuedPC = 0; diff --git a/Core/MIPS/IR/IRFrontend.h b/Core/MIPS/IR/IRFrontend.h index 4ae7b4a095..58262831b4 100644 --- a/Core/MIPS/IR/IRFrontend.h +++ b/Core/MIPS/IR/IRFrontend.h @@ -89,7 +89,7 @@ public: void DoState(PointerWrap &p); bool CheckRounding(u32 blockAddress); // returns true if we need a do-over - void DoJit(u32 em_address, std::vector &instructions, u32 &mipsBytes, bool preload); + void DoJit(u32 em_address, std::vector &instructions, u32 &mipsBytes); void EatPrefix() override { js.EatPrefix(); diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 65d6a87de6..633b3282f8 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -116,48 +116,28 @@ void IRJit::Compile(u32 em_address) { PROFILE_THIS_SCOPE("jitc"); - if (g_Config.bPreloadFunctions) { - // Look to see if we've preloaded this block. - int block_num = blocks_.FindPreloadBlock(em_address); - if (block_num != -1) { - IRBlock *block = blocks_.GetBlock(block_num); - // Okay, let's link and finalize the block now. - int cookie = compileToNative_ ? block->GetNativeOffset() : block->GetIRArenaOffset(); - block->Finalize(cookie); - if (block->IsValid()) { - // Success, we're done. - FinalizeNativeBlock(&blocks_, block_num); - return; - } - } - } - std::vector instructions; u32 mipsBytes; - if (!CompileBlock(em_address, instructions, mipsBytes, false)) { + if (!CompileBlock(em_address, instructions, mipsBytes)) { // Ran out of block numbers - need to reset. ERROR_LOG(Log::JIT, "Ran out of block numbers, clearing cache"); ClearCache(); - CompileBlock(em_address, instructions, mipsBytes, false); + CompileBlock(em_address, instructions, mipsBytes); } if (frontend_.CheckRounding(em_address)) { // Our assumptions are all wrong so it's clean-slate time. ClearCache(); - CompileBlock(em_address, instructions, mipsBytes, false); + CompileBlock(em_address, instructions, mipsBytes); } } // WARNING! This can be called from IRInterpret / the JIT, through the function preload stuff! -bool IRJit::CompileBlock(u32 em_address, std::vector &instructions, u32 &mipsBytes, bool preload) { +bool IRJit::CompileBlock(u32 em_address, std::vector &instructions, u32 &mipsBytes) { _dbg_assert_(compilerEnabled_); - frontend_.DoJit(em_address, instructions, mipsBytes, preload); - if (instructions.empty()) { - _dbg_assert_(preload); - // We return true when preloading so it doesn't abort. - return preload; - } + frontend_.DoJit(em_address, instructions, mipsBytes); + _dbg_assert_(!instructions.empty()); int block_num = blocks_.AllocateBlock(em_address, mipsBytes, instructions); if ((block_num & ~MIPS_EMUHACK_VALUE_MASK) != 0) { @@ -167,13 +147,13 @@ bool IRJit::CompileBlock(u32 em_address, std::vector &instructions, u32 } IRBlock *b = blocks_.GetBlock(block_num); - if (preload || mipsTracer.tracing_enabled) { + if (mipsTracer.tracing_enabled) { // Hash, then only update page stats, don't link yet. // TODO: Should we always hash? Then we can reuse blocks. b->UpdateHash(); } - if (!CompileNativeBlock(&blocks_, block_num, preload)) + if (!CompileNativeBlock(&blocks_, block_num)) return false; if (mipsTracer.tracing_enabled) { @@ -181,88 +161,11 @@ bool IRJit::CompileBlock(u32 em_address, std::vector &instructions, u32 } // Updates stats, also patches the first MIPS instruction into an emuhack if 'preload == false' - blocks_.FinalizeBlock(block_num, preload); - if (!preload) - FinalizeNativeBlock(&blocks_, block_num); + blocks_.FinalizeBlock(block_num); + FinalizeNativeBlock(&blocks_, block_num); return true; } -void IRJit::CompileFunction(u32 start_address, u32 length) { - _dbg_assert_(compilerEnabled_); - - PROFILE_THIS_SCOPE("jitc"); - - // Note: we don't actually write emuhacks yet, so we can validate hashes. - // This way, if the game changes the code afterward, we'll catch even without icache invalidation. - - // We may go up and down from branches, so track all block starts done here. - std::set doneAddresses; - std::vector pendingAddresses; - pendingAddresses.reserve(16); - pendingAddresses.push_back(start_address); - while (!pendingAddresses.empty()) { - u32 em_address = pendingAddresses.back(); - pendingAddresses.pop_back(); - - // To be safe, also check if a real block is there. This can be a runtime module load. - u32 inst = Memory::ReadUnchecked_U32(em_address); - if (MIPS_IS_RUNBLOCK(inst) || doneAddresses.find(em_address) != doneAddresses.end()) { - // Already compiled this address. - continue; - } - - std::vector instructions; - u32 mipsBytes; - if (!CompileBlock(em_address, instructions, mipsBytes, true)) { - // Ran out of block numbers - let's hope there's no more code it needs to run. - // Will flush when actually compiling. - ERROR_LOG(Log::JIT, "Ran out of block numbers while compiling function"); - return; - } - - doneAddresses.insert(em_address); - - for (const IRInst &inst : instructions) { - u32 exit = 0; - - switch (inst.op) { - case IROp::ExitToConst: - case IROp::ExitToConstIfEq: - case IROp::ExitToConstIfNeq: - case IROp::ExitToConstIfGtZ: - case IROp::ExitToConstIfGeZ: - case IROp::ExitToConstIfLtZ: - case IROp::ExitToConstIfLeZ: - case IROp::ExitToConstIfFpTrue: - case IROp::ExitToConstIfFpFalse: - exit = inst.constant; - break; - - case IROp::ExitToPC: - case IROp::Break: - // Don't add any, we'll do block end anyway (for jal, etc.) - exit = 0; - break; - - default: - exit = 0; - break; - } - - // Only follow jumps internal to the function. - if (exit != 0 && exit >= start_address && exit < start_address + length) { - // Even if it's a duplicate, we check at loop start. - pendingAddresses.push_back(exit); - } - } - - // Also include after the block for jal returns. - if (em_address + mipsBytes < start_address + length) { - pendingAddresses.push_back(em_address + mipsBytes); - } - } -} - void IRJit::RunLoopUntil(u64 globalticks) { PROFILE_THIS_SCOPE("jit"); @@ -430,13 +333,11 @@ std::vector IRBlockCache::FindInvalidatedBlockNumbers(u32 address, u32 leng return found; } -void IRBlockCache::FinalizeBlock(int blockIndex, bool preload) { +void IRBlockCache::FinalizeBlock(int blockIndex) { // TODO: What's different about preload blocks? IRBlock &block = blocks_[blockIndex]; - if (!preload) { - int cookie = compileToNative_ ? block.GetNativeOffset() : block.GetIRArenaOffset(); - block.Finalize(cookie); - } + int cookie = compileToNative_ ? block.GetNativeOffset() : block.GetIRArenaOffset(); + block.Finalize(cookie); u32 startAddr, size; block.GetRange(&startAddr, &size); diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index 063bb40c9c..4b3e0efac5 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -122,7 +122,7 @@ public: void Clear(); std::vector FindInvalidatedBlockNumbers(u32 address, u32 length); - void FinalizeBlock(int blockNum, bool preload = false); + void FinalizeBlock(int blockNum); int GetNumBlocks() const override { return (int)blocks_.size(); } int AllocateBlock(int emAddr, u32 origSize, const std::vector &inst); IRBlock *GetBlock(int blockNum) { @@ -212,7 +212,6 @@ public: void RunLoopUntil(u64 globalticks) override; void Compile(u32 em_address) override; // Compiles a block at current MIPS PC - void CompileFunction(u32 start_address, u32 length) override; bool DescribeCodePtr(const u8 *ptr, std::string &name) override; // Not using a regular block cache. @@ -238,8 +237,8 @@ public: void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override; protected: - bool CompileBlock(u32 em_address, std::vector &instructions, u32 &mipsBytes, bool preload); - virtual bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num, bool preload) { return true; } + bool CompileBlock(u32 em_address, std::vector &instructions, u32 &mipsBytes); + virtual bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num) { return true; } virtual void FinalizeNativeBlock(IRBlockCache *irBlockCache, int block_num) {} bool compileToNative_; diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index 229bd88106..0bed8b1794 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -507,8 +507,8 @@ void IRNativeJit::Init(IRNativeBackend &backend) { } } -bool IRNativeJit::CompileNativeBlock(IRBlockCache *irblockCache, int block_num, bool preload) { - return backend_->CompileBlock(irblockCache, block_num, preload); +bool IRNativeJit::CompileNativeBlock(IRBlockCache *irblockCache, int block_num) { + return backend_->CompileBlock(irblockCache, block_num); } void IRNativeJit::FinalizeNativeBlock(IRBlockCache *irblockCache, int block_num) { diff --git a/Core/MIPS/IR/IRNativeCommon.h b/Core/MIPS/IR/IRNativeCommon.h index a49ab07343..a432fa1a1d 100644 --- a/Core/MIPS/IR/IRNativeCommon.h +++ b/Core/MIPS/IR/IRNativeCommon.h @@ -71,7 +71,7 @@ public: int OffsetFromCodePtr(const u8 *ptr); virtual void GenerateFixedCode(MIPSState *mipsState) = 0; - virtual bool CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) = 0; + virtual bool CompileBlock(IRBlockCache *irBlockCache, int block_num) = 0; virtual void ClearAllBlocks() = 0; virtual void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) = 0; void FinalizeBlock(IRBlockCache *irBlockCache, int block_num, const JitOptions &jo); @@ -198,7 +198,7 @@ public: protected: void Init(IRNativeBackend &backend); - bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num, bool preload) override; + bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num) override; void FinalizeNativeBlock(IRBlockCache *irBlockCache, int block_num) override; IRNativeBackend *backend_ = nullptr; diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index 2698e026ec..7de9ddb2e1 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -136,7 +136,6 @@ namespace MIPSComp { virtual void DoState(PointerWrap &p) = 0; virtual void RunLoopUntil(u64 globalticks) = 0; virtual void Compile(u32 em_address) = 0; - virtual void CompileFunction(u32 start_address, u32 length) { } virtual void ClearCache() = 0; virtual void UpdateFCR31() = 0; virtual MIPSOpcode GetOriginalOp(MIPSOpcode op) = 0; diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index ef90409e36..3161a81d13 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -68,7 +68,6 @@ namespace MIPSComp { int numInstructions; bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block bool hadBreakpoints; - bool preloading = false; JitBlock *curBlock; u8 hasSetRounding = 0; diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 4f456c5beb..77562427ad 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -906,33 +906,6 @@ skip: } } - void PrecompileFunction(u32 startAddr, u32 length) { - // Direct calls to this ignore the bPreloadFunctions flag, since it's just for stubs. - std::lock_guard guard(MIPSComp::jitLock); - if (MIPSComp::jit) { - MIPSComp::jit->CompileFunction(startAddr, length); - } - } - - void PrecompileFunctions() { - if (!g_Config.bPreloadFunctions) { - return; - } - std::lock_guard guard(functions_lock); - - // TODO: Load from cache file if available instead. - - double st = time_now_d(); - for (auto iter = functions.begin(), end = functions.end(); iter != end; iter++) { - const AnalyzedFunction &f = *iter; - - PrecompileFunction(f.start, f.end - f.start + 4); - } - double et = time_now_d(); - - NOTICE_LOG(Log::JIT, "Precompiled %d MIPS functions in %0.2f milliseconds", (int)functions.size(), (et - st) * 1000.0); - } - static const char *DefaultFunctionName(char buffer[256], u32 startAddr) { snprintf(buffer, 256, "z_un_%08x", startAddr); return buffer; diff --git a/Core/MIPS/MIPSAnalyst.h b/Core/MIPS/MIPSAnalyst.h index 98b227eaf7..2c8ed6df6f 100644 --- a/Core/MIPS/MIPSAnalyst.h +++ b/Core/MIPS/MIPSAnalyst.h @@ -97,7 +97,6 @@ namespace MIPSAnalyst { void Reset(); - bool IsRegisterUsed(u32 reg, u32 addr); // This will not only create a database of "AnalyzedFunction" structs, it also // will insert all the functions it finds into the symbol map, if insertSymbols is true. @@ -108,8 +107,6 @@ namespace MIPSAnalyst { bool 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); void SetHashMapFilename(const std::string& filename = ""); void LoadBuiltinHashMap(); diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index 87b1a14dcc..2fd9a34523 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -56,7 +56,7 @@ static void NoBlockExits() { _assert_msg_(false, "Never exited block, invalid IR?"); } -bool RiscVJitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) { +bool RiscVJitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num) { if (GetSpaceLeft() < 0x800) return false; diff --git a/Core/MIPS/RiscV/RiscVJit.h b/Core/MIPS/RiscV/RiscVJit.h index 2bc0b1ec51..ba4eb383ef 100644 --- a/Core/MIPS/RiscV/RiscVJit.h +++ b/Core/MIPS/RiscV/RiscVJit.h @@ -36,7 +36,7 @@ public: bool DescribeCodePtr(const u8 *ptr, std::string &name) const override; void GenerateFixedCode(MIPSState *mipsState) override; - bool CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) override; + bool CompileBlock(IRBlockCache *irBlockCache, int block_num) override; void ClearAllBlocks() override; void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override; diff --git a/Core/MIPS/x86/X64IRJit.cpp b/Core/MIPS/x86/X64IRJit.cpp index 5bb0e011b3..fbfcf9ff9c 100644 --- a/Core/MIPS/x86/X64IRJit.cpp +++ b/Core/MIPS/x86/X64IRJit.cpp @@ -55,7 +55,7 @@ static void NoBlockExits() { _assert_msg_(false, "Never exited block, invalid IR?"); } -bool X64JitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) { +bool X64JitBackend::CompileBlock(IRBlockCache *irBlockCache, int block_num) { if (GetSpaceLeft() < 0x800) return false; diff --git a/Core/MIPS/x86/X64IRJit.h b/Core/MIPS/x86/X64IRJit.h index e80a8544d2..fe44eed3ad 100644 --- a/Core/MIPS/x86/X64IRJit.h +++ b/Core/MIPS/x86/X64IRJit.h @@ -52,7 +52,7 @@ public: bool DescribeCodePtr(const u8 *ptr, std::string &name) const override; void GenerateFixedCode(MIPSState *mipsState) override; - bool CompileBlock(IRBlockCache *irBlockCache, int block_num, bool preload) override; + bool CompileBlock(IRBlockCache *irBlockCache, int block_num) override; void ClearAllBlocks() override; void InvalidateBlock(IRBlockCache *irBlockCache, int block_num) override;