From 9b29fe8aede15f4e36915284927d11e24dab3df0 Mon Sep 17 00:00:00 2001 From: Fiora Date: Sat, 4 Oct 2014 21:28:21 -0700 Subject: [PATCH] WIP: don't let the backpatcher hit the same location twice If a location is hit by the backpatcher, don't fastmem it when recompiling the block unless the block has actually been invalidated. --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 2 ++ .../Core/PowerPC/JitCommon/JitBackpatch.cpp | 28 +++++++++---------- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 2 ++ .../Core/Core/PowerPC/JitCommon/JitCache.cpp | 13 ++++++--- .../Core/Core/PowerPC/JitCommon/Jit_Util.cpp | 13 +++++---- Source/Core/Core/PowerPC/JitCommon/Jit_Util.h | 3 -- 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index de051b4bf9..aad2885c86 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -221,6 +221,8 @@ void Jit64::ClearCache() { blocks.Clear(); trampolines.ClearCodeSpace(); + jit->js.pcAtLoc.clear(); + jit->js.registersInUseAtLoc.clear(); farcode.ClearCodeSpace(); ClearCodeSpace(); m_clear_cache_asap = false; diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp index ea921817b8..d1cfe7aac9 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBackpatch.cpp @@ -65,14 +65,21 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx) return false; } - auto it = registersInUseAtLoc.find(codePtr); - if (it == registersInUseAtLoc.end()) + auto pc_it = jit->js.pcAtLoc.find(codePtr); + if (pc_it == jit->js.pcAtLoc.end()) { - PanicAlert("BackPatch: no register use entry for address %p", codePtr); + PanicAlert("BackPatch: no pc entry for address %p", codePtr); + return nullptr; + } + u32 pc = pc_it->second; + + auto reguse_it = jit->js.registersInUseAtLoc.find(pc); + if (reguse_it == jit->js.registersInUseAtLoc.end()) + { + PanicAlert("BackPatch: no register use entry for PC %x", pc); return false; } - - u32 registersInUse = it->second; + u32 registersInUse = reguse_it->second; if (!info.isMemoryWrite) { @@ -97,16 +104,7 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx) } else { - // TODO: special case FIFO writes. Also, support 32-bit mode. - it = pcAtLoc.find(codePtr); - if (it == pcAtLoc.end()) - { - PanicAlert("BackPatch: no pc entry for address %p", codePtr); - return nullptr; - } - - u32 pc = it->second; - + // TODO: special case FIFO writes u8 *start; if (info.byteSwap || info.hasImmediate) { diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index 4c3cd2562b..7332ecd105 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -98,6 +98,8 @@ protected: JitBlock *curBlock; std::unordered_set fifoWriteAddresses; + std::unordered_map registersInUseAtLoc; + std::unordered_map pcAtLoc; }; PPCAnalyst::CodeBlock code_block; diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index c577ddaf3d..7080f9b137 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -359,14 +359,19 @@ using namespace Gen; block_map.erase(it1, it2); } - // If the code was actually modified, we need to clear the relevant entries from the - // FIFO write address cache, so we don't end up with FIFO checks in places they shouldn't - // be (this can clobber flags, and thus break any optimization that relies on flags - // being in the right place between instructions). if (!forced) { for (u32 i = address; i < address + length; i += 4) + { + // If the code was actually modified, we need to clear the relevant entries from the + // FIFO write address cache, so we don't end up with FIFO checks in places they shouldn't + // be (this can clobber flags, and thus break any optimization that relies on flags + // being in the right place between instructions). jit->js.fifoWriteAddresses.erase(i); + // We use these entries to determine whether there's a fastmem fault at this location, + // so clear it since the block is being replaced. + jit->js.registersInUseAtLoc.erase(i); + } } } } diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp index 283ea6ea2e..9d5a0ac707 100644 --- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp @@ -299,7 +299,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem && !opAddress.IsImm() && - !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) + !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) && + jit->js.registersInUseAtLoc.find(jit->js.compilerPC) == jit->js.registersInUseAtLoc.end() #ifdef ENABLE_MEM_CHECK && !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging #endif @@ -307,7 +308,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, { u8 *mov = UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend); - registersInUseAtLoc[mov] = registersInUse; + jit->js.pcAtLoc[mov] = jit->js.compilerPC; + jit->js.registersInUseAtLoc[jit->js.compilerPC] = registersInUse; } else { @@ -483,7 +485,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bMMU && SConfig::GetInstance().m_LocalCoreStartupParameter.bFastmem && !(flags & SAFE_LOADSTORE_NO_FASTMEM) && - (reg_value.IsImm() || !(flags & SAFE_LOADSTORE_NO_SWAP)) + (reg_value.IsImm() || !(flags & SAFE_LOADSTORE_NO_SWAP)) && + jit->js.registersInUseAtLoc.find(jit->js.compilerPC) == jit->js.registersInUseAtLoc.end() #ifdef ENABLE_MEM_CHECK && !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging #endif @@ -497,8 +500,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces NOP(padding); } - registersInUseAtLoc[mov] = registersInUse; - pcAtLoc[mov] = jit->js.compilerPC; + jit->js.pcAtLoc[mov] = jit->js.compilerPC; + jit->js.registersInUseAtLoc[jit->js.compilerPC] = registersInUse; return; } diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h index e46621067a..709ddc7343 100644 --- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h +++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.h @@ -131,7 +131,4 @@ public: void ConvertSingleToDouble(Gen::X64Reg dst, Gen::X64Reg src, bool src_is_gpr = false); void ConvertDoubleToSingle(Gen::X64Reg dst, Gen::X64Reg src); void SetFPRF(Gen::X64Reg xmm); -protected: - std::unordered_map registersInUseAtLoc; - std::unordered_map pcAtLoc; };